The problem
MCP (Model Context Protocol) is the standard way for an application that uses a language model to talk to programs that offer tools. All its messages are JSON-RPC 2.0 objects: JSON (JavaScript Object Notation) text that asks another program to run a function (a remote procedure call) or answers such a request. Before anything else, a program has to recognize what kind of message it received. You will write that classifier.
The kinds of message
classify(msg) takes a parsed message (any JSON value: a dict, a list, a number...) and returns (kind, error_code):
- request,
("request", None): a dict with"jsonrpc": "2.0", a string"method", and an"id"that is a string or an integer. MCP forbids anullid, and aboolis not an integer here."params", if present, must be an object (a dict). - notification,
("notification", None): the same, but with no"id"key at all. Nobody answers a notification. - response,
("response", None):"jsonrpc": "2.0", a valid"id", and exactly one of"result"(an object) or"error"(an object with an integer"code"and a string"message"), and no"method". An error response may have"id": nullwhen the id of the request could not be read. - invalid,
("invalid", -32600): anything else, including batches (lists): MCP removed JSON-RPC batching in revision 2025-06-18.
Example.
message kind {"jsonrpc": "2.0", "id": 1, "method": "tools/list"}request {"jsonrpc": "2.0", "method": "notifications/progress"}notification {"jsonrpc": "2.0", "id": 1, "result": {}}response {"jsonrpc": "2.0", "id": null, "error": {"code": -32700, "message": "Parse error"}}response {"jsonrpc": "2.0", "id": null, "method": "x"}invalid: a request's id cannot be null{"jsonrpc": "2.0", "id": true, "method": "x"}invalid: trueis not an integer{"jsonrpc": "2.0", "id": 1, "result": {}, "error": {...}}invalid: both resultanderrora list containing one request invalid: a batch
Errors
JSON-RPC reserves standard error codes, and error_response(id, code, message) builds the error response for them: {"jsonrpc": "2.0", "id": id, "error": {"code": code, "message": message}}.
Example.
error_response(1, -32601, "Method not found")is{"jsonrpc": "2.0", "id": 1, "error": {"code": -32601, "message": "Method not found"}}.
What to implement
classify(msg): the kind and error code above.error_response(id, code, message): the error response dict.- The constants
PARSE_ERROR = -32700,INVALID_REQUEST = -32600,METHOD_NOT_FOUND = -32601,INVALID_PARAMS = -32602,INTERNAL_ERROR = -32603.
Requirements
- An error response may have
"id": Nonewhen the request's id could not be read; accept it.