Message Format
MCP uses JSON-RPC 2.0 as its wire format. The transport layer is responsible for converting MCP protocol messages into JSON-RPC format for transmission and converting received JSON-RPC messages back into MCP protocol messages. There are three types of JSON-RPC messages used:Requests
Responses
Notifications
Built-in Transport Types
MCP currently defines two standard transport mechanisms:Standard Input/Output (stdio)
The stdio transport enables communication through standard input and output streams. This is particularly useful for local integrations and command-line tools. Use stdio when:- Building command-line tools
- Implementing local integrations
- Needing simple process communication
- Working with shell scripts
Server
Client
Streamable HTTP
The Streamable HTTP transport uses HTTP POST requests for client-to-server communication and optional Server-Sent Events (SSE) streams for server-to-client communication. Use Streamable HTTP when:- Building web-based integrations
- Needing client-server communication over HTTP
- Requiring stateful sessions
- Supporting multiple concurrent clients
- Implementing resumable connections
How it Works
- Client-to-Server Communication: Every JSON-RPC message from client to server is sent as a new HTTP POST request to the MCP endpoint
- Server Responses: The server can respond either with:
- A single JSON response (
Content-Type: application/json
) - An SSE stream (
Content-Type: text/event-stream
) for multiple messages
- A single JSON response (
- Server-to-Client Communication: Servers can send requests/notifications to clients via:
- SSE streams initiated by client requests
- SSE streams from HTTP GET requests to the MCP endpoint
Server
Client
Session Management
Streamable HTTP supports stateful sessions to maintain context across multiple requests:- Session Initialization: Servers may assign a session ID during initialization by including it in an
Mcp-Session-Id
header - Session Persistence: Clients must include the session ID in all subsequent requests using the
Mcp-Session-Id
header - Session Termination: Sessions can be explicitly terminated by sending an HTTP DELETE request with the session ID
Resumability and Redelivery
To support resuming broken connections, Streamable HTTP provides:- Event IDs: Servers can attach unique IDs to SSE events for tracking
- Resume from Last Event: Clients can resume by sending the
Last-Event-ID
header - Message Replay: Servers can replay missed messages from the disconnection point
Security Considerations
When implementing Streamable HTTP transport, follow these security best practices:- Validate Origin Headers: Always validate the
Origin
header on all incoming connections to prevent DNS rebinding attacks - Bind to Localhost: When running locally, bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
- Implement Authentication: Use proper authentication for all connections
- Use HTTPS: Always use TLS/HTTPS for production deployments
- Validate Session IDs: Ensure session IDs are cryptographically secure and properly validated
Server-Sent Events (SSE) - Deprecated
SSE as a standalone transport is deprecated as of protocol version 2024-11-05.
It has been replaced by Streamable HTTP, which incorporates SSE as an optional
streaming mechanism. For backwards compatibility information, see the
backwards compatibility section below.
- Only server-to-client streaming is needed
- Working with restricted networks
- Implementing simple updates
Legacy Security Considerations
The deprecated SSE transport had similar security considerations to Streamable HTTP, particularly regarding DNS rebinding attacks. These same protections should be applied when using SSE streams within the Streamable HTTP transport.Server
Client
Custom Transports
MCP makes it easy to implement custom transports for specific needs. Any transport implementation just needs to conform to the Transport interface: You can implement custom transports for:- Custom network protocols
- Specialized communication channels
- Integration with existing systems
- Performance optimization
Error Handling
Transport implementations should handle various error scenarios:- Connection errors
- Message parsing errors
- Protocol errors
- Network timeouts
- Resource cleanup
Best Practices
When implementing or using MCP transport:- Handle connection lifecycle properly
- Implement proper error handling
- Clean up resources on connection close
- Use appropriate timeouts
- Validate messages before sending
- Log transport events for debugging
- Implement reconnection logic when appropriate
- Handle backpressure in message queues
- Monitor connection health
- Implement proper security measures
Security Considerations
When implementing transport:Authentication and Authorization
- Implement proper authentication mechanisms
- Validate client credentials
- Use secure token handling
- Implement authorization checks
Data Security
- Use TLS for network transport
- Encrypt sensitive data
- Validate message integrity
- Implement message size limits
- Sanitize input data
Network Security
- Implement rate limiting
- Use appropriate timeouts
- Handle denial of service scenarios
- Monitor for unusual patterns
- Implement proper firewall rules
- For HTTP-based transports (including Streamable HTTP), validate Origin headers to prevent DNS rebinding attacks
- For local servers, bind only to localhost (127.0.0.1) instead of all interfaces (0.0.0.0)
Debugging Transport
Tips for debugging transport issues:- Enable debug logging
- Monitor message flow
- Check connection states
- Validate message formats
- Test error scenarios
- Use network analysis tools
- Implement health checks
- Monitor resource usage
- Test edge cases
- Use proper error tracking
Backwards Compatibility
To maintain compatibility between different protocol versions:For Servers Supporting Older Clients
Servers wanting to support clients using the deprecated HTTP+SSE transport should:- Host both the old SSE and POST endpoints alongside the new MCP endpoint
- Handle initialization requests on both endpoints
- Maintain separate handling logic for each transport type
For Clients Supporting Older Servers
Clients wanting to support servers using the deprecated transport should:- Accept server URLs that may use either transport
- Attempt to POST an
InitializeRequest
with properAccept
headers:- If successful, use Streamable HTTP transport
- If it fails with 4xx status, fall back to legacy SSE transport
- Issue a GET request expecting an SSE stream with
endpoint
event for legacy servers