fix(mcp): preserve headers during auth and debug (#31802)

This commit is contained in:
Aiden Cline 2026-06-10 23:12:02 -05:00 committed by GitHub
commit bf05e8a122
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 15 additions and 5 deletions

View file

@ -744,6 +744,7 @@ export const McpDebugCommand = effectCmd({
const response = await fetch(serverConfig.url, { const response = await fetch(serverConfig.url, {
method: "POST", method: "POST",
headers: { headers: {
...serverConfig.headers,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json, text/event-stream", Accept: "application/json, text/event-stream",
}, },
@ -792,6 +793,7 @@ export const McpDebugCommand = effectCmd({
// Try creating transport with auth provider to trigger discovery // Try creating transport with auth provider to trigger discovery
const transport = new StreamableHTTPClientTransport(new URL(serverConfig.url), { const transport = new StreamableHTTPClientTransport(new URL(serverConfig.url), {
authProvider, authProvider,
requestInit: serverConfig.headers ? { headers: serverConfig.headers } : undefined,
}) })
try { try {

View file

@ -741,7 +741,10 @@ export const layer = Layer.effect(
auth, auth,
) )
const transport = new StreamableHTTPClientTransport(url, { authProvider }) const transport = new StreamableHTTPClientTransport(url, {
authProvider,
requestInit: mcpConfig.headers ? { headers: mcpConfig.headers } : undefined,
})
return yield* Effect.tryPromise({ return yield* Effect.tryPromise({
try: () => { try: () => {

View file

@ -38,7 +38,7 @@ class MockUnauthorizedError extends Error {
const transportCalls: Array<{ const transportCalls: Array<{
type: "streamable" | "sse" type: "streamable" | "sse"
url: string url: string
options: { authProvider?: unknown } options: { authProvider?: unknown; requestInit?: RequestInit }
}> = [] }> = []
// Mock the transport constructors // Mock the transport constructors
@ -46,7 +46,10 @@ void mock.module("@modelcontextprotocol/sdk/client/streamableHttp.js", () => ({
StreamableHTTPClientTransport: class MockStreamableHTTP { StreamableHTTPClientTransport: class MockStreamableHTTP {
url: string url: string
authProvider: { redirectToAuthorization?: (url: URL) => Promise<void> } | undefined authProvider: { redirectToAuthorization?: (url: URL) => Promise<void> } | undefined
constructor(url: URL, options?: { authProvider?: { redirectToAuthorization?: (url: URL) => Promise<void> } }) { constructor(
url: URL,
options?: { authProvider?: { redirectToAuthorization?: (url: URL) => Promise<void> }; requestInit?: RequestInit },
) {
this.url = url.toString() this.url = url.toString()
this.authProvider = options?.authProvider this.authProvider = options?.authProvider
transportCalls.push({ transportCalls.push({
@ -127,11 +130,12 @@ const mcpTest = testEffect(
) )
const service = MCP.Service as unknown as Effect.Effect<MCPNS.Interface, never, never> const service = MCP.Service as unknown as Effect.Effect<MCPNS.Interface, never, never>
const config = (name: string) => ({ const config = (name: string, headers?: Record<string, string>) => ({
mcp: { mcp: {
[name]: { [name]: {
type: "remote" as const, type: "remote" as const,
url: "https://example.com/mcp", url: "https://example.com/mcp",
headers,
}, },
}, },
}) })
@ -227,6 +231,7 @@ mcpTest.instance(
expect(failure).toEqual(Option.none()) expect(failure).toEqual(Option.none())
expect(typeof url).toBe("string") expect(typeof url).toBe("string")
expect(url).toContain("https://") expect(url).toContain("https://")
expect(transportCalls.at(-1)?.options.requestInit?.headers).toEqual({ "X-Custom-Header": "custom-value" })
}), }),
{ config: config("test-oauth-server-3") }, { config: config("test-oauth-server-3", { "X-Custom-Header": "custom-value" }) },
) )