New:Socket for Asana Is Now Available.Learn more
Get Started

@modelcontextprotocol/node

Package Overview
Dependencies
Maintainers
6
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@modelcontextprotocol/node - npm Package Compare versions

Comparing version
2.0.0-alpha.2
to
2.0.0-alpha.3
+2
-214
dist/index.d.mts

@@ -1,219 +0,7 @@

import { WebStandardStreamableHTTPServerTransportOptions } from "@modelcontextprotocol/server";
import { AuthInfo, JSONRPCMessage, MessageExtraInfo, RequestId, Transport, WebStandardStreamableHTTPServerTransportOptions } from "@modelcontextprotocol/server";
import { IncomingMessage, ServerResponse } from "node:http";
import * as z from "zod/v4";
//#region ../../core/src/types/schemas.d.ts
//#region src/streamableHttp.d.ts
/**
* A uniquely identifying ID for a request in JSON-RPC.
*/
declare const RequestIdSchema: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
declare const JSONRPCMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
method: z.ZodString;
params: z.ZodOptional<z.ZodObject<{
_meta: z.ZodOptional<z.ZodObject<{
/**
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
*/
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
/**
* If specified, this request is related to the provided task.
*/
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
taskId: z.ZodString;
}, z.core.$strip>>;
}, z.core.$loose>>;
}, z.core.$loose>>;
jsonrpc: z.ZodLiteral<"2.0">;
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
}, z.core.$strict>, z.ZodObject<{
method: z.ZodString;
params: z.ZodOptional<z.ZodObject<{
_meta: z.ZodOptional<z.ZodObject<{
/**
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
*/
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
/**
* If specified, this request is related to the provided task.
*/
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
taskId: z.ZodString;
}, z.core.$strip>>;
}, z.core.$loose>>;
}, z.core.$loose>>;
jsonrpc: z.ZodLiteral<"2.0">;
}, z.core.$strict>, z.ZodObject<{
jsonrpc: z.ZodLiteral<"2.0">;
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
result: z.ZodObject<{
/**
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
* for notes on `_meta` usage.
*/
_meta: z.ZodOptional<z.ZodObject<{
/**
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
*/
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
/**
* If specified, this request is related to the provided task.
*/
"io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
taskId: z.ZodString;
}, z.core.$strip>>;
}, z.core.$loose>>;
}, z.core.$loose>;
}, z.core.$strict>, z.ZodObject<{
jsonrpc: z.ZodLiteral<"2.0">;
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
error: z.ZodObject<{
code: z.ZodNumber;
message: z.ZodString;
data: z.ZodOptional<z.ZodUnknown>;
}, z.core.$strip>;
}, z.core.$strict>]>;
//#endregion
//#region ../../core/src/types/types.d.ts
type Primitive = string | number | boolean | bigint | null | undefined;
type Flatten<T$1> = T$1 extends Primitive ? T$1 : T$1 extends Array<infer U> ? Array<Flatten<U>> : T$1 extends Set<infer U> ? Set<Flatten<U>> : T$1 extends Map<infer K, infer V> ? Map<Flatten<K>, Flatten<V>> : T$1 extends object ? { [K in keyof T$1]: Flatten<T$1[K]> } : T$1;
type Infer<Schema extends z.ZodTypeAny> = Flatten<z.infer<Schema>>;
type RequestId = Infer<typeof RequestIdSchema>;
type JSONRPCMessage = Infer<typeof JSONRPCMessageSchema>;
/**
* Information about a validated access token, provided to request handlers.
*/
interface AuthInfo {
/**
* The access token.
*/
token: string;
/**
* The client ID associated with this token.
*/
clientId: string;
/**
* Scopes associated with this token.
*/
scopes: string[];
/**
* When the token expires (in seconds since epoch).
*/
expiresAt?: number;
/**
* The RFC 8707 resource server identifier for which this token is valid.
* If set, this MUST match the MCP server's resource identifier (minus hash fragment).
*/
resource?: URL;
/**
* Additional data associated with the token.
* This field should be used for any additional data that needs to be attached to the auth info.
*/
extra?: Record<string, unknown>;
}
/**
* Extra information about a message.
*/
interface MessageExtraInfo {
/**
* The original HTTP request.
*/
request?: globalThis.Request;
/**
* The authentication information.
*/
authInfo?: AuthInfo;
/**
* Callback to close the SSE stream for this request, triggering client reconnection.
* Only available when using {@linkcode @modelcontextprotocol/node!streamableHttp.NodeStreamableHTTPServerTransport | NodeStreamableHTTPServerTransport} with eventStore configured.
*/
closeSSEStream?: () => void;
/**
* Callback to close the standalone GET SSE stream, triggering client reconnection.
* Only available when using {@linkcode @modelcontextprotocol/node!streamableHttp.NodeStreamableHTTPServerTransport | NodeStreamableHTTPServerTransport} with eventStore configured.
*/
closeStandaloneSSEStream?: () => void;
}
//#endregion
//#region ../../core/src/shared/transport.d.ts
/**
* Options for sending a JSON-RPC message.
*/
type TransportSendOptions = {
/**
* If present, `relatedRequestId` is used to indicate to the transport which incoming request to associate this outgoing message with.
*/
relatedRequestId?: RequestId | undefined;
/**
* The resumption token used to continue long-running requests that were interrupted.
*
* This allows clients to reconnect and continue from where they left off, if supported by the transport.
*/
resumptionToken?: string | undefined;
/**
* A callback that is invoked when the resumption token changes, if supported by the transport.
*
* This allows clients to persist the latest token for potential reconnection.
*/
onresumptiontoken?: ((token: string) => void) | undefined;
};
/**
* Describes the minimal contract for an MCP transport that a client or server can communicate over.
*/
interface Transport {
/**
* Starts processing messages on the transport, including any connection steps that might need to be taken.
*
* This method should only be called after callbacks are installed, or else messages may be lost.
*
* NOTE: This method should not be called explicitly when using {@linkcode @modelcontextprotocol/client!client/client.Client | Client} or {@linkcode @modelcontextprotocol/server!server/server.Server | Server} classes, as they will implicitly call {@linkcode Transport.start | start()}.
*/
start(): Promise<void>;
/**
* Sends a JSON-RPC message (request or response).
*
* If present, `relatedRequestId` is used to indicate to the transport which incoming request to associate this outgoing message with.
*/
send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void>;
/**
* Closes the connection.
*/
close(): Promise<void>;
/**
* Callback for when the connection is closed for any reason.
*
* This should be invoked when {@linkcode Transport.close | close()} is called as well.
*/
onclose?: (() => void) | undefined;
/**
* Callback for when an error occurs.
*
* Note that errors are not necessarily fatal; they are used for reporting any kind of exceptional condition out of band.
*/
onerror?: ((error: Error) => void) | undefined;
/**
* Callback for when a message (request or response) is received over the connection.
*
* Includes the {@linkcode MessageExtraInfo.request | request} and {@linkcode MessageExtraInfo.authInfo | authInfo} if the transport is authenticated.
*
* The {@linkcode MessageExtraInfo.request | request} can be used to get the original request information (headers, etc.)
*/
onmessage?: (<T$1 extends JSONRPCMessage>(message: T$1, extra?: MessageExtraInfo) => void) | undefined;
/**
* The session ID generated for this connection.
*/
sessionId?: string | undefined;
/**
* Sets the protocol version used for the connection (called when the initialize response is received).
*/
setProtocolVersion?: ((version: string) => void) | undefined;
/**
* Sets the supported protocol versions for header validation (called during connect).
* This allows the server to pass its supported versions to the transport.
*/
setSupportedProtocolVersions?: ((versions: string[]) => void) | undefined;
}
//#endregion
//#region src/streamableHttp.d.ts
/**
* Configuration options for {@linkcode NodeStreamableHTTPServerTransport}

@@ -220,0 +8,0 @@ *

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.mts","names":[],"sources":["../../../core/src/types/schemas.ts","../../../core/src/types/types.ts","../../../core/src/shared/transport.ts","../src/streamableHttp.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AG+ImB,cHtBN,eGsBM,EHtBS,CAAA,CAAA,QGsBT,CAAA,SAAA,CHtBS,CAAA,CAAA,SGsBT,EHtBS,CAAA,CAAA,SGsBT,CAAA,CAAA;cHoCN,sBAAoB,CAAA,CAAA,mBAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCT5B,SAAA;KACA,eAAa,YAAU,YACtB,MACA,YAAU,iBACR,MAAM,QAAQ,MACd,YAAU,eACR,IAAI,QAAQ,MACZ,YAAU,wBACR,IAAI,QAAQ,IAAI,QAAQ,MACxB,mCACgB,MAAI,QAAQ,IAAE,QAC5B;KAET,qBAAqB,CAAA,CAAE,cAAc,QAAQ,CAAA,CAAE,MAAM;KAU9C,SAAA,GAAY,aAAa;KAMzB,cAAA,GAAiB,aAAa;;;;UAiNzB,QAAA;;;;;;;;;;;;;;;;;;;;;aAyBF;;;;;UAMH;;;;;UA+EK,gBAAA;;;;YAIH,UAAA,CAAW;;;;aAKV;;;;;;;;;;;;;;;;;KC7dH,oBAAA;;;;qBAIW;;;;;;;;;;;;;;;;;UAmBN,SAAA;;;;;;;;WAQJ;;;;;;gBAOK,0BAA0B,uBAAuB;;;;WAKtD;;;;;;;;;;;;qBAcU;;;;;;;;4BASK,yBAAyB,aAAW;;;;EF+D/B,SAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA;;;;ECT5B;AAAS;;;EAER,4BAAA,CAAA,EAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,EAAA,GAAA,IAAA,CAAA,GAAA,SAAA;;;;;;;;;KEvJM,oCAAA,GAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6CtC,iCAAA,YAA6C;;;;wBAMjC;;;;;;;;;;;;;gCAyCS;0BAIN;;;;EH8DK,IAAA,SAAA,CAAA,OAAA,EAAA,CAAA,CAAA,OAAA,EGvDK,cHuDL,EAAA,KAAA,CAAA,EGvD6B,gBHuD7B,EAAA,GAAA,IAAA,CAAA,GAAA,SAAA;EAAA,IAAA,SAAA,CAAA,CAAA,EAAA,CAAA,CAAA,OAAA,EGnDD,cHmDC,EAAA,KAAA,CAAA,EGnDuB,gBHmDvB,EAAA,GAAA,IAAA,CAAA,GAAA,SAAA;;;;ACX2F;EAGvH,KAAA,CAAA,CAAA,EEnCc,OFmCP,CAAA,IAAA,CAAA;EAAM;;;EAEZ,KAAA,CAAA,CAAA,EE9Ba,OF8Bb,CAAA,IAAA,CAAA;EAAU;;;EACR,IAAA,CAAA,OAAA,EExBgB,cFwBhB,EAAA,OACU,CADV,EAAA;IACA,gBAAA,CAAA,EEzB+D,SFyB/D;EAAU,CAAA,CAAA,EEzBmE,OFyBnE,CAAA,IAAA,CAAA;EACI;;;;;;;;;;EAGV,aAAA,CAAA,GAAA,EEfiB,eFejB,GAAA;IACgB,IAAA,CAAA,EEhB4B,QFgB5B;EAAY,CAAA,EAAA,GAAA,EEhBiC,cFgBjC,EAAA,UAAA,CAAA,EAAA,OAAA,CAAA,EEhBwE,OFgBxE,CAAA,IAAA,CAAA;EAAE;;;;AAC3B;EAEa,cAAA,CAAA,SAAA,EESE,SFTF,CAAA,EAAA,IAAA;EAA8B;;;;EAU9C,wBAAS,CAAA,CAAgB,EAAA,IAAA;AAMrC"}
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/streamableHttp.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AA4JwB,KAjIZ,oCAAA,GAAuC,+CAiI3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cApFX,iCAAA,YAA6C;;;;wBAMjC;;;;;;;;;;;;;gCAyCS;0BAIN;;;;oCAOU,wBAAwB;8BAI9B,wBAAwB;;;;;WAQrC;;;;WAOA;;;;gBAOK;uBAA+C;MAAc;;;;;;;;;;;qBAcxD;WAA2B;UAAiB,uCAAuC;;;;;;4BA4BlF"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.mjs","names":[],"sources":["../src/streamableHttp.ts"],"sourcesContent":["/**\n * Node.js Streamable HTTP Server Transport\n *\n * This is a thin wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides\n * compatibility with Node.js HTTP server (`IncomingMessage`/`ServerResponse`).\n *\n * For web-standard environments (Cloudflare Workers, Deno, Bun), use {@linkcode WebStandardStreamableHTTPServerTransport} directly.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { getRequestListener } from '@hono/node-server';\nimport type { AuthInfo, JSONRPCMessage, MessageExtraInfo, RequestId, Transport } from '@modelcontextprotocol/core';\nimport type { WebStandardStreamableHTTPServerTransportOptions } from '@modelcontextprotocol/server';\nimport { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';\n\n/**\n * Configuration options for {@linkcode NodeStreamableHTTPServerTransport}\n *\n * This is an alias for {@linkcode WebStandardStreamableHTTPServerTransportOptions} for backward compatibility.\n */\nexport type StreamableHTTPServerTransportOptions = WebStandardStreamableHTTPServerTransportOptions;\n\n/**\n * Server transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.\n * It supports both SSE streaming and direct HTTP responses.\n *\n * This is a wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides Node.js HTTP compatibility.\n * It uses the `@hono/node-server` library to convert between Node.js HTTP and Web Standard APIs.\n *\n * In stateful mode:\n * - Session ID is generated and included in response headers\n * - Session ID is always included in initialization responses\n * - Requests with invalid session IDs are rejected with `404 Not Found`\n * - Non-initialization requests without a session ID are rejected with `400 Bad Request`\n * - State is maintained in-memory (connections, message history)\n *\n * In stateless mode:\n * - No Session ID is included in any responses\n * - No session validation is performed\n *\n * @example Stateful setup\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateful\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *\n * const transport = new NodeStreamableHTTPServerTransport({\n * sessionIdGenerator: () => randomUUID()\n * });\n *\n * await server.connect(transport);\n * ```\n *\n * @example Stateless setup\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateless\"\n * const transport = new NodeStreamableHTTPServerTransport({\n * sessionIdGenerator: undefined\n * });\n * ```\n *\n * @example Using with a pre-parsed request body (e.g. Express)\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_express\"\n * app.post('/mcp', (req, res) => {\n * transport.handleRequest(req, res, req.body);\n * });\n * ```\n */\nexport class NodeStreamableHTTPServerTransport implements Transport {\n private _webStandardTransport: WebStandardStreamableHTTPServerTransport;\n private _requestListener: ReturnType<typeof getRequestListener>;\n // Store auth and parsedBody per request for passing through to handleRequest\n private _requestContext: WeakMap<Request, { authInfo?: AuthInfo; parsedBody?: unknown }> = new WeakMap();\n\n constructor(options: StreamableHTTPServerTransportOptions = {}) {\n this._webStandardTransport = new WebStandardStreamableHTTPServerTransport(options);\n\n // Create a request listener that wraps the web standard transport\n // getRequestListener converts Node.js HTTP to Web Standard and properly handles SSE streaming\n // overrideGlobalObjects: false prevents Hono from overwriting global Response, which would\n // break frameworks like Next.js whose response classes extend the native Response\n this._requestListener = getRequestListener(\n async (webRequest: Request) => {\n // Get context if available (set during handleRequest)\n const context = this._requestContext.get(webRequest);\n return this._webStandardTransport.handleRequest(webRequest, {\n authInfo: context?.authInfo,\n parsedBody: context?.parsedBody\n });\n },\n { overrideGlobalObjects: false }\n );\n }\n\n /**\n * Gets the session ID for this transport instance.\n */\n get sessionId(): string | undefined {\n return this._webStandardTransport.sessionId;\n }\n\n /**\n * Sets callback for when the transport is closed.\n */\n set onclose(handler: (() => void) | undefined) {\n this._webStandardTransport.onclose = handler;\n }\n\n get onclose(): (() => void) | undefined {\n return this._webStandardTransport.onclose;\n }\n\n /**\n * Sets callback for transport errors.\n */\n set onerror(handler: ((error: Error) => void) | undefined) {\n this._webStandardTransport.onerror = handler;\n }\n\n get onerror(): ((error: Error) => void) | undefined {\n return this._webStandardTransport.onerror;\n }\n\n /**\n * Sets callback for incoming messages.\n */\n set onmessage(handler: ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined) {\n this._webStandardTransport.onmessage = handler;\n }\n\n get onmessage(): ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined {\n return this._webStandardTransport.onmessage;\n }\n\n /**\n * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n return this._webStandardTransport.start();\n }\n\n /**\n * Closes the transport and all active connections.\n */\n async close(): Promise<void> {\n return this._webStandardTransport.close();\n }\n\n /**\n * Sends a JSON-RPC message through the transport.\n */\n async send(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void> {\n return this._webStandardTransport.send(message, options);\n }\n\n /**\n * Handles an incoming HTTP request, whether `GET` or `POST`.\n *\n * This method converts Node.js HTTP objects to Web Standard Request/Response\n * and delegates to the underlying {@linkcode WebStandardStreamableHTTPServerTransport}.\n *\n * @param req - Node.js `IncomingMessage`, optionally with `auth` property from middleware\n * @param res - Node.js `ServerResponse`\n * @param parsedBody - Optional pre-parsed body from body-parser middleware\n */\n async handleRequest(req: IncomingMessage & { auth?: AuthInfo }, res: ServerResponse, parsedBody?: unknown): Promise<void> {\n // Store context for this request to pass through auth and parsedBody\n // We need to intercept the request creation to attach this context\n const authInfo = req.auth;\n\n // Create a custom handler that includes our context\n // overrideGlobalObjects: false prevents Hono from overwriting global Response, which would\n // break frameworks like Next.js whose response classes extend the native Response\n const handler = getRequestListener(\n async (webRequest: Request) => {\n return this._webStandardTransport.handleRequest(webRequest, {\n authInfo,\n parsedBody\n });\n },\n { overrideGlobalObjects: false }\n );\n\n // Delegate to the request listener which handles all the Node.js <-> Web Standard conversion\n // including proper SSE streaming support\n await handler(req, res);\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n this._webStandardTransport.closeSSEStream(requestId);\n }\n\n /**\n * Close the standalone GET SSE stream, triggering client reconnection.\n * Use this to implement polling behavior for server-initiated notifications.\n */\n closeStandaloneSSEStream(): void {\n this._webStandardTransport.closeStandaloneSSEStream();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,oCAAb,MAAoE;CAChE,AAAQ;CACR,AAAQ;CAER,AAAQ,kCAAmF,IAAI,SAAS;CAExG,YAAY,UAAgD,EAAE,EAAE;AAC5D,OAAK,wBAAwB,IAAI,yCAAyC,QAAQ;AAMlF,OAAK,mBAAmB,mBACpB,OAAO,eAAwB;GAE3B,MAAM,UAAU,KAAK,gBAAgB,IAAI,WAAW;AACpD,UAAO,KAAK,sBAAsB,cAAc,YAAY;IACxD,UAAU,SAAS;IACnB,YAAY,SAAS;IACxB,CAAC;KAEN,EAAE,uBAAuB,OAAO,CACnC;;;;;CAML,IAAI,YAAgC;AAChC,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,QAAQ,SAAmC;AAC3C,OAAK,sBAAsB,UAAU;;CAGzC,IAAI,UAAoC;AACpC,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,QAAQ,SAA+C;AACvD,OAAK,sBAAsB,UAAU;;CAGzC,IAAI,UAAgD;AAChD,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,UAAU,SAAoF;AAC9F,OAAK,sBAAsB,YAAY;;CAG3C,IAAI,YAAuF;AACvF,SAAO,KAAK,sBAAsB;;;;;;CAOtC,MAAM,QAAuB;AACzB,SAAO,KAAK,sBAAsB,OAAO;;;;;CAM7C,MAAM,QAAuB;AACzB,SAAO,KAAK,sBAAsB,OAAO;;;;;CAM7C,MAAM,KAAK,SAAyB,SAA2D;AAC3F,SAAO,KAAK,sBAAsB,KAAK,SAAS,QAAQ;;;;;;;;;;;;CAa5D,MAAM,cAAc,KAA4C,KAAqB,YAAqC;EAGtH,MAAM,WAAW,IAAI;AAiBrB,QAZgB,mBACZ,OAAO,eAAwB;AAC3B,UAAO,KAAK,sBAAsB,cAAc,YAAY;IACxD;IACA;IACH,CAAC;KAEN,EAAE,uBAAuB,OAAO,CACnC,CAIa,KAAK,IAAI;;;;;;;CAQ3B,eAAe,WAA4B;AACvC,OAAK,sBAAsB,eAAe,UAAU;;;;;;CAOxD,2BAAiC;AAC7B,OAAK,sBAAsB,0BAA0B"}
{"version":3,"file":"index.mjs","names":[],"sources":["../src/streamableHttp.ts"],"sourcesContent":["/**\n * Node.js Streamable HTTP Server Transport\n *\n * This is a thin wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides\n * compatibility with Node.js HTTP server (`IncomingMessage`/`ServerResponse`).\n *\n * For web-standard environments (Cloudflare Workers, Deno, Bun), use {@linkcode WebStandardStreamableHTTPServerTransport} directly.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nimport { getRequestListener } from '@hono/node-server';\nimport type {\n AuthInfo,\n JSONRPCMessage,\n MessageExtraInfo,\n RequestId,\n Transport,\n WebStandardStreamableHTTPServerTransportOptions\n} from '@modelcontextprotocol/server';\nimport { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';\n\n/**\n * Configuration options for {@linkcode NodeStreamableHTTPServerTransport}\n *\n * This is an alias for {@linkcode WebStandardStreamableHTTPServerTransportOptions} for backward compatibility.\n */\nexport type StreamableHTTPServerTransportOptions = WebStandardStreamableHTTPServerTransportOptions;\n\n/**\n * Server transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.\n * It supports both SSE streaming and direct HTTP responses.\n *\n * This is a wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides Node.js HTTP compatibility.\n * It uses the `@hono/node-server` library to convert between Node.js HTTP and Web Standard APIs.\n *\n * In stateful mode:\n * - Session ID is generated and included in response headers\n * - Session ID is always included in initialization responses\n * - Requests with invalid session IDs are rejected with `404 Not Found`\n * - Non-initialization requests without a session ID are rejected with `400 Bad Request`\n * - State is maintained in-memory (connections, message history)\n *\n * In stateless mode:\n * - No Session ID is included in any responses\n * - No session validation is performed\n *\n * @example Stateful setup\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateful\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *\n * const transport = new NodeStreamableHTTPServerTransport({\n * sessionIdGenerator: () => randomUUID()\n * });\n *\n * await server.connect(transport);\n * ```\n *\n * @example Stateless setup\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateless\"\n * const transport = new NodeStreamableHTTPServerTransport({\n * sessionIdGenerator: undefined\n * });\n * ```\n *\n * @example Using with a pre-parsed request body (e.g. Express)\n * ```ts source=\"./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_express\"\n * app.post('/mcp', (req, res) => {\n * transport.handleRequest(req, res, req.body);\n * });\n * ```\n */\nexport class NodeStreamableHTTPServerTransport implements Transport {\n private _webStandardTransport: WebStandardStreamableHTTPServerTransport;\n private _requestListener: ReturnType<typeof getRequestListener>;\n // Store auth and parsedBody per request for passing through to handleRequest\n private _requestContext: WeakMap<Request, { authInfo?: AuthInfo; parsedBody?: unknown }> = new WeakMap();\n\n constructor(options: StreamableHTTPServerTransportOptions = {}) {\n this._webStandardTransport = new WebStandardStreamableHTTPServerTransport(options);\n\n // Create a request listener that wraps the web standard transport\n // getRequestListener converts Node.js HTTP to Web Standard and properly handles SSE streaming\n // overrideGlobalObjects: false prevents Hono from overwriting global Response, which would\n // break frameworks like Next.js whose response classes extend the native Response\n this._requestListener = getRequestListener(\n async (webRequest: Request) => {\n // Get context if available (set during handleRequest)\n const context = this._requestContext.get(webRequest);\n return this._webStandardTransport.handleRequest(webRequest, {\n authInfo: context?.authInfo,\n parsedBody: context?.parsedBody\n });\n },\n { overrideGlobalObjects: false }\n );\n }\n\n /**\n * Gets the session ID for this transport instance.\n */\n get sessionId(): string | undefined {\n return this._webStandardTransport.sessionId;\n }\n\n /**\n * Sets callback for when the transport is closed.\n */\n set onclose(handler: (() => void) | undefined) {\n this._webStandardTransport.onclose = handler;\n }\n\n get onclose(): (() => void) | undefined {\n return this._webStandardTransport.onclose;\n }\n\n /**\n * Sets callback for transport errors.\n */\n set onerror(handler: ((error: Error) => void) | undefined) {\n this._webStandardTransport.onerror = handler;\n }\n\n get onerror(): ((error: Error) => void) | undefined {\n return this._webStandardTransport.onerror;\n }\n\n /**\n * Sets callback for incoming messages.\n */\n set onmessage(handler: ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined) {\n this._webStandardTransport.onmessage = handler;\n }\n\n get onmessage(): ((message: JSONRPCMessage, extra?: MessageExtraInfo) => void) | undefined {\n return this._webStandardTransport.onmessage;\n }\n\n /**\n * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n return this._webStandardTransport.start();\n }\n\n /**\n * Closes the transport and all active connections.\n */\n async close(): Promise<void> {\n return this._webStandardTransport.close();\n }\n\n /**\n * Sends a JSON-RPC message through the transport.\n */\n async send(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void> {\n return this._webStandardTransport.send(message, options);\n }\n\n /**\n * Handles an incoming HTTP request, whether `GET` or `POST`.\n *\n * This method converts Node.js HTTP objects to Web Standard Request/Response\n * and delegates to the underlying {@linkcode WebStandardStreamableHTTPServerTransport}.\n *\n * @param req - Node.js `IncomingMessage`, optionally with `auth` property from middleware\n * @param res - Node.js `ServerResponse`\n * @param parsedBody - Optional pre-parsed body from body-parser middleware\n */\n async handleRequest(req: IncomingMessage & { auth?: AuthInfo }, res: ServerResponse, parsedBody?: unknown): Promise<void> {\n // Store context for this request to pass through auth and parsedBody\n // We need to intercept the request creation to attach this context\n const authInfo = req.auth;\n\n // Create a custom handler that includes our context\n // overrideGlobalObjects: false prevents Hono from overwriting global Response, which would\n // break frameworks like Next.js whose response classes extend the native Response\n const handler = getRequestListener(\n async (webRequest: Request) => {\n return this._webStandardTransport.handleRequest(webRequest, {\n authInfo,\n parsedBody\n });\n },\n { overrideGlobalObjects: false }\n );\n\n // Delegate to the request listener which handles all the Node.js <-> Web Standard conversion\n // including proper SSE streaming support\n await handler(req, res);\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n this._webStandardTransport.closeSSEStream(requestId);\n }\n\n /**\n * Close the standalone GET SSE stream, triggering client reconnection.\n * Use this to implement polling behavior for server-initiated notifications.\n */\n closeStandaloneSSEStream(): void {\n this._webStandardTransport.closeStandaloneSSEStream();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwEA,IAAa,oCAAb,MAAoE;CAChE,AAAQ;CACR,AAAQ;CAER,AAAQ,kCAAmF,IAAI,SAAS;CAExG,YAAY,UAAgD,EAAE,EAAE;AAC5D,OAAK,wBAAwB,IAAI,yCAAyC,QAAQ;AAMlF,OAAK,mBAAmB,mBACpB,OAAO,eAAwB;GAE3B,MAAM,UAAU,KAAK,gBAAgB,IAAI,WAAW;AACpD,UAAO,KAAK,sBAAsB,cAAc,YAAY;IACxD,UAAU,SAAS;IACnB,YAAY,SAAS;IACxB,CAAC;KAEN,EAAE,uBAAuB,OAAO,CACnC;;;;;CAML,IAAI,YAAgC;AAChC,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,QAAQ,SAAmC;AAC3C,OAAK,sBAAsB,UAAU;;CAGzC,IAAI,UAAoC;AACpC,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,QAAQ,SAA+C;AACvD,OAAK,sBAAsB,UAAU;;CAGzC,IAAI,UAAgD;AAChD,SAAO,KAAK,sBAAsB;;;;;CAMtC,IAAI,UAAU,SAAoF;AAC9F,OAAK,sBAAsB,YAAY;;CAG3C,IAAI,YAAuF;AACvF,SAAO,KAAK,sBAAsB;;;;;;CAOtC,MAAM,QAAuB;AACzB,SAAO,KAAK,sBAAsB,OAAO;;;;;CAM7C,MAAM,QAAuB;AACzB,SAAO,KAAK,sBAAsB,OAAO;;;;;CAM7C,MAAM,KAAK,SAAyB,SAA2D;AAC3F,SAAO,KAAK,sBAAsB,KAAK,SAAS,QAAQ;;;;;;;;;;;;CAa5D,MAAM,cAAc,KAA4C,KAAqB,YAAqC;EAGtH,MAAM,WAAW,IAAI;AAiBrB,QAZgB,mBACZ,OAAO,eAAwB;AAC3B,UAAO,KAAK,sBAAsB,cAAc,YAAY;IACxD;IACA;IACH,CAAC;KAEN,EAAE,uBAAuB,OAAO,CACnC,CAIa,KAAK,IAAI;;;;;;;CAQ3B,eAAe,WAA4B;AACvC,OAAK,sBAAsB,eAAe,UAAU;;;;;;CAOxD,2BAAiC;AAC7B,OAAK,sBAAsB,0BAA0B"}
{
"name": "@modelcontextprotocol/node",
"version": "2.0.0-alpha.2",
"version": "2.0.0-alpha.3",
"description": "Model Context Protocol implementation for TypeScript - Node.js middleware",

@@ -29,2 +29,10 @@ "license": "MIT",

},
"types": "./dist/index.d.mts",
"typesVersions": {
"*": {
"sse": [
"dist/sse.d.mts"
]
}
},
"files": [

@@ -38,4 +46,9 @@ "dist"

"hono": "^4.11.4",
"@modelcontextprotocol/server": "^2.0.0-alpha.2"
"@modelcontextprotocol/server": "^2.0.0-alpha.3"
},
"peerDependenciesMeta": {
"hono": {
"optional": true
}
},
"devDependencies": {

@@ -49,8 +62,7 @@ "@eslint/js": "^9.39.2",

"tsdown": "^0.18.0",
"tsx": "^4.16.5",
"typescript": "^5.9.3",
"typescript-eslint": "^8.48.1",
"vitest": "^4.0.15",
"@modelcontextprotocol/server": "^2.0.0-alpha.2",
"@modelcontextprotocol/core": "^2.0.0-alpha.1",
"@modelcontextprotocol/server": "^2.0.0-alpha.3",
"@modelcontextprotocol/core-internal": "^2.0.0-alpha.2",
"@modelcontextprotocol/eslint-config": "^2.0.0",

@@ -69,6 +81,4 @@ "@modelcontextprotocol/test-helpers": "^2.0.0-alpha.0",

"test": "vitest run",
"test:watch": "vitest",
"server": "tsx watch --clear-screen=false scripts/cli.ts server",
"client": "tsx scripts/cli.ts client"
"test:watch": "vitest"
}
}