Conversation
…. OAuth) Add an "Apply to All Requests" affordance that injects a configurable set of extra HTTP headers and/or query params into every outbound request to the target MCP server — not just the MCP transport POSTs, but also the OAuth auxiliary calls (protected-resource / authorization-server metadata discovery, dynamic client registration, and the token exchange). This unblocks connecting to MCP servers deployed behind a gateway that gates access with a header or query param (e.g. Vercel Deployment Protection's x-vercel-protection-bypass). Previously custom headers only reached the transport, so OAuth discovery/DCR/token requests hit the gateway's auth wall and the flow never learned the real authorization server. Implementation: - New shared fetch wrapper (client/src/lib/requestExtras.ts) that injects the extras in one place; threaded into the transport (direct mode) and into the SDK auth methods (fetchFn) so it works in both "Via Proxy" and direct modes. - Query params are embedded into the proxy `url=` target for proxy mode and appended to the URL for direct mode; header extras flow through the existing custom-header plumbing (forwarded by the proxy via x-custom-auth-headers). - OAuthCallback now builds the same proxy/extras-aware fetchFn for the token exchange, fixing the OAuth-bypasses-Via-Proxy gap (modelcontextprotocol#995). - UI: new ApplyToAllRequests section in the sidebar (masked values). - Headless: server CLI flags (--header, --query-param) and env vars (MCP_REQUEST_HEADERS, MCP_REQUEST_QUERY_PARAMS) surfaced via /config; the `mcp-inspector` launcher forwards them; the `--cli` invoker gains --query-param (appended to the server URL on every request). - Default behavior is unchanged when no extras are configured; no secrets logged. Tests: unit tests for the shared wrapper (transport + OAuth discovery/DCR/token injection and the no-op default) and the query-param type helpers, plus CLI integration tests asserting query-param injection reaches the server. Refs: modelcontextprotocol#879, modelcontextprotocol#995, modelcontextprotocol#752, modelcontextprotocol#817 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012FAFCf8AzpqyNF1oKZNGzh
12 tasks
Simplify the feature per review feedback: - Remove query-param support entirely. Headers alone cover the gateway-bypass use case (e.g. Vercel Deployment Protection accepts its bypass secret as a header), so the separate query-param list, plumbing, CLI/env flags, and tests are dropped. - Drop the separate "Apply to All Requests" header list (it duplicated Custom Headers). Instead, add a single "Also apply to OAuth requests" toggle beneath the existing Custom Headers. When on, the custom headers are injected into the OAuth auxiliary requests (metadata discovery, DCR, token exchange) in addition to the transport; when off (default), behavior is unchanged. - Replace the request-extras module with a focused header-only fetch wrapper (customHeaderFetch) threaded into the SDK auth methods, useConnection, AuthDebugger, and the OAuth callback route. - Headless: `--header` / MCP_REQUEST_HEADERS now feed the Custom Headers list and default the toggle on (opt out via MCP_APPLY_HEADERS_TO_ALL_REQUESTS=false), surfaced via GET /config. - README: document the toggle instead of a query param, and link Vercel's Protection Bypass for Automation docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012FAFCf8AzpqyNF1oKZNGzh
On a normal launch the server reports `defaultCustomHeaders: []` and `defaultApplyHeadersToAllRequests: false`. The client applied the boolean unconditionally, so after enabling the toggle and reloading it would render on (from localStorage) and then flip off once the /config fetch resolved — and the persistence effect wrote that `false` back, destroying the saved value. Only apply the headless header/toggle defaults when the server actually declares header defaults (i.e. --header / MCP_REQUEST_HEADERS were provided); otherwise leave the user's persisted headers and toggle untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012FAFCf8AzpqyNF1oKZNGzh
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an "Also apply to OAuth requests" toggle beneath Custom Headers so the configured headers are attached to the OAuth auxiliary calls too — not just the MCP transport. This lets the Inspector complete OAuth against an MCP server deployed behind a gateway that gates access with a header (the motivating case: Vercel Deployment Protection's Protection Bypass for Automation).
Type of Change
Changes Made
The problem: Custom Headers were only attached to the MCP transport requests. The OAuth auxiliary requests the SDK issues itself — protected-resource / authorization-server metadata discovery, dynamic client registration (
/register), and the token exchange (/token) — went out without the custom header and hit the gateway's auth wall, so discovery failed and OAuth never completed.The fix:
customHeaderFetch) threaded into the SDK's auth methods, so it works in both connection modes ("Via Proxy" and direct) and reaches the OAuth calls regardless of which layer issues them.OAuthCallbackwith the same header-aware fetch (and the proxy fetch, when "Via Proxy" is selected) that the rest of the OAuth flow already uses viacreateProxyFetch— that standalone route previously issued itsauth()call with the browser's default fetch, so neither the proxy nor the custom headers reached it.--header/MCP_REQUEST_HEADERSfeed the Custom Headers list and default the toggle on (opt out withMCP_APPLY_HEADERS_TO_ALL_REQUESTS=false), surfaced viaGET /config.Header values are masked in the UI and never logged. Existing headers always win over injected ones (never clobbers an
Authorization).Related Issues
mainnow routes OAuth through the proxy via Inspector client: Added proxy fetch for use by auth (to avoid CORS issues) modelcontextprotocol/inspector#1047'screateProxyFetch. This PR extends that same fetch to the one route it didn't cover — the post-redirectOAuthCallbacktoken exchange.Testing
Test Results and/or Instructions
Verified live against an MCP server behind Vercel Deployment Protection: with the bypass header configured and the toggle on, protected-resource discovery succeeds through the gateway, the client follows
authorization_serversto the (separate, unprotected) auth host, login completes.Unit tests cover the header-injecting fetch wrapper (OAuth discovery/DCR/token injection, existing-header precedence, enabled/blank filtering, and the no-op default). Full client suite + CLI suite pass; prettier + lint clean.
Checklist
npm run prettier-fix)Breaking Changes
None. The toggle defaults off, so existing flows are unaffected.
🤖 Generated with Claude Code