Commit 26a87ed
committed
Support JSON response mode for
## Motivation and Context
The MCP Streamable HTTP specification allows servers to return POST responses as either
`text/event-stream` (SSE) or `application/json`:
> If the input is a JSON-RPC request, the server MUST either return `Content-Type: text/event-stream`,
> to initiate an SSE stream, or `Content-Type: application/json`, to return one JSON object.
See: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server
The TypeScript and Python SDKs support a configurable JSON response mode
via `enableJsonResponse` / `is_json_response_enabled`.
JSON response mode is suitable for simple tool servers that do not need server-initiated requests.
It avoids SSE framing overhead and returns a single JSON object for the POST response.
## Behavior
- POST responses use `Content-Type: application/json` and return a single JSON object.
- The POST `Accept` header requirement is relaxed to `application/json` only
(matching the Python SDK's lenient behavior).
- Request-scoped notifications (`progress`, `log`) cannot ride along with the single-object response
and are silently dropped.
- Session-scoped standalone notifications (`resources/updated`, `elicitation/complete`)
and broadcast notifications (`tools/list_changed`, etc.) continue to flow to clients connected
to the GET SSE stream.
- All server-to-client requests (`sampling/createMessage`, `roots/list`, `elicitation/create`)
raise an error in JSON response mode.
- Combines with `stateless: true` for simple single-response servers without session tracking.
## How Has This Been Tested?
Added tests for JSON response mode:
- POST request returns `application/json` response
- Accept header validation requires only `application/json`
- Returns 406 when Accept header is missing
- Accepts wildcard `*/*` in Accept header
- Request-scoped notifications (progress, log) during tool execution are silently dropped
- Request-scoped notifications do not leak to GET SSE even when connected
- Session-scoped standalone notifications are delivered via GET SSE
- Broadcast notifications are delivered via GET SSE
- `send_request` raises for `sampling/createMessage`, `roots/list`, `elicitation/create`
- Combined with `stateless: true`: POST returns JSON without a session ID, GET returns 405
## Breaking Changes
None. JSON response mode is opt-in via `enable_json_response: true`.
The default behavior (SSE responses) is unchanged.StreamableHTTPTransport
1 parent 0770e27 commit 26a87ed
3 files changed
Lines changed: 449 additions & 4 deletions
File tree
- lib/mcp/server/transports
- test/mcp/server/transports
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1425 | 1425 | | |
1426 | 1426 | | |
1427 | 1427 | | |
| 1428 | + | |
| 1429 | + | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
1428 | 1445 | | |
1429 | 1446 | | |
1430 | 1447 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
46 | | - | |
| 47 | + | |
| 48 | + | |
47 | 49 | | |
48 | 50 | | |
49 | 51 | | |
| |||
94 | 96 | | |
95 | 97 | | |
96 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
97 | 105 | | |
98 | 106 | | |
99 | 107 | | |
| |||
172 | 180 | | |
173 | 181 | | |
174 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
175 | 187 | | |
176 | 188 | | |
177 | 189 | | |
| |||
278 | 290 | | |
279 | 291 | | |
280 | 292 | | |
281 | | - | |
| 293 | + | |
| 294 | + | |
282 | 295 | | |
283 | 296 | | |
284 | 297 | | |
| |||
519 | 532 | | |
520 | 533 | | |
521 | 534 | | |
522 | | - | |
| 535 | + | |
523 | 536 | | |
524 | 537 | | |
525 | 538 | | |
| |||
0 commit comments