Harden the protocol
Distinguish JSON-RPC errors, tool errors, and notifications.
Build it in your language
The tester treats your program as a black box: any language works. These are just the most convenient ones for this project.
Standard Error Handling and Silent Notifications
A compliant MCP server must format standard JSON-RPC errors and handle notifications (messages omitting the id key) without emitting any stdout response.
Mental Model: JSON-RPC Errors & Notifications
- Parse Error (
-32700/id: null): Unparsable incoming lines. - Method Not Found (
-32601/id: <id>): Unregistered method invocations. - Tool Execution Errors: Returns
isError: trueinresultwhen tool arguments are missing or invalid. - Notifications: Requests lacking an
idproperty (e.g."notifications/initialized") generate no output.
Your Goal in this Stage
Handle JSON parse failures, unrecognized methods, tool argument errors, and silent notifications.
Input Format (Parse error)
not-jsonOutput Format
{
"jsonrpc": "2.0",
"id": null,
"error": { "code": -32700, "message": "Parse error" }
}
Input Format (Unknown method)
{ "jsonrpc": "2.0", "id": 8, "method": "unknown" }
Output Format
{
"jsonrpc": "2.0",
"id": 8,
"error": { "code": -32601, "message": "Method not found" }
}
Step-by-Step Implementation Guide
- Catch JSON syntax errors: Return
-32700withid: null. - Ignore notifications: If
idis missing, execute side effects silently without writing to stdout. - Catch missing methods: Return
-32601with callerid. - Validate tool parameters: Return
isError: truewhen arguments are incomplete.
Acceptance Criteria
- ✅ Emits code -32700 on unparsable input.
- ✅ Emits code -32601 on unrecognized methods.
- ✅ Flags invalid tool arguments with
isError: true. - ✅ Produces zero output for notifications.
Protocol boundaries
A notification omits id; id: null is not a notification and is invalid in MCP. Respond with id: null, code -32600, and message Invalid Request. Unknown resources use -32002 / Resource not found; unknown tools use -32602 / Unknown tool. For echo, require a string text and no additional properties; invalid arguments return result.content: [{"type":"text","text":"Invalid arguments for echo"}] and isError: true. For add, require exactly a and b, both finite numbers. Do not coerce values to hide type errors. Protocol errors go to stdout and processing continues until EOF with exit 0.
Output and errors
Multiline examples are formatted for readability. Emit compact JSON without optional spaces, with properties in the order shown by the output examples, and a final newline. Keep logs off stdout. Tests compare exact text.