An open protocol created by Anthropic that standardizes how AI applications connect to external tools, data sources, and prompts. MCP defines a JSON-RPC 2.0 based client-server protocol where hosts embed clients that talk to servers exposing tools, resources, and prompts.
All MCP messages MUST be framed as JSON-RPC 2.0 requests, responses, or notifications with the 'jsonrpc' field set to the string '2.0'
Reusing JSON-RPC 2.0 gives MCP a battle-tested message shape, standard error envelope, and free library support across every language an agent host is likely to be implemented in
Implementations MUST use one of the standardized MCP transports (stdio, Streamable HTTP, or the legacy HTTP+SSE transport) rather than inventing a bespoke transport
A closed set of transports lets any compliant client talk to any compliant server without negotiation over transport details
Individual JSON-RPC messages sent over the stdio transport MUST NOT contain embedded newlines in the serialized form - each message is a single line terminated by a newline
The stdio transport frames messages by newline; embedding literal newlines inside a message would corrupt the frame boundary
A client MUST send the 'initialize' request as its first message after establishing the transport, and MUST NOT issue any other requests until it has received the initialize response and sent the 'notifications/initialized' notification
A fixed handshake prevents servers from having to guess which client capabilities are available when answering early requests
The server MUST echo the negotiated protocol version back in its initialize response; if it cannot support any version the client offers, it MUST fail the request rather than proceeding
Explicit version negotiation avoids silent incompatibility where two peers keep talking while interpreting the same method name differently
A server MUST NOT respond successfully to a tools/* request unless it advertised the 'tools' capability in its initialize response, and similarly for 'resources', 'prompts', and 'logging'
Capability advertisement is the contract that lets a client skip calling methods that will never work on this server, avoiding useless round-trips and cryptic errors
A server SHOULD declare the 'listChanged' sub-capability under tools, resources, or prompts when it is capable of emitting the corresponding notifications/*/list_changed notification
Clients that know a server will emit list_changed can cache listings and refresh reactively instead of polling
Every tool declared in a tools/list response MUST carry a JSON Schema object under 'inputSchema' describing the accepted parameters, even if the schema is an empty object
A machine-readable input schema is what lets the host validate arguments, surface them to the model, and generate UI - without it the tool is unusable programmatically
Tools SHOULD provide a natural-language description aimed at the model, explaining when the tool should be used and what it returns
The description is what the model reads to decide whether to call the tool; terse or missing descriptions lead to either never-called or incorrectly-called tools
{"name":"read_file","description":"Read the contents of a UTF-8 text file from the local filesystem","inputSchema":{"type":"object","properties":{"path":{"type":"string"}},"required":["path"]}}
A well-formed tool declaration with a name, description, and JSON Schema for its single required string parameter
Every resource exposed through resources/list MUST be identified by a URI string, and clients MUST read its content via resources/read using that exact URI
A URI is the only stable identifier a client can hand back when asking for content; names or descriptions are human-readable and may change
A resource's content MUST be returned as either a text payload with a declared mimeType or as a binary blob encoded with base64 and a declared mimeType
Without a declared mimeType a client cannot decide whether to show the content as text, render it in a UI, or hand it to the model as raw bytes
Every prompt returned from prompts/list MUST declare its arguments (if any) with a name and a required/optional flag so clients can prompt the user for values before calling prompts/get
Clients cannot present a prompt to an end user without knowing which variables need to be filled in - hidden arguments break the authoring UX
{"name":"review_code","description":"Review a snippet of code","arguments":[{"name":"language","description":"The programming language","required":true},{"name":"code","description":"The code to review","required":true}]}
A prompt declaration with two required arguments and human-readable descriptions
Clients SHOULD give the user an opportunity to review and approve or modify sampling requests before forwarding them to the model, especially for sensitive contexts
Sampling lets a server indirectly instruct the client's model; human review protects against prompt injection and quota abuse
{"jsonrpc":"2.0","id":42,"method":"sampling/createMessage","params":{"messages":[{"role":"user","content":{"type":"text","text":"Summarize the attached file"}}],"maxTokens":500}}
A sampling/createMessage request with a single user turn and a maxTokens budget
Error responses MUST use the JSON-RPC 2.0 error envelope with numeric 'code', human-readable 'message', and optional 'data' fields, and MUST NOT encode errors as successful results with an error flag
Treating application errors as successful results breaks every generic JSON-RPC client library and defeats the purpose of a standard error shape