-
Notifications
You must be signed in to change notification settings - Fork 811
Support server returning only JSON on requests #299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* always send headers specified in requestInit option * avoid doubled onerror call * use for-await to iterate SSE stream * remove outdated comments * simplify requestId tracking * throw error when response Content-Type is out of spec
StreamableHTTPClientTransport cleanup / fixes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks mostly good - some doc updates + remove accidental .swp file
some non-blocking questions/nits, feel free to ignore
src/examples/README.md
Outdated
|
||
```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" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work for me - I get:
❯ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":"1"}' \
-i http://localhost:3000/mcp 2>&1
HTTP/1.1 406 Not Acceptable
X-Powered-By: Express
Date: Thu, 10 Apr 2025 10:50:08 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
{"jsonrpc":"2.0","error":{"code":-32000,"message":"Not Acceptable: Client must accept both application/json and text/event-stream"},"id":null}%
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This worked with the current implementation:
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"
src/examples/README.md
Outdated
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" \ | ||
-H "mcp-session-id: $SESSION_ID" \ | ||
-d '{"jsonrpc":"2.0","method":"mcp.call_tool","params":{"name":"greet","arguments":{"name":"World"}},"id":"2"}' \ | ||
http://localhost:3000/mcp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mcp.call_tool
isn't correct, also I needed to have the Accept: text/event-stream
header here too
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": "tools/call",
"params": {
"name": "greet",
"arguments": {
"name": "World"
}
},
"id": "2"
}' \
http://localhost:3000/mcp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove before merging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh, how this got it here!
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`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this may need the same treatment mentioned prior
src/server/streamableHttp.test.ts
Outdated
await jsonResponseTransport.handleRequest(req, mockResponse); | ||
|
||
// Wait for all promises to resolve | ||
await new Promise(resolve => setTimeout(resolve, 50)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[non-blocking nit] is there a better way to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like it would just slow down tests
src/server/streamableHttp.test.ts
Outdated
it("should return JSON response for a single request", async () => { | ||
const requestMessage: JSONRPCMessage = { | ||
jsonrpc: "2.0", | ||
method: "test", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[non-blocking question] should this use real MCP messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, actually was thinking to use MCP server and rewrite tests, mocking request doesn't seem robust
src/server/streamableHttp.test.ts
Outdated
await jsonResponseTransport.handleRequest(req, mockResponse); | ||
|
||
// Wait for all promises to resolve - give it enough time | ||
await new Promise(resolve => setTimeout(resolve, 100)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same nit as prior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we actually don't even need it, was trying to make the test work, but the issues was in completely different place
Spec states that servers must support either streaming or json response. Clients MUST support both.
We anticipate that TypeScript sdk will mostly be used with streaming, but for testing purpose adding support for returning JSON.
Returning JSON is more limited in functionality as we are loosing streaming tool notification/logging etc.
Example of a response calling to server that supports streaming:

Example of a response calling to server that support only JSON (loosing logging):
