Freezing MCP Initialization Capabilities: Version Negotiation, Handshake Receipts, and In-Session Invariants
A successful `initialize` does not let either side add or remove features freely during a session. This article seals the protocol version, both parties’ capabilities, implementation identities, and the `initialized` boundary into an auditable receipt, preventing existing connections from using capabilities negotiated only later.
Key Points
- Topic Focus: AI Agent、MCP、DevOps
- Suitable for: indie hackers, full-stack engineers, AI application developers
- Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
The Client declares support for Sampling, and after a rolling deployment the Server can handle it as well, so the gateway enables sampling/createMessage directly on an existing connection. However, this capability was not exchanged when that connection was initialized, and the audit log retains only the current configuration. The call occasionally succeeds, but there is no proof that both parties ever agreed to this contract; as soon as an instance rolls back, behavior diverges.
An In-Depth Guide to the MCP Protocol introduces the message structure, while MCP Tool Schema Design constrains individual tools. This article addresses an earlier control-plane concern: when a connection transitions from “able to carry JSON-RPC” to “authorized to execute a specific MCP capability,” and how the negotiated result remains immutable throughout the session.
Seal the initialize Result into a Version Contract
Under the 2025-11-25 lifecycle, initialize must be the first interaction between the Client and Server. The Client submits its supported protocol version, capabilities, and implementation information. If the Server supports that version, it must return it unchanged; otherwise, it returns another version that it supports. If the Client does not support the returned version, it must disconnect rather than selecting a few fields and continuing. After a successful response, the Client must also send notifications/initialized. Until the Server receives it, the Server should not initiate requests other than ping and logging.
The control plane stores an mcpHandshakeReceipt.v1 containing the connection or session ID, Client and Server principals, request and response digests, final protocol version, canonicalized JSON for both parties’ capabilities, implementation names and versions, transport, policy version, initialization time, initialized arrival time, and deployment generation. Capabilities must be interpreted according to the direction of each party rather than combined as a union. For example, Sampling is a Client capability, while Resources is a Server capability; nested capabilities such as resources.subscribe and sampling.tools must also exist at every level. The Agent Tool Capability Catalog can consume this frozen snapshot, but it must not overwrite an existing session with the latest catalog.
NEW -> INITIALIZE_SENT -> VERSION_ACCEPTED -> RECEIPT_SEALED
RECEIPT_SEALED -> INITIALIZED_ACKED -> OPERATIONAL
Any negotiation failure -> REJECTED -> CLOSED
OPERATIONAL -> DRAINING -> CLOSED
The only activation point is activateSession(receiptDigest). Within a transaction, it verifies that the version is supported, all required capabilities are present, the response JSON-RPC ID matches, the receipt has been sealed, and the initialized notification belongs to the same transport generation. It then uses CAS to write OPERATIONAL and a ready outbox record. Ordinary requests arriving before this point enter a bounded buffer or are explicitly rejected; they must never execute before the receipt is backfilled. Subsequent HTTP requests must also carry the negotiated MCP-Protocol-Version. Compatibility inference when the header is missing must not override established handshake facts.
Capability Changes Must Create a New Session
Configuration, tool lists, and authorization scope may change during a deployment, but initialization capabilities are not a hot-update channel. New optional capabilities take effect only for new handshakes. When revoking a high-risk capability, mark the old receipt generation as DRAINING, reject new related operations, wait for in-flight requests to finish, and then close the connection. Tool-list changes can use a negotiated listChanged notification, but they cannot conjure the listChanged capability itself. The compatibility windows described in REST API Versioning also apply, but MCP must additionally bind bidirectional capabilities to session timing.
Fault injection must cover repeated initialize calls, different payloads using the same JSON-RPC ID, initialized arriving before the response, the Server returning an unknown version, a proxy tampering with the version header, an old instance reusing a new session, and normalization differences caused by capability casing or empty objects. Assert that every non-ping operation maps back to exactly one handshake receipt, repeated handshakes never overwrite the original receipt, and an old generation cannot acquire capabilities added later. MCP Audit Logging Design preserves these causal fields.
Release gates require a 100% pass rate for protocol matrix tests; zero premature activations across 10,000 out-of-order handshake cases; 0% of runtime requests without a receipt; zero divergence between capability decisions and the frozen snapshot; 100% classification coverage for rejection reasons; initialization p99 within budget; and no more than 32 buffered requests. During rollout, first record shadow receipts only and compare them with existing routing decisions. Then enforce them for 5% of new sessions before gradually increasing to 100%. During rollback, stop issuing new generations, retain validators for old receipts and the drain path, and never reinterpret an existing connection as having the previous version’s capability set.
Related
Related Content
Article
From Copilot to Codex: AI Coding Tools Enter the Agent Era
Technical trends, engineering practices, and indie-developer perspectives around AI, AI Agents, and Vibe Coding.
Article
Why Does MCP Matter? Understanding the AI Tool Protocol
Technical trends, engineering practices, and an independent developer perspective on MCP and AI Agents.
Article
Core Architecture of AI Agents: Planning, Memory, Tools, and Execution
Technical trends, engineering practices, and independent developer perspectives around AI Agents and large language models.
Article
How Should RAG and Agents Work Together?
An independent developer's perspective on technical trends and engineering practices involving RAG and AI agents.