MP-301g · Module 1

Error Codes & Protocol Negotiation

3 min read

JSON-RPC defines four standard error codes: -32700 (parse error — malformed JSON), -32600 (invalid request — missing required fields), -32601 (method not found), and -32603 (internal error — server-side failure). MCP extends this range with application-specific codes for capability mismatches, authentication failures, and rate limiting. Your error handler must distinguish between protocol errors (the message itself is broken) and application errors (the message was valid but the operation failed). Protocol errors indicate bugs; application errors indicate runtime conditions.

Protocol negotiation happens in the initialize handshake. The client sends its supported protocol version and capabilities. The server responds with the protocol version it will use (which may be lower than what the client requested) and its own capabilities. If the client and server cannot agree on a compatible version, the server returns an error and the connection fails. Capabilities are additive — the client declares what it can provide (roots, sampling), and the server declares what it offers (tools, resources, prompts). Neither side should call methods that the other did not advertise.

Version negotiation follows semver semantics. A client requesting protocol version "2025-11-05" can connect to a server offering "2024-11-05" if the major version matches and the server version is not newer than the client. The initialize response includes the negotiated version, and both sides must honor it for the remainder of the session. Sending a request that belongs to a newer protocol version than what was negotiated is a protocol violation — the server should reject it with -32601 (method not found), not crash.

  1. Map your error codes Create an enum or constant map of all JSON-RPC and MCP-specific error codes your server can return. Include human-readable messages for each. Do not use raw numbers in application code.
  2. Implement version negotiation Parse the client's requested protocol version in initialize. Compare against your supported versions. Respond with the highest mutually compatible version or an error if none exists.
  3. Test capability boundaries Write tests that call methods not advertised in the server's capabilities. Verify the server returns -32601 (method not found), not a crash or silent failure.