Merge branch 'main' into request-propagation-in-tools
This commit is contained in:
commit
e714050642
1 changed files with 378 additions and 23 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { Transport } from "../shared/transport.js";
|
||||
import { isInitializeRequest, isJSONRPCError, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema, RequestId } from "../types.js";
|
||||
import { isInitializeRequest, isJSONRPCError, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema, RequestId, SUPPORTED_PROTOCOL_VERSIONS, DEFAULT_NEGOTIATED_PROTOCOL_VERSION } from "../types.js";
|
||||
import getRawBody from "raw-body";
|
||||
import contentType from "content-type";
|
||||
import { randomUUID } from "node:crypto";
|
||||
|
|
@ -111,7 +111,7 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
private _eventStore?: EventStore;
|
||||
private _onsessioninitialized?: (sessionId: string) => void;
|
||||
|
||||
sessionId?: string | undefined;
|
||||
sessionId?: string;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
onmessage?: (message: JSONRPCMessage, extra: MessageExtraInfo) => void;
|
||||
|
|
@ -173,6 +173,9 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
if (!this.validateSession(req, res)) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateProtocolVersion(req, res)) {
|
||||
return;
|
||||
}
|
||||
// Handle resumability: check for Last-Event-ID header
|
||||
if (this._eventStore) {
|
||||
const lastEventId = req.headers['last-event-id'] as string | undefined;
|
||||
|
|
@ -380,11 +383,17 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
}
|
||||
|
||||
}
|
||||
// If an Mcp-Session-Id is returned by the server during initialization,
|
||||
// clients using the Streamable HTTP transport MUST include it
|
||||
// in the Mcp-Session-Id header on all of their subsequent HTTP requests.
|
||||
if (!isInitializationRequest && !this.validateSession(req, res)) {
|
||||
return;
|
||||
if (!isInitializationRequest) {
|
||||
// If an Mcp-Session-Id is returned by the server during initialization,
|
||||
// clients using the Streamable HTTP transport MUST include it
|
||||
// in the Mcp-Session-Id header on all of their subsequent HTTP requests.
|
||||
if (!this.validateSession(req, res)) {
|
||||
return;
|
||||
}
|
||||
// Mcp-Protocol-Version header is required for all requests after initialization.
|
||||
if (!this.validateProtocolVersion(req, res)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -459,6 +468,9 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
if (!this.validateSession(req, res)) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateProtocolVersion(req, res)) {
|
||||
return;
|
||||
}
|
||||
await this.close();
|
||||
res.writeHead(200).end();
|
||||
}
|
||||
|
|
@ -526,6 +538,25 @@ export class StreamableHTTPServerTransport implements Transport {
|
|||
return true;
|
||||
}
|
||||
|
||||
private validateProtocolVersion(req: IncomingMessage, res: ServerResponse): boolean {
|
||||
let protocolVersion = req.headers["mcp-protocol-version"] ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
||||
if (Array.isArray(protocolVersion)) {
|
||||
protocolVersion = protocolVersion[protocolVersion.length - 1];
|
||||
}
|
||||
|
||||
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) {
|
||||
res.writeHead(400).end(JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
error: {
|
||||
code: -32000,
|
||||
message: `Bad Request: Unsupported protocol version (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`
|
||||
},
|
||||
id: null
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
// Close all SSE connections
|
||||
|
|
|
|||
Loading…
Reference in a new issue