Skip to content

Reject requests with a null id - #605

Closed
dominikklein wants to merge 1 commit into
modelcontextprotocol:mainfrom
dominikklein:reject_requests_with_a_null_id
Closed

dominikklein wants to merge 1 commit into
modelcontextprotocol:mainfrom
dominikklein:reject_requests_with_a_null_id

Conversation

@dominikklein

Copy link
Copy Markdown

MCP doesn't allow a null request id, but "id": null was treated like a missing id: the method ran and nothing was answered, so over HTTP the client got a 202 with an empty body. Such a request now gets Invalid Request (-32600) and the method isn't called. valid_id? no longer accepts nil (its error message drops "or null"), and the check only applies when the id key is present, so a message without an id is still a notification. The HTTP transport's legacy path also routed these messages as notifications, so it checks for the key now too; on the 2026-07-28 path the error comes back as a 400.

server.handle_json('{"jsonrpc":"2.0","id":null,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hi"}}}')
# => {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid Request","data":"Request ID must match validation pattern, or be an integer"}}

This covers the null-id part of #601. Requests sent without any id are still run as notifications; that's the separate question in the issue and is left open here. A notification method sent with "id": null is refused now as well, since by JSON-RPC rules that's a request.

Refs #601.

MCP doesn't allow a null request id, but a request with "id": null was run
like a notification: the method executed and nothing was answered (202 over
HTTP). It now gets Invalid Request (-32600) and the method doesn't run.
A message without an id is still handled as a notification.

Refs modelcontextprotocol#601.
@koic

koic commented Oct 15, 2026

Copy link
Copy Markdown
Member

Closing in favor of #612, which refuses a null id the same way (-32600, the method not run, notification? keyed on the presence of the member) and also covers the other part of #601: a protocol request method sent without an id is no
longer run as a notification, as the TypeScript and Python servers drop such a message, while methods registered with define_custom_method keep serving notifications.

#612 also adds regression tests for an id-less tools/call and ping on the transport, for the null id on both lifecycles, and for a custom method still running without an id.

Thank you for the report and the repro in #601 that showed the id-less call running as well.

@koic koic closed this Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants