Skip to content

Commit d50aa6a

Browse files
Merge branch 'main' into tool-search
2 parents 00a4973 + 01caa53 commit d50aa6a

File tree

6 files changed

+176
-19
lines changed

6 files changed

+176
-19
lines changed

cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector-cli",
3-
"version": "0.16.7",
3+
"version": "0.16.8",
44
"description": "CLI for the Model Context Protocol inspector",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector-client",
3-
"version": "0.16.7",
3+
"version": "0.16.8",
44
"description": "Client-side application for the Model Context Protocol inspector",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",

package-lock.json

Lines changed: 100 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector",
3-
"version": "0.16.7",
3+
"version": "0.16.8",
44
"description": "Model Context Protocol inspector",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",
@@ -47,11 +47,12 @@
4747
"check-version": "node scripts/check-version-consistency.js"
4848
},
4949
"dependencies": {
50-
"@modelcontextprotocol/inspector-cli": "^0.16.7",
51-
"@modelcontextprotocol/inspector-client": "^0.16.7",
52-
"@modelcontextprotocol/inspector-server": "^0.16.7",
50+
"@modelcontextprotocol/inspector-cli": "^0.16.8",
51+
"@modelcontextprotocol/inspector-client": "^0.16.8",
52+
"@modelcontextprotocol/inspector-server": "^0.16.8",
5353
"@modelcontextprotocol/sdk": "^1.18.0",
5454
"concurrently": "^9.2.0",
55+
"node-fetch": "^3.3.2",
5556
"open": "^10.2.0",
5657
"shell-quote": "^1.8.3",
5758
"spawn-rx": "^5.1.2",

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector-server",
3-
"version": "0.16.7",
3+
"version": "0.16.8",
44
"description": "Server-side application for the Model Context Protocol inspector",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",

server/src/index.ts

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
import cors from "cors";
44
import { parseArgs } from "node:util";
55
import { parse as shellParseArgs } from "shell-quote";
6+
import nodeFetch, { Headers as NodeHeaders } from "node-fetch";
7+
8+
// Type-compatible wrappers for node-fetch to work with browser-style types
9+
const fetch = nodeFetch;
10+
const Headers = NodeHeaders;
611

712
import {
813
SSEClientTransport,
@@ -231,13 +236,37 @@ const authMiddleware = (
231236
next();
232237
};
233238

239+
/**
240+
* Converts a Node.js ReadableStream to a web-compatible ReadableStream
241+
* This is necessary for the EventSource polyfill which expects web streams
242+
*/
243+
const createWebReadableStream = (nodeStream: any): ReadableStream => {
244+
return new ReadableStream({
245+
start(controller) {
246+
nodeStream.on("data", (chunk: any) => {
247+
controller.enqueue(chunk);
248+
});
249+
nodeStream.on("end", () => {
250+
controller.close();
251+
});
252+
nodeStream.on("error", (err: any) => {
253+
controller.error(err);
254+
});
255+
},
256+
});
257+
};
258+
234259
/**
235260
* Creates a `fetch` function that merges dynamic session headers with the
236261
* headers from the actual request, ensuring that request-specific headers like
237-
* `Content-Type` are preserved.
262+
* `Content-Type` are preserved. For SSE requests, it also converts Node.js
263+
* streams to web-compatible streams.
238264
*/
239265
const createCustomFetch = (headerHolder: { headers: HeadersInit }) => {
240-
return (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
266+
return async (
267+
input: RequestInfo | URL,
268+
init?: RequestInit,
269+
): Promise<Response> => {
241270
// Determine the headers from the original request/init.
242271
// The SDK may pass a Request object or a URL and an init object.
243272
const originalHeaders =
@@ -252,8 +281,43 @@ const createCustomFetch = (headerHolder: { headers: HeadersInit }) => {
252281
finalHeaders.set(key, value);
253282
});
254283

255-
// This works for both `fetch(url, init)` and `fetch(request)` style calls.
256-
return fetch(input, { ...init, headers: finalHeaders });
284+
// Convert Headers to a plain object for node-fetch compatibility
285+
const headersObject: Record<string, string> = {};
286+
finalHeaders.forEach((value, key) => {
287+
headersObject[key] = value;
288+
});
289+
290+
// Get the response from node-fetch (cast input and init to handle type differences)
291+
const response = await fetch(
292+
input as any,
293+
{ ...init, headers: headersObject } as any,
294+
);
295+
296+
// Check if this is an SSE request by looking at the Accept header
297+
const acceptHeader = finalHeaders.get("Accept");
298+
const isSSE = acceptHeader?.includes("text/event-stream");
299+
300+
if (isSSE && response.body) {
301+
// For SSE requests, we need to convert the Node.js stream to a web ReadableStream
302+
// because the EventSource polyfill expects web-compatible streams
303+
const webStream = createWebReadableStream(response.body);
304+
305+
// Create a new response with the web-compatible stream
306+
// Convert node-fetch headers to plain object for web Response compatibility
307+
const responseHeaders: Record<string, string> = {};
308+
response.headers.forEach((value: string, key: string) => {
309+
responseHeaders[key] = value;
310+
});
311+
312+
return new Response(webStream, {
313+
status: response.status,
314+
statusText: response.statusText,
315+
headers: responseHeaders,
316+
}) as Response;
317+
}
318+
319+
// For non-SSE requests, return the response as-is (cast to handle type differences)
320+
return response as unknown as Response;
257321
};
258322
};
259323

0 commit comments

Comments
 (0)