Skip to content

Commit 9403f10

Browse files
committed
fix(mcp): treat 404 as 405 for streamable-http SSE GET
Servers that answer the SDK's optional SSE-stream GET with 404 instead of the spec-mandated 405 made the whole connection fail with "Failed to open SSE stream: Not Found". Ports cline/cline#8321 Refs modelcontextprotocol/typescript-sdk#1150 LLM: Done with Claude Opus 5 in Zoo Code.
1 parent ca9b60f commit 9403f10

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

src/services/mcp/McpHub.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,35 @@ const McpSettingsSchema = z.object({
152152
mcpServers: z.record(ServerConfigSchema),
153153
})
154154

155+
/**
156+
* `fetch` wrapper for Streamable HTTP MCP transports that reports a `404` answer to a
157+
* `GET` request as `405 Method Not Allowed`.
158+
*
159+
* The MCP SDK opens the optional server-to-client SSE stream with a `GET` request. Per the
160+
* MCP spec a server that does not offer such a stream must answer `405`, which the SDK
161+
* treats as "no SSE stream available" and silently ignores. Servers answering `404`
162+
* instead make the SDK fail the whole connection with
163+
* `Failed to open SSE stream: Not Found`, even though POST-based requests work fine, so
164+
* the status is normalized here.
165+
*
166+
* Any other request method or status code is passed through untouched.
167+
*
168+
* See: https://github.com/modelcontextprotocol/typescript-sdk/issues/1150
169+
*/
170+
const streamableHttpFetch: typeof fetch = async (url, init) => {
171+
const response = await fetch(url, init)
172+
173+
if (init?.method?.toUpperCase() === "GET" && response.status === 404) {
174+
return new Response(response.body, {
175+
status: 405,
176+
statusText: "Method Not Allowed",
177+
headers: response.headers,
178+
})
179+
}
180+
181+
return response
182+
}
183+
155184
export class McpHub {
156185
private providerRef: WeakRef<ClineProvider>
157186
private disposables: vscode.Disposable[] = []
@@ -824,6 +853,7 @@ export class McpHub {
824853
transport = new StreamableHTTPClientTransport(new URL(configInjected.url), {
825854
authProvider,
826855
requestInit: { headers: configInjected.headers },
856+
fetch: streamableHttpFetch,
827857
})
828858

829859
// Set up Streamable HTTP specific error handling

0 commit comments

Comments
 (0)