From 59bbaba6a2159fb8c9fc8e9664375f121ed2bbf2 Mon Sep 17 00:00:00 2001 From: Luca Moretti Date: Fri, 20 Feb 2026 08:12:45 +0000 Subject: [PATCH] fix: exclude x-custom-auth-headers from direct connections The x-custom-auth-headers meta-header is a proxy implementation detail used by the inspector proxy server to know which custom headers to forward. When connecting directly to an MCP server, this header should not be sent because: 1. MCP servers don't expect it and won't include it in their Access-Control-Allow-Headers CORS response 2. This causes the browser to block the request during CORS preflight Fixes #1100 --- .../hooks/__tests__/useConnection.test.tsx | 29 +++++++++++++++++++ client/src/lib/hooks/useConnection.ts | 7 +++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/client/src/lib/hooks/__tests__/useConnection.test.tsx b/client/src/lib/hooks/__tests__/useConnection.test.tsx index 4907a085b..7c6d983ec 100644 --- a/client/src/lib/hooks/__tests__/useConnection.test.tsx +++ b/client/src/lib/hooks/__tests__/useConnection.test.tsx @@ -1384,6 +1384,35 @@ describe("useConnection", () => { expect(mockSSETransport.url?.toString()).toBe("http://localhost:8080/"); }); + test("does not send x-custom-auth-headers for direct connections", async () => { + const customHeaders: CustomHeaders = [ + { name: "Authorization", value: "Bearer token123", enabled: true }, + { name: "X-Tenant-ID", value: "acme-inc", enabled: true }, + ]; + + const directPropsWithHeaders = { + ...defaultProps, + connectionType: "direct" as const, + customHeaders, + }; + + const { result } = renderHook(() => + useConnection(directPropsWithHeaders), + ); + + await act(async () => { + await result.current.connect(); + }); + + const headers = mockSSETransport.options?.requestInit?.headers; + // Custom headers should still be sent + expect(headers).toHaveProperty("Authorization", "Bearer token123"); + expect(headers).toHaveProperty("X-Tenant-ID", "acme-inc"); + // But the x-custom-auth-headers meta-header should NOT be sent for direct connections + // because MCP servers don't expect it and it breaks CORS preflight + expect(headers).not.toHaveProperty("x-custom-auth-headers"); + }); + test("uses proxy server URL when connectionType is 'proxy'", async () => { const proxyProps = { ...defaultProps, diff --git a/client/src/lib/hooks/useConnection.ts b/client/src/lib/hooks/useConnection.ts index e14d1037f..f4e06a0db 100644 --- a/client/src/lib/hooks/useConnection.ts +++ b/client/src/lib/hooks/useConnection.ts @@ -558,8 +558,11 @@ export function useConnection({ } }); - // Add custom header names as a special request header for server processing - if (customHeaderNames.length > 0) { + // Add custom header names as a special request header for proxy server processing. + // Only include this meta-header for proxied connections — direct connections send + // headers straight to the MCP server, which won't include x-custom-auth-headers + // in its Access-Control-Allow-Headers, breaking CORS preflight checks. + if (customHeaderNames.length > 0 && connectionType !== "direct") { headers["x-custom-auth-headers"] = JSON.stringify(customHeaderNames); }