Skip to content

Commit 1977e2a

Browse files
authored
Merge pull request #966 from olaservo/fix/streamable-http-401-handling
fix: detect 401 errors from StreamableHTTP transport for OAuth flow
2 parents 8ea530c + d1fcbd2 commit 1977e2a

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

server/src/index.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import {
1717
StdioClientTransport,
1818
getDefaultEnvironment,
1919
} from "@modelcontextprotocol/sdk/client/stdio.js";
20-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
20+
import {
21+
StreamableHTTPClientTransport,
22+
StreamableHTTPError,
23+
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2124
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2225
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
2326
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
@@ -44,6 +47,22 @@ const { values } = parseArgs({
4447
},
4548
});
4649

50+
/**
51+
* Helper function to detect 401 Unauthorized errors from various transport types.
52+
* StreamableHTTPClientTransport throws a generic Error with "HTTP 401" in the message
53+
* when there's no authProvider configured, while SSEClientTransport throws SseError.
54+
*/
55+
const is401Error = (error: unknown): boolean => {
56+
if (error instanceof SseError && error.code === 401) return true;
57+
if (error instanceof StreamableHTTPError && error.code === 401) return true;
58+
if (
59+
error instanceof Error &&
60+
(error.message.includes("HTTP 401") || error.message.includes("(401)"))
61+
)
62+
return true;
63+
return false;
64+
};
65+
4766
// Function to get HTTP headers.
4867
const getHttpHeaders = (req: express.Request): Record<string, string> => {
4968
const headers: Record<string, string> = {};
@@ -508,10 +527,10 @@ app.post(
508527
req.body,
509528
);
510529
} catch (error) {
511-
if (error instanceof SseError && error.code === 401) {
530+
if (is401Error(error)) {
512531
console.error(
513532
"Received 401 Unauthorized from MCP server:",
514-
error.message,
533+
error instanceof Error ? error.message : error,
515534
);
516535
res.status(401).json(error);
517536
return;
@@ -649,7 +668,7 @@ app.get(
649668
transportToServer: serverTransport,
650669
});
651670
} catch (error) {
652-
if (error instanceof SseError && error.code === 401) {
671+
if (is401Error(error)) {
653672
console.error(
654673
"Received 401 Unauthorized from MCP server. Authentication failure.",
655674
);
@@ -695,7 +714,7 @@ app.get(
695714
transportToServer: serverTransport,
696715
});
697716
} catch (error) {
698-
if (error instanceof SseError && error.code === 401) {
717+
if (is401Error(error)) {
699718
console.error(
700719
"Received 401 Unauthorized from MCP server. Authentication failure.",
701720
);

0 commit comments

Comments
 (0)