Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions client/src/lib/hooks/__tests__/useConnection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 5 additions & 2 deletions client/src/lib/hooks/useConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down