MCP uses JSON-RPC to encode messages. JSON-RPC messages MUST be UTF-8 encoded. The protocol currently defines two standard transport mechanisms for client-server communication:Documentation Index
Fetch the complete documentation index at: https://modelcontextprotocol.io/llms.txt
Use this file to discover all available pages before exploring further.
- stdio, communication over standard in and standard out
- Streamable HTTP
stdio
In the stdio transport:- The client launches the MCP server as a subprocess.
- The server reads JSON-RPC messages from its standard input (
stdin) and sends messages to its standard output (stdout). - Messages are individual JSON-RPC requests, notifications, or responses.
- Messages are delimited by newlines, and MUST NOT contain embedded newlines.
- The server MAY write UTF-8 strings to its standard error (
stderr) for any logging purposes including informational, debug, and error messages. - The client MAY capture, forward, or ignore the server’s
stderroutput and SHOULD NOT assumestderroutput indicates error conditions. - The server MUST NOT write anything to its
stdoutthat is not a valid MCP message. - The client MUST NOT write anything to the server’s
stdinthat is not a valid MCP message.
Streamable HTTP
This replaces the HTTP+SSE
transport from
protocol version 2024-11-05. See the backwards compatibility
guide below.
https://example.com/mcp.
Security Warning
When implementing Streamable HTTP transport:- Servers MUST validate the
Originheader on all incoming connections to prevent DNS rebinding attacks- If the
Originheader is present and invalid, servers MUST respond with HTTP 403 Forbidden. The HTTP response body MAY comprise a JSON-RPC error response that has noid
- If the
- When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
- Servers SHOULD implement proper authentication for all connections
Sending Messages to the Server
Every JSON-RPC message sent from the client MUST be a new HTTP POST request to the MCP endpoint.- The client MUST use HTTP POST to send JSON-RPC messages to the MCP endpoint.
- The client MUST include an
Acceptheader, listing bothapplication/jsonandtext/event-streamas supported content types. - The client MUST include the standard MCP request headers on each POST request.
- The body of the HTTP POST request MUST be a single JSON-RPC request, notification, or response to a server-sent request.
- If the body is a JSON-RPC notification or response to a server-sent request:
- If the server accepts the input, the server MUST return HTTP status code 202 Accepted with no body.
- If the server cannot accept the input, it MUST return an HTTP error status code
(e.g., 400 Bad Request). The HTTP response body MAY comprise a JSON-RPC error
response that has no
id.
- If the body is a JSON-RPC request, the server MUST either
return
Content-Type: text/event-stream, to initiate an SSE stream, orContent-Type: application/json, to return one JSON object. The client MUST support both these cases. - If the server initiates an SSE stream:
- The server SHOULD immediately send an SSE event consisting of an event
ID and an empty
datafield in order to prime the client to reconnect (using that event ID asLast-Event-ID). - After the server has sent an SSE event with an event ID to the client, the server MAY close the connection (without terminating the SSE stream) at any time in order to avoid holding a long-lived connection. The client SHOULD then “poll” the SSE stream by attempting to reconnect.
- If the server does close the connection prior to terminating the SSE stream,
it SHOULD send an SSE event with a standard
retryfield before closing the connection. The client MUST respect theretryfield, waiting the given number of milliseconds before attempting to reconnect. - The SSE stream SHOULD eventually include a JSON-RPC response for the JSON-RPC request sent in the POST body.
- The server MAY send JSON-RPC requests and notifications before sending the JSON-RPC response. These messages MUST relate to the originating client request.
- After the JSON-RPC response has been sent, the server SHOULD terminate the SSE stream.
- Disconnection MAY occur at any time (e.g., due to network conditions).
Therefore:
- Disconnection SHOULD NOT be interpreted as the client cancelling its request.
- To cancel, the client SHOULD explicitly send an MCP
CancelledNotification. - To avoid message loss due to disconnection, the server MAY make the stream resumable.
- The server SHOULD immediately send an SSE event consisting of an event
ID and an empty
Listening for Messages from the Server
- The client MAY issue an HTTP GET to the MCP endpoint. This can be used to open an SSE stream, allowing the server to communicate to the client, without the client first sending data via HTTP POST.
- The client MUST include an
Acceptheader, listingtext/event-streamas a supported content type. - The server MUST either return
Content-Type: text/event-streamin response to this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server does not offer an SSE stream at this endpoint. Per RFC 9110 §15.5.6, if the server returns HTTP 405, it MUST include anAllowheader listing the methods it does support (e.g.,Allow: POST). - If the server initiates an SSE stream:
- The server MAY send JSON-RPC notifications and pings on the stream.
- These messages SHOULD be unrelated to any concurrently-running JSON-RPC
request from the client, except that
roots/list,sampling/createMessage, andelicitation/createrequests MUST NOT be sent on standalone streams. - The server MUST NOT send a JSON-RPC response on the stream unless resuming a stream associated with a previous client request.
- The server MAY close the SSE stream at any time.
- If the server closes the connection without terminating the stream, it
SHOULD follow the same polling behavior as described for POST requests:
sending a
retryfield and allowing the client to reconnect. - The client MAY close the SSE stream at any time.
Multiple Connections
- The client MAY remain connected to multiple SSE streams simultaneously.
- The server MUST send each of its JSON-RPC messages on only one of the connected
streams; that is, it MUST NOT broadcast the same message across multiple streams.
- The risk of message loss MAY be mitigated by making the stream resumable.
Resumability and Redelivery
To support resuming broken connections, and redelivering messages that might otherwise be lost:- Servers MAY attach an
idfield to their SSE events, as described in the SSE standard.- If present, the ID MUST be globally unique across all streams.
- Event IDs SHOULD encode sufficient information to identify the originating
stream, enabling the server to correlate a
Last-Event-IDto the correct stream.
- If the client wishes to resume after a disconnection (whether due to network failure
or server-initiated closure), it SHOULD issue an HTTP GET to the MCP endpoint,
and include the
Last-Event-IDheader to indicate the last event ID it received.- The server MAY use this header to replay messages that would have been sent after the last event ID, on the stream that was disconnected, and to resume the stream from that point.
- The server MUST NOT replay messages that would have been delivered on a different stream.
- This mechanism applies regardless of how the original stream was initiated (via
POST or GET). Resumption is always via HTTP GET with
Last-Event-ID.
Sequence Diagram
Protocol Version Header
If using HTTP, the client MUST include theMCP-Protocol-Version: <protocol-version> HTTP header on all subsequent requests to the MCP
server, allowing the MCP server to respond based on the MCP protocol version.
For example: MCP-Protocol-Version: 2025-06-18
The protocol version sent by the client SHOULD be the one negotiated during
initialization.
For backwards compatibility, if the server does not receive an MCP-Protocol-Version
header, and has no other way to identify the version - for example, by relying on the
protocol version negotiated during initialization - the server SHOULD assume protocol
version 2025-03-26.
If the server receives a request with an invalid or unsupported
MCP-Protocol-Version, it MUST respond with 400 Bad Request.
Standard MCP Request Headers
The Streamable HTTP transport requires clients to include the following headers on POST requests, mirrored from the JSON-RPC request body:| Header Name | Source Field | Required For |
|---|---|---|
Mcp-Method | method | All requests and notifications |
Mcp-Name | params.name or params.uri | tools/call, resources/read, prompts/get requests |
Examples
tools/call request:
resources/read request:
initialize request (no Mcp-Name needed):
Case Sensitivity
Header names (called “field names” in RFC 9110) are case-insensitive. Clients and servers MUST use case-insensitive comparisons for header names. Header values (such as method names) are case-sensitive.Server Validation
Servers that process the request body MUST reject requests where the values specified in the headers do not match the corresponding values in the request body. This prevents potential security vulnerabilities when different components in the network rely on different sources of truth (e.g., a load balancer routing on the header value while the MCP server executes based on the body value). When rejecting a request due to header validation failure, servers MUST return HTTP status400 Bad Request and SHOULD include a JSON-RPC error response using the following error code:
| Code | Name | Description |
|---|---|---|
-32001 | HeaderMismatch | The HTTP headers do not match the corresponding values in the request body, or required headers are missing/malformed. |
-32000 to
-32099).
Example error response:
- A required standard header (
Mcp-Method,Mcp-Name) is missing - A header value does not match the corresponding request body value
- A header value contains invalid characters
Intermediaries MUST return an appropriate HTTP error status (e.g.,
400 Bad Request)
for validation failures but are not required to return a JSON-RPC error response.Custom Headers from Tool Parameters
MCP servers MAY designate specific tool parameters to be mirrored into HTTP headers using anx-mcp-header extension property in the parameter’s schema within the tool’s
inputSchema. See Tool Definitions for
details on how to annotate tool parameters.
While the use of x-mcp-header is optional for servers, clients MUST support this
feature. When a server’s tool definition includes x-mcp-header annotations, conforming
clients MUST mirror the designated parameter values into HTTP headers.
Schema Extension
Thex-mcp-header property specifies the name portion used to construct the header name
Mcp-Param-{name}.
Constraints on x-mcp-header values:
- MUST NOT be empty
- MUST contain only ASCII characters (excluding space and
:) - MUST be case-insensitively unique among all
x-mcp-headervalues in theinputSchema - MUST only be applied to parameters with primitive types (number, string, boolean)
x-mcp-header value violates these
constraints. Rejection means the client MUST exclude the invalid tool from the result
of tools/list. Clients SHOULD log a warning when rejecting a tool definition,
including the tool name and the reason for rejection.
Example tool definition:
Value Encoding
Clients MUST encode parameter values before including them in HTTP headers to ensure safe transmission and prevent injection attacks. Type conversion: Convert the parameter value to its string representation:string: Use the value as-isnumber: Convert to decimal string representation (e.g.,42,3.14)boolean: Convert to lowercase"true"or"false"
=?base64? and suffix ?= indicate that the value is Base64-encoded.
Servers and intermediaries that need to inspect these values MUST decode them
accordingly.
Encoding examples:
| Original Value | Reason | Encoded Header Value |
|---|---|---|
"us-west1" | Plain ASCII | Mcp-Param-Region: us-west1 |
"Hello, 世界" | Contains non-ASCII | Mcp-Param-Greeting: =?base64?SGVsbG8sIOS4lueVjA==?= |
" padded " | Leading/trailing spaces | Mcp-Param-Text: =?base64?IHBhZGRlZCA=?= |
"line1\nline2" | Contains newline | Mcp-Param-Text: =?base64?bGluZTEKbGluZTI=?= |
Client Behavior
When constructing atools/call request via HTTP transport, the client MUST:
- Extract the values for any standard headers from the request body (e.g.,
method,params.name,params.uri) - Append the
Mcp-Methodheader and, if applicable,Mcp-Nameheader to the request - Inspect the tool’s
inputSchemafor properties marked withx-mcp-headerand extract the value for each parameter - Encode the values according to the Value Encoding rules
- Append a
Mcp-Param-{Name}: {Value}header to the request
Server Behavior for Custom Headers
Intermediate servers that do not recognize anMcp-Param-{Name} header MUST forward it and otherwise ignore it, as required by the HTTP Semantics RFC.
Servers MUST reject requests with a recognized Mcp-Param-{Name} header that contains invalid
characters (see Value Encoding).
Any server that processes the message body MUST validate that encoded header values,
after decoding if Base64-encoded, match the corresponding values in the request body.
Servers MUST reject requests with a 400 Bad Request HTTP status and JSON-RPC error
code -32001 (HeaderMismatch) if any validation fails.
| Scenario | Client Behavior | Server Behavior |
|---|---|---|
| Parameter value provided | Client MUST include the header | Server MUST validate header matches body |
Parameter value is null | Client MUST omit the header | Server MUST NOT expect the header |
| Parameter not in arguments | Client MUST omit the header | Server MUST NOT expect the header |
| Client omits header but value is in body | Non-conforming client | Server MUST reject the request |
SSE Stream Configuration
When initiating SSE streams, servers SHOULD include theX-Accel-Buffering: no
header in HTTP responses that return Content-Type: text/event-stream. This header
instructs reverse proxies (such as nginx) to disable response buffering, ensuring that
SSE events are delivered to clients immediately rather than being held in a buffer.
Without this header, proxies may accumulate messages before sending them to the client,
introducing unwanted latency and potentially breaking the real-time nature of SSE
communication.
Backwards Compatibility
Clients and servers can maintain backwards compatibility with the deprecated HTTP+SSE transport (from protocol version 2024-11-05) as follows: Servers wanting to support older clients should:- Continue to host both the SSE and POST endpoints of the old transport, alongside the
new “MCP endpoint” defined for the Streamable HTTP transport.
- It is also possible to combine the old POST endpoint and the new MCP endpoint, but this may introduce unneeded complexity.
- Accept an MCP server URL from the user, which may point to either a server using the old transport or the new transport.
- Attempt to POST an
InitializeRequestto the server URL, with anAcceptheader as defined above:- If it succeeds, the client can assume this is a server supporting the new Streamable HTTP transport.
- If it fails with the following HTTP status codes “400 Bad Request”, “404 Not
Found”, or “405 Method Not Allowed”:
- Issue a GET request to the server URL, expecting that this will open an SSE stream
and return an
endpointevent as the first event. - When the
endpointevent arrives, the client can assume this is a server running the old HTTP+SSE transport, and should use that transport for all subsequent communication.
- Issue a GET request to the server URL, expecting that this will open an SSE stream
and return an