Skip to content

Clean up the MCP authentication simplification - #1347

Open
jiaenren wants to merge 1 commit into
jiaenr/mcp-reduce-required-valuesfrom
jiaenr/mcp-review-cleanup
Open

Clean up the MCP authentication simplification#1347
jiaenren wants to merge 1 commit into
jiaenr/mcp-reduce-required-valuesfrom
jiaenr/mcp-review-cleanup

Conversation

@jiaenren

@jiaenren jiaenren commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Last PR in the MCP authentication simplification stack.

Issue - None

A cleanup pass over the whole MCP auth stack, from a four-angle review (reuse, simplification, efficiency, altitude). No behaviour changes — the chart renders byte-identically with and without MCP enabled.

Dead state the simplification left behind

$mcpOidcProxyEnabled was an alias for $mcpEnabled, so its three {{- if }} blocks were nested inside the very condition they tested. $mcpMetadataUrl and $mcpBaseUrl lost their only reader when the www-authenticate mapper was deleted. mcp-service.yaml pre-declared six variables to hoist scope out of a conditional that no longer exists.

Credentials derived once per tool call instead of three times

Deleting RequestContextMiddleware left get_request_credentials() recomputing from scratch on every call — twice in protocol.py, then again per Gateway request in tool_requests.py. Each derivation is a regex over the bearer plus a scan of the request-ID header, on the request hot path. track_request_task() had become a contextmanager whose body was a bare yield; it is now bind_credentials(), which binds one derivation so later calls reuse it.

Mandatory configuration stops pretending to be optional

The five fields auth cannot start without were Optional-with-None plus a hand-rolled missing-field check — which then cost eight cast(str, ...) calls to undo. Declaring them required lets pydantic report them by name, and mypy now catches an incomplete construction at build time.

Tests

  • AnyTokenVerifier re-implemented FastMCP's shipped DebugTokenVerifier; the user_name threaded through the harness only ever wrote a claim nothing reads.
  • test_auth passed auth_enabled and oidc_access_token_jwks_url — both deleted by this stack and silently ignored, one contradicting an assertion five lines above it.
  • test_protocol hand-built its ASGI app, so it skipped the origin guard and body limit create_application installs.
  • Two create_autospec(Redis) calls cost ~1s to assert one awaited close.
  • Three BUILD targets kept a dep on //src/lib/utils:login they no longer use.

Render harness

It rendered the same release twice to slice one template out, and counted the MCP audience across the whole document — passing only because the other occurrence happens to carry a value: prefix. Now scoped to the audiences list, and negative-tested.

Docs

Deleting direct mode took four sections of the user appendix with it that were never about auth modes, orphaning the Safety and Limits bullets under an authentication lead-in. Restored. The deployment guide still showed oidcProxy.enabled and the secret paths the chart now derives; the README still told operators to keep replicas at 1, which the move to Redis had already made false. One RST table row had lost its cell marker, and an orphan line was left mid-page.

Comments are shortened throughout. _derive_fernet_key no longer calls derive_jwt_key private — it isn't; the real reason for pinning the derivation locally is that an upstream change would silently make stored state undecryptable.

Before / after

auth.py:                            360 → 321 lines
Envoy template:                   1,219 → 1,196 lines
mcp-service.yaml placeholders:        9 →   3
test/smoke/mcp_checks.py:           415 → 382 lines
credential derivations per tool call: 3 →   1

Everything above is behaviour-preserving: the rendered chart is byte-identical
with and without MCP enabled.

Verification

  • bazel test //src/service/mcp/... //test/smoke/... — 76/76 pass
  • render-tests.sh — pass; MCP and non-MCP renders byte-identical to before
  • Negative-tested the audience assertion by making the append unconditional and confirming the harness fails

🤖 Generated with Claude Code

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@jiaenren
jiaenren requested a review from a team as a code owner August 28, 2026 06:25
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0ac088b2-6372-44f9-a756-4466d17350b2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

A cleanup pass over the whole MCP auth stack. No behaviour changes: the
chart renders byte-identically, with and without MCP enabled.

Dead state. $mcpOidcProxyEnabled was an alias for $mcpEnabled, so its three
conditionals were nested inside the condition they tested. $mcpMetadataUrl
and $mcpBaseUrl lost their only reader when the www-authenticate mapper was
deleted. mcp-service.yaml pre-declared six variables to hoist scope out of a
conditional that no longer exists.

Credentials are derived once per tool call instead of three times. Deleting
RequestContextMiddleware left get_request_credentials() recomputing from
scratch on every call -- twice in protocol.py and again per Gateway request
in tool_requests.py -- each one a regex over the bearer plus a scan of the
request-ID header. track_request_task() had become a contextmanager whose
body was a bare yield; it now binds the derivation so later calls reuse it.

Mandatory configuration stops pretending to be optional. The five fields
auth cannot start without were Optional-with-None plus a hand-rolled
missing-field check, which cost eight casts to undo. Declaring them required
lets pydantic report them, and mypy now catches an incomplete construction.

Tests. AnyTokenVerifier re-implemented FastMCP's DebugTokenVerifier, and the
user_name it threaded through the harness only ever wrote a claim nothing
reads. test_auth passed auth_enabled and oidc_access_token_jwks_url, both
deleted by this stack and silently ignored, one of them contradicting an
assertion five lines above. test_protocol hand-built its ASGI app, so it
skipped the origin guard and body limit that create_application installs.
Two create_autospec(Redis) calls cost ~1s to assert one awaited close.
Three BUILD targets kept a dep on //src/lib/utils:login they no longer use.

The render harness rendered the same release twice to slice one template out,
and counted the MCP audience across the whole document -- passing only
because the other occurrence happens to carry a value: prefix. It is now
scoped to the audiences list, and negative-tested.

Docs. Deleting direct mode took four sections of the user appendix with it
that were never about auth modes, orphaning the Safety and Limits bullets
under an authentication lead-in; they are restored. The deployment guide
still showed oidcProxy.enabled and the secret paths the chart now derives,
and the README told operators to keep replicas at 1, which the move to Redis
had already made false. Two RST tables were left malformed.

Comments are shortened throughout, and _derive_fernet_key no longer calls
derive_jwt_key private -- it is not; the real reason for pinning the
derivation locally is that an upstream change would make stored state
undecryptable.

Verification
- bazel test //src/service/mcp/... //test/smoke/... -- 76/76 pass
- render-tests.sh -- pass; MCP and non-MCP renders byte-identical to before
- negative-tested the audience assertion by making the append unconditional

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jiaenren
jiaenren force-pushed the jiaenr/mcp-review-cleanup branch from 34111bc to dcd3127 Compare August 31, 2026 21:52
@jiaenren jiaenren changed the title Remove what the simplification left behind Clean up the MCP authentication simplification Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant