Merge pull request #966 from olaservo/fix/streamable-http-401-handling

fix: detect 401 errors from StreamableHTTP transport for OAuth flow
This commit is contained in:
Cliff Hall 2025-12-13 18:04:34 -05:00 • committed by GitHub
commit 1977e2a597
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -17,7 +17,10 @@ import {
StdioClientTransport,
getDefaultEnvironment,
} from "@modelcontextprotocol/sdk/client/stdio.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import {
StreamableHTTPClientTransport,
StreamableHTTPError,
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
@ -44,6 +47,22 @@ const { values } = parseArgs({
},
});
/**
* Helper function to detect 401 Unauthorized errors from various transport types.
* StreamableHTTPClientTransport throws a generic Error with "HTTP 401" in the message
* when there's no authProvider configured, while SSEClientTransport throws SseError.
*/
const is401Error = (error: unknown): boolean => {
if (error instanceof SseError && error.code === 401) return true;
if (error instanceof StreamableHTTPError && error.code === 401) return true;
if (
error instanceof Error &&
(error.message.includes("HTTP 401") || error.message.includes("(401)"))
)
return true;
return false;
};
// Function to get HTTP headers.
const getHttpHeaders = (req: express.Request): Record<string, string> => {
const headers: Record<string, string> = {};
@ -508,10 +527,10 @@ app.post(
req.body,
);
} catch (error) {
if (error instanceof SseError && error.code === 401) {
if (is401Error(error)) {
console.error(
"Received 401 Unauthorized from MCP server:",
error.message,
error instanceof Error ? error.message : error,
);
res.status(401).json(error);
return;
@ -649,7 +668,7 @@ app.get(
transportToServer: serverTransport,
});
} catch (error) {
if (error instanceof SseError && error.code === 401) {
if (is401Error(error)) {
console.error(
"Received 401 Unauthorized from MCP server. Authentication failure.",
);
@ -695,7 +714,7 @@ app.get(
transportToServer: serverTransport,
});
} catch (error) {
if (error instanceof SseError && error.code === 401) {
if (is401Error(error)) {
console.error(
"Received 401 Unauthorized from MCP server. Authentication failure.",
);