diff --git a/src/examples/README.md b/src/examples/README.md index 937159c3..cc6af51c 100644 --- a/src/examples/README.md +++ b/src/examples/README.md @@ -20,15 +20,43 @@ The server will start on port 3000. You can test the initialization and tool cal ```bash # Initialize the server and get the session ID from headers -SESSION_ID=$(curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \ - -d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":"1"}' \ +SESSION_ID=$(curl -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Accept: text/event-stream" \ + -d '{ + "jsonrpc": "2.0", + "method": "initialize", + "params": { + "capabilities": {}, + "protocolVersion": "2025-03-26", + "clientInfo": { + "name": "test", + "version": "1.0.0" + } + }, + "id": "1" + }' \ -i http://localhost:3000/mcp 2>&1 | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\r') echo "Session ID: $SESSION_ID" # Call the greet tool using the saved session ID -curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \ +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Accept: text/event-stream" \ -H "mcp-session-id: $SESSION_ID" \ - -d '{"jsonrpc":"2.0","method":"mcp.call_tool","params":{"name":"greet","arguments":{"name":"World"}},"id":"2"}' \ + -d '{ + "jsonrpc": "2.0", + "method": "tools/call", + "params": { + "name": "greet", + "arguments": { + "name": "World" + } + }, + "id": "2" + }' \ http://localhost:3000/mcp ``` @@ -52,10 +80,25 @@ The server will start on port 3000. You can test the initialization and tool lis ```bash # First initialize the server and save the session ID to a variable -SESSION_ID=$(curl -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \ - -d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":"1"}' \ +SESSION_ID=$(curl -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Accept: text/event-stream" \ + -d '{ + "jsonrpc": "2.0", + "method": "initialize", + "params": { + "capabilities": {}, + "protocolVersion": "2025-03-26", + "clientInfo": { + "name": "test", + "version": "1.0.0" + } + }, + "id": "1" + }' \ -i http://localhost:3000/mcp 2>&1 | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\r') -echo "Session ID: $SESSION_ID" +echo "Session ID: $SESSION_ID # Then list tools using the saved session ID curl -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \ diff --git a/src/examples/server/jsonResponseStreamableHttp.ts b/src/examples/server/jsonResponseStreamableHttp.ts index 9b053631..1d322112 100644 --- a/src/examples/server/jsonResponseStreamableHttp.ts +++ b/src/examples/server/jsonResponseStreamableHttp.ts @@ -149,10 +149,29 @@ function isInitializeRequest(body: unknown): boolean { // Start the server const PORT = 3000; app.listen(PORT, () => { - console.log(`MCP Streamable HTTP Server with JSON responses listening on port ${PORT}`); - console.log(`Server is running. Press Ctrl+C to stop.`); - console.log(`Initialize with: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":"1"}' http://localhost:${PORT}/mcp`); - console.log(`Then call tool with: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "mcp-session-id: YOUR_SESSION_ID" -d '{"jsonrpc":"2.0","method":"mcp.call_tool","params":{"name":"greet","arguments":{"name":"World"}},"id":"2"}' http://localhost:${PORT}/mcp`); + console.log(`MCP Streamable HTTP Server listening on port ${PORT}`); + console.log(`Initialize session with the command below id you are using curl for testing: + ----------------------------- + SESSION_ID=$(curl -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Accept: text/event-stream" \ + -d '{ + "jsonrpc": "2.0", + "method": "initialize", + "params": { + "capabilities": {}, + "protocolVersion": "2025-03-26", + "clientInfo": { + "name": "test", + "version": "1.0.0" + } + }, + "id": "1" + }' \ + -i http://localhost:3000/mcp 2>&1 | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\\r') + echo "Session ID: $SESSION_ID" + -----------------------------`); }); // Handle server shutdown diff --git a/src/examples/server/simpleStreamableHttp.ts b/src/examples/server/simpleStreamableHttp.ts index 74c3ef53..5b228cbd 100644 --- a/src/examples/server/simpleStreamableHttp.ts +++ b/src/examples/server/simpleStreamableHttp.ts @@ -186,7 +186,28 @@ function isInitializeRequest(body: unknown): boolean { const PORT = 3000; app.listen(PORT, () => { console.log(`MCP Streamable HTTP Server listening on port ${PORT}`); - console.log(`Test with: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":"1"}' http://localhost:${PORT}/mcp`); + console.log(`Initialize session with the command below id you are using curl for testing: + ----------------------------- + SESSION_ID=$(curl -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -H "Accept: text/event-stream" \ + -d '{ + "jsonrpc": "2.0", + "method": "initialize", + "params": { + "capabilities": {}, + "protocolVersion": "2025-03-26", + "clientInfo": { + "name": "test", + "version": "1.0.0" + } + }, + "id": "1" + }' \ + -i http://localhost:3000/mcp 2>&1 | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\\r') + echo "Session ID: $SESSION_ID" + -----------------------------`); }); // Handle server shutdown diff --git a/src/server/.streamableHttp.test.ts.swp b/src/server/.streamableHttp.test.ts.swp deleted file mode 100644 index 4ab20fa3..00000000 Binary files a/src/server/.streamableHttp.test.ts.swp and /dev/null differ diff --git a/src/server/streamableHttp.test.ts b/src/server/streamableHttp.test.ts index 926c4306..640c843d 100644 --- a/src/server/streamableHttp.test.ts +++ b/src/server/streamableHttp.test.ts @@ -1252,7 +1252,7 @@ describe("StreamableHTTPServerTransport", () => { it("should return JSON response for a single request", async () => { const requestMessage: JSONRPCMessage = { jsonrpc: "2.0", - method: "test", + method: "tools/list", params: {}, id: "test-req-id", }; @@ -1306,8 +1306,8 @@ describe("StreamableHTTPServerTransport", () => { it("should return JSON response for batch requests", async () => { const batchMessages: JSONRPCMessage[] = [ - { jsonrpc: "2.0", method: "test1", params: {}, id: "req1" }, - { jsonrpc: "2.0", method: "test2", params: {}, id: "req2" }, + { jsonrpc: "2.0", method: "tools/list", params: {}, id: "req1" }, + { jsonrpc: "2.0", method: "tools/call", params: {}, id: "req2" }, ]; const req = createMockRequest({ @@ -1334,9 +1334,6 @@ describe("StreamableHTTPServerTransport", () => { await jsonResponseTransport.handleRequest(req, mockResponse); - // Wait for all promises to resolve - give it enough time - await new Promise(resolve => setTimeout(resolve, 100)); - // Should respond with application/json header expect(mockResponse.writeHead).toHaveBeenCalledWith( 200, @@ -1350,7 +1347,7 @@ describe("StreamableHTTPServerTransport", () => { const responseJson = JSON.parse(mockResponse.end.mock.calls[0][0] as string); expect(Array.isArray(responseJson)).toBe(true); expect(responseJson).toHaveLength(2); - + // Check each response exists separately without assuming order expect(responseJson).toContainEqual(expect.objectContaining({ id: "req1", result: { value: "result-for-req1" } })); expect(responseJson).toContainEqual(expect.objectContaining({ id: "req2", result: { value: "result-for-req2" } }));