From 13eb077329d3f8b7db5599da2fd9a5749c3ab386 Mon Sep 17 00:00:00 2001 From: ihrpr Date: Mon, 19 May 2025 18:29:42 +0100 Subject: [PATCH] fix auth conect --- client/src/App.tsx | 1 - client/src/lib/hooks/useConnection.ts | 33 +++++++++++++++++---------- package-lock.json | 9 -------- server/src/mcpProxy.ts | 17 +++++++++++++- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index c32f4840..68065e24 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -234,7 +234,6 @@ const App = () => { const onOAuthConnect = useCallback( (serverUrl: string) => { setSseUrl(serverUrl); - setTransportType("sse"); setIsAuthDebuggerVisible(false); void connectMcpServer(); }, diff --git a/client/src/lib/hooks/useConnection.ts b/client/src/lib/hooks/useConnection.ts index 4ced90e4..6d328033 100644 --- a/client/src/lib/hooks/useConnection.ts +++ b/client/src/lib/hooks/useConnection.ts @@ -250,8 +250,12 @@ export function useConnection({ }; const handleAuthError = async (error: unknown) => { - if (error instanceof SseError && error.code === 401) { - // Create a new auth provider with the current server URL + const is401Error = + (error instanceof SseError && error.code === 401) || + (error instanceof Error && error.message.includes('401')) || + (error instanceof Error && error.message.includes('Unauthorized')); + + if (is401Error) { const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl); const result = await auth(serverAuthProvider, { serverUrl: sseUrl }); @@ -330,7 +334,6 @@ export function useConnection({ mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`); mcpProxyServerUrl.searchParams.append("url", sseUrl); transportOptions = { - authProvider: serverAuthProvider, eventSourceInit: { fetch: ( url: string | URL | globalThis.Request, @@ -347,7 +350,6 @@ export function useConnection({ mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`); mcpProxyServerUrl.searchParams.append("url", sseUrl); transportOptions = { - authProvider: serverAuthProvider, eventSourceInit: { fetch: ( url: string | URL | globalThis.Request, @@ -375,9 +377,9 @@ export function useConnection({ const clientTransport = transportType === "streamable-http" ? new StreamableHTTPClientTransport(mcpProxyServerUrl as URL, { - sessionId: undefined, - ...transportOptions, - }) + sessionId: undefined, + ...transportOptions, + }) : new SSEClientTransport(mcpProxyServerUrl as URL, transportOptions); if (onNotification) { @@ -425,12 +427,19 @@ export function useConnection({ `Failed to connect to MCP Server via the MCP Inspector Proxy: ${mcpProxyServerUrl}:`, error, ); - const shouldRetry = await handleAuthError(error); - if (shouldRetry) { - return connect(undefined, retryCount + 1); - } - if (error instanceof SseError && error.code === 401) { + // Check for auth-related errors + const is401Error = + (error instanceof SseError && error.code === 401) || + (error instanceof Error && error.message.includes('401')) || + (error instanceof Error && error.message.includes('Unauthorized')); + + if (is401Error) { + console.log("Detected 401 error, attempting OAuth flow"); + const shouldRetry = await handleAuthError(error); + if (shouldRetry) { + return connect(undefined, retryCount + 1); + } // Don't set error state if we're about to redirect for auth return; } diff --git a/package-lock.json b/package-lock.json index 92e89f74..46beb270 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8407,15 +8407,6 @@ "node": "20 || >=22" } }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", diff --git a/server/src/mcpProxy.ts b/server/src/mcpProxy.ts index b93c0cdf..4e81fd59 100644 --- a/server/src/mcpProxy.ts +++ b/server/src/mcpProxy.ts @@ -1,4 +1,5 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; +import { isJSONRPCRequest } from "@modelcontextprotocol/sdk/types.js"; function onClientError(error: Error) { console.error("Error from inspector client:", error); @@ -19,7 +20,21 @@ export default function mcpProxy({ let transportToServerClosed = false; transportToClient.onmessage = (message) => { - transportToServer.send(message).catch(onServerError); + transportToServer.send(message).catch((error) => { + // Send error response back to client if it was a request (has id) and connection is still open + if (isJSONRPCRequest(message) && !transportToClientClosed) { + const errorResponse = { + jsonrpc: "2.0" as const, + id: message.id, + error: { + code: -32001, + message: error.message, + data: error + } + }; + transportToClient.send(errorResponse).catch(onClientError); + } + }); }; transportToServer.onmessage = (message) => {