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:
commit
1977e2a597
1 changed files with 24 additions and 5 deletions
|
|
@ -17,7 +17,10 @@ import {
|
||||||
StdioClientTransport,
|
StdioClientTransport,
|
||||||
getDefaultEnvironment,
|
getDefaultEnvironment,
|
||||||
} from "@modelcontextprotocol/sdk/client/stdio.js";
|
} 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 { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
||||||
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
||||||
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.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.
|
// Function to get HTTP headers.
|
||||||
const getHttpHeaders = (req: express.Request): Record<string, string> => {
|
const getHttpHeaders = (req: express.Request): Record<string, string> => {
|
||||||
const headers: Record<string, string> = {};
|
const headers: Record<string, string> = {};
|
||||||
|
|
@ -508,10 +527,10 @@ app.post(
|
||||||
req.body,
|
req.body,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof SseError && error.code === 401) {
|
if (is401Error(error)) {
|
||||||
console.error(
|
console.error(
|
||||||
"Received 401 Unauthorized from MCP server:",
|
"Received 401 Unauthorized from MCP server:",
|
||||||
error.message,
|
error instanceof Error ? error.message : error,
|
||||||
);
|
);
|
||||||
res.status(401).json(error);
|
res.status(401).json(error);
|
||||||
return;
|
return;
|
||||||
|
|
@ -649,7 +668,7 @@ app.get(
|
||||||
transportToServer: serverTransport,
|
transportToServer: serverTransport,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof SseError && error.code === 401) {
|
if (is401Error(error)) {
|
||||||
console.error(
|
console.error(
|
||||||
"Received 401 Unauthorized from MCP server. Authentication failure.",
|
"Received 401 Unauthorized from MCP server. Authentication failure.",
|
||||||
);
|
);
|
||||||
|
|
@ -695,7 +714,7 @@ app.get(
|
||||||
transportToServer: serverTransport,
|
transportToServer: serverTransport,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof SseError && error.code === 401) {
|
if (is401Error(error)) {
|
||||||
console.error(
|
console.error(
|
||||||
"Received 401 Unauthorized from MCP server. Authentication failure.",
|
"Received 401 Unauthorized from MCP server. Authentication failure.",
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue