Protocol Interactions
3. Protocol Interactions & Message Deep Dive¶
This section details the fundamental JSON-RPC 2.0 message structures used by MCP, lifecycle management, and authorization basics.
3.1. Base Message Structures (JSON-RPC 2.0)¶
MCP uses standard JSON-RPC 2.0 for all messages. Key requirements and constraints:
- Requests:
- Sent by either Client or Server to initiate an operation.
jsonrpc: "2.0"id:stringornumber(Mandatory, MUST NOT benull). Request IDs must be unique per session for the sender.method:string(Name of the method to be invoked).params:object(Optional parameters for the method).
- Responses:
- Sent in reply to a Request.
jsonrpc: "2.0"id:stringornumber(Must match the ID of the corresponding Request).result:object(Present on success, contains the operation result).error:object(Present on failure). Must containcode(integer),message(string), and optionallydata(unknown).- A response MUST contain either
resultorerror, but not both.
- Notifications:
- Sent by either Client or Server as a one-way message (no response expected).
jsonrpc: "2.0"method:string(Name of the notification event).params:object(Optional parameters for the notification).- MUST NOT include an
id.
- Batching:
- Implementations MUST support receiving batched requests/notifications (sent as a JSON array).
- Implementations MAY support sending batches.
Security Considerations (Base JSON-RPC):
- Request ID Uniqueness: While mandated, improper handling could lead to response mismatches or potential replay attacks if IDs are predictable or reused insecurely within a session.
- Error Handling: Sensitive information could be leaked in
errormessages (messageordatafields) if not carefully constructed. - Batching Complexity: Handling batches correctly is crucial. Errors in processing one part of a batch should not necessarily halt others, but error reporting needs to be precise. Large batches could be used for DoS attempts.
3.2. Lifecycle Management (Initialize, Shutdown, Exit)¶
The connection follows a defined lifecycle:
- Initialization Phase:
- Trigger: Client sends
initializerequest to Server. - Purpose: Negotiate protocol version, exchange capabilities, share implementation info (
clientInfo,serverInfo). - Client
initializeParams:protocolVersion,capabilities(Client's offered features likeroots,sampling),clientInfo(name,version). - Server
initializeResult:protocolVersion(Agreed version),capabilities(Server's offered features likelogging,prompts,resources,tools),serverInfo(name,version). - Protocol Version Negotiation: Client proposes version (latest supported). Server responds with the same version if supported, otherwise its latest supported version. Client SHOULD disconnect if server's version is unsupported.
- Capability Negotiation: Defines which optional features (Resources, Tools, Prompts, Sampling, Logging, Roots, etc.) are available for the session. Specific sub-capabilities (e.g.,
listChanged,subscribe) are also negotiated here. - Confirmation: Client sends
notifications/initializednotification after receiving a successfulinitializeresponse. - Restrictions:
initializerequest MUST NOT be batched.- Client SHOULD NOT send other requests (except ping) before server responds to
initialize. - Server SHOULD NOT send requests (except ping, logging) before receiving
notifications/initialized.
- Trigger: Client sends
- Operation Phase:
- Normal exchange of requests, responses, and notifications based on negotiated capabilities and protocol version.
- Shutdown Phase:
- Clean termination initiated usually by the Client.
- No specific protocol messages.
- Relies on transport layer closure (e.g., closing stdio streams, closing HTTP connections).
- Specification provides guidance for graceful shutdown with stdio (close input, wait/SIGTERM, wait/SIGKILL).
Security Considerations (Lifecycle):
- Initialization Vulnerabilities:
- Capability Spoofing/Misrepresentation: A malicious Client or Server could lie about its
capabilitiesorInfo, potentially tricking the other party into insecure operations or attempting to enable features it doesn't securely support. - Version Downgrade Attacks: If negotiation logic isn't strict, an attacker might force the use of an older, potentially less secure protocol version.
- Resource Exhaustion during Init: A flood of
initializerequests or large capability objects could cause DoS. - Information Leakage:
clientInfoandserverInfocould leak potentially sensitive details about the software versions in use, aiding attackers in finding known exploits.
- Capability Spoofing/Misrepresentation: A malicious Client or Server could lie about its
- Improper Shutdown: Failure to shut down gracefully (especially with stdio) could leave orphaned server processes, potentially consuming resources or holding locks.
- State Mismatches: If the
notifications/initializedis lost or mishandled, the Client and Server might have different understandings of the session state, leading to errors or unexpected behavior. - Capability Enforcement: The protocol relies on implementations to honor the negotiated capabilities. A compromised or malicious participant could ignore the negotiation and attempt to use features that weren't agreed upon.
3.3. Authorization (HTTP Transport)¶
Authorization is optional but specified for HTTP-based transports. Implementations using stdio SHOULD retrieve credentials from the environment instead.
- Standard: Based on OAuth 2.1 (IETF Draft) with PKCE mandatory for all clients.
- Trigger: Server responds with HTTP 401 Unauthorized when authorization is required.
- Flow: Standard OAuth 2.1 Authorization Code Grant flow with PKCE.
- Client receives 401.
- Client generates
code_verifierandcode_challenge. - Client directs user-agent (browser) to Server's authorization endpoint (
/authorizeby default, or discovered via metadata) withcode_challenge. - User authenticates and authorizes the Client via the Server.
- Server redirects user-agent back to Client's registered
redirect_uriwith anauthorization_code. - Client receives
authorization_code. - Client makes a POST request to the Server's token endpoint (
/tokenby default, or discovered) including theauthorization_codeand the originalcode_verifier. - Server verifies the code and verifier, issues an
access_token(and optionally arefresh_token). - Client includes the
access_tokenin theAuthorization: Bearer <token>header for subsequent MCP requests over HTTP.
- Metadata Discovery (RFC 8414):
- Clients MUST attempt discovery via
GET /.well-known/oauth-authorization-serverrelative to the authorization base URL (Server URL with path removed). - Clients SHOULD include
MCP-Protocol-Versionheader in discovery requests. - Servers SHOULD provide metadata; if not, Clients MUST fallback to default paths (
/authorize,/token,/register).
- Clients MUST attempt discovery via
- Dynamic Client Registration (RFC 7591):
- Clients and Servers SHOULD support dynamic registration via the registration endpoint (
/registerby default or discovered). - Allows clients to obtain
client_id(and potentiallyclient_secretfor confidential clients) automatically. - Servers not supporting it require alternative methods (hardcoded ID, manual user entry).
- Clients and Servers SHOULD support dynamic registration via the registration endpoint (
- Access Token Usage:
- MUST be sent in
Authorization: Bearer <token>header for every HTTP request. - MUST NOT be sent in URI query string.
- Servers MUST validate tokens (signature, expiry, scope) and respond with 401/403 on failure.
- MUST be sent in
- Third-Party Authorization: Servers MAY delegate auth to a third-party OAuth server, acting as a client to the third-party and an authorization server to the MCP client. Requires careful session binding and validation.
Security Considerations (Authorization):
- Transport Security: All authorization endpoints MUST use HTTPS.
- PKCE Implementation: Correct implementation is crucial to prevent authorization code interception attacks.
- Redirect URI Validation: Servers MUST strictly validate
redirect_uriagainst pre-registered values to prevent Open Redirect attacks and token leakage. - Token Storage (Client): Clients MUST store access and refresh tokens securely (e.g., using OS keychain, encrypted storage).
- Token Handling (Server): Servers SHOULD enforce short token lifetimes, support token rotation (refresh tokens), and securely validate tokens.
- Dynamic Client Registration Security: Unauthenticated or improperly secured registration endpoints could allow malicious clients to register. Servers need robust policies.
- Metadata Security: Relying on potentially unsecured HTTP for discovery (if HTTPS is not enforced) could lead to endpoint spoofing.
- Third-Party Auth Risks: Introduces complexity and reliance on the third-party's security. Session binding must be robust to prevent attacks where a compromised third-party session grants access to MCP.
- Scope Management: Proper definition and enforcement of OAuth scopes are needed to limit the client's access to only what the user authorized (least privilege).
- Credential Handling (stdio): Retrieving credentials from the environment for stdio transport needs careful handling to avoid exposing secrets in logs, process lists, or insecure environment variable storage.