From 9bfcddf853058166038b65b283cc9bc4e989bcb3 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Tue, 27 May 2025 21:02:12 +0300 Subject: [PATCH 1/3] passthrough original incoming http headers to callbacks in extra --- package-lock.json | 4 ++-- src/server/sse.ts | 8 ++++---- src/shared/protocol.ts | 9 ++++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40bad9fe..1a9a8f45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@modelcontextprotocol/sdk", - "version": "1.11.4", + "version": "1.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@modelcontextprotocol/sdk", - "version": "1.11.4", + "version": "1.12.0", "license": "MIT", "dependencies": { "ajv": "^6.12.6", diff --git a/src/server/sse.ts b/src/server/sse.ts index 03f6fefc..fe39128e 100644 --- a/src/server/sse.ts +++ b/src/server/sse.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import { IncomingMessage, ServerResponse } from "node:http"; +import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "node:http"; import { Transport } from "../shared/transport.js"; import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js"; import getRawBody from "raw-body"; @@ -20,7 +20,7 @@ export class SSEServerTransport implements Transport { onclose?: () => void; onerror?: (error: Error) => void; - onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo }) => void; + onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo, requestHeaders?: IncomingHttpHeaders }) => void; /** * Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`. @@ -106,7 +106,7 @@ export class SSEServerTransport implements Transport { } try { - await this.handleMessage(typeof body === 'string' ? JSON.parse(body) : body, { authInfo }); + await this.handleMessage(typeof body === 'string' ? JSON.parse(body) : body, { authInfo, requestHeaders: req.headers }); } catch { res.writeHead(400).end(`Invalid message: ${body}`); return; @@ -118,7 +118,7 @@ export class SSEServerTransport implements Transport { /** * Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST. */ - async handleMessage(message: unknown, extra?: { authInfo?: AuthInfo }): Promise { + async handleMessage(message: unknown, extra?: { authInfo?: AuthInfo, requestHeaders?: IncomingHttpHeaders }): Promise { let parsedMessage: JSONRPCMessage; try { parsedMessage = JSONRPCMessageSchema.parse(message); diff --git a/src/shared/protocol.ts b/src/shared/protocol.ts index 4694929d..0e3708f7 100644 --- a/src/shared/protocol.ts +++ b/src/shared/protocol.ts @@ -25,6 +25,7 @@ import { } from "../types.js"; import { Transport, TransportSendOptions } from "./transport.js"; import { AuthInfo } from "../server/auth/types.js"; +import { IncomingHttpHeaders } from "node:http"; /** * Callback for progress notifications. @@ -127,6 +128,11 @@ export type RequestHandlerExtra Date: Tue, 27 May 2025 21:53:21 +0300 Subject: [PATCH 2/3] passthrough original incoming http headers to callbacks in extra --- src/server/sse.ts | 2 +- src/shared/protocol.ts | 4 ++-- src/shared/transport.ts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/server/sse.ts b/src/server/sse.ts index fe39128e..0e69b5c8 100644 --- a/src/server/sse.ts +++ b/src/server/sse.ts @@ -118,7 +118,7 @@ export class SSEServerTransport implements Transport { /** * Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST. */ - async handleMessage(message: unknown, extra?: { authInfo?: AuthInfo, requestHeaders?: IncomingHttpHeaders }): Promise { + async handleMessage(message: unknown, extra?: { authInfo?: AuthInfo, requestHeaders: IncomingHttpHeaders }): Promise { let parsedMessage: JSONRPCMessage; try { parsedMessage = JSONRPCMessageSchema.parse(message); diff --git a/src/shared/protocol.ts b/src/shared/protocol.ts index 0e3708f7..7b0ff058 100644 --- a/src/shared/protocol.ts +++ b/src/shared/protocol.ts @@ -131,7 +131,7 @@ export type RequestHandlerExtra void; + onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo, requestHeaders?: IncomingHttpHeaders }) => void; /** * The session ID generated for this connection. From 7a2d9a92a9167a1cd02b13f03d5b6a41bb641d87 Mon Sep 17 00:00:00 2001 From: Konstantin Konstantinov Date: Tue, 27 May 2025 23:57:47 +0300 Subject: [PATCH 3/3] passthrough original incoming http headers to callbacks in extra --- src/server/streamableHttp.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/streamableHttp.ts b/src/server/streamableHttp.ts index dc99c306..39c40ed7 100644 --- a/src/server/streamableHttp.ts +++ b/src/server/streamableHttp.ts @@ -1,4 +1,4 @@ -import { IncomingMessage, ServerResponse } from "node:http"; +import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "node:http"; import { Transport } from "../shared/transport.js"; import { isInitializeRequest, isJSONRPCError, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema, RequestId } from "../types.js"; import getRawBody from "raw-body"; @@ -113,7 +113,7 @@ export class StreamableHTTPServerTransport implements Transport { sessionId?: string | undefined; onclose?: () => void; onerror?: (error: Error) => void; - onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo }) => void; + onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo, requestHeaders?: IncomingHttpHeaders }) => void; constructor(options: StreamableHTTPServerTransportOptions) { this.sessionIdGenerator = options.sessionIdGenerator; @@ -395,7 +395,7 @@ export class StreamableHTTPServerTransport implements Transport { // handle each message for (const message of messages) { - this.onmessage?.(message, { authInfo }); + this.onmessage?.(message, { authInfo, requestHeaders: req.headers }); } } else if (hasRequests) { // The default behavior is to use SSE streaming @@ -430,7 +430,7 @@ export class StreamableHTTPServerTransport implements Transport { // handle each message for (const message of messages) { - this.onmessage?.(message, { authInfo }); + this.onmessage?.(message, { authInfo, requestHeaders: req.headers }); } // The server SHOULD NOT close the SSE stream before sending all JSON-RPC responses // This will be handled by the send() method when responses are ready