MCP 2026-07-28 Dual-Version Migration
AppTheory serves the final MCP 2026-07-28 stateless transport alongside the established 2025-11-25 session-ful
transport on the same MCP handler. This is an additive server change; there is no server-wide mode flag and no second
route or deployment construct.
Existing session-ful clients: no change
Clients that use 2025-11-25 keep the same behavior:
- call
initialize - retain the returned
Mcp-Session-Id - use that session id for later POST/GET/DELETE requests
- receive the existing response bodies without
resultType - use SSE streaming, replay, tasks, and the existing session error contract as before
Do not add modern routing headers to a session-ful client unless it is intentionally sending a 2026-07-28 request.
All pre-existing session-ful contract fixtures remain byte-identical.
Modern stateless clients: migration checklist
For a client that opts into 2026-07-28:
- Keep using
POST /mcpon the existing AppTheory handler. - Do not call
initializeand do not send or expectMcp-Session-Id. - Call
server/discoverto read supported protocol versions, capabilities, and server identity. - Send
Content-Type: application/jsonandAccept: application/json, text/event-stream. - Identify the protocol with
Mcp-Protocol-Version: 2026-07-28orparams._meta["io.modelcontextprotocol/protocolVersion"]. - When both protocol values are present, make them identical.
- Send
Mcp-Methodequal to the JSON-RPCmethodon every request or notification. -
Send
Mcp-Namefor the methods below, using the exact body value:Method Mcp-Namevaluetools/callparams.nameprompts/getparams.nameresources/readparams.uri - Advertise per-request client capabilities under
params._meta["io.modelcontextprotocol/clientCapabilities"]. - Branch on every successful result’s
resultType.
The 2026-07-28 shape is POST-only in this milestone. It does not route initialize, sessions, GET/listen,
DELETE, task methods, task-augmented tool calls, resource subscriptions, or subscriptions/listen. A GET or DELETE
carrying Mcp-Protocol-Version: 2026-07-28 returns HTTP 405 before legacy session validation.
Discover before calling methods
Example:
curl -sS \
-X POST "https://YOUR_ENDPOINT/mcp" \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2026-07-28' \
-H 'mcp-method: server/discover' \
-d '{
"jsonrpc":"2.0",
"id":"discover",
"method":"server/discover",
"params":{
"_meta":{
"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{}
}
}
}'
AppTheory advertises, in preference order:
2026-07-282025-11-252025-06-182025-03-26
The result derives capabilities from the server’s configured registries and hooks and returns the server constructor’s
name/version under _meta["io.modelcontextprotocol/serverInfo"]. A task-enabled server advertises its task capability
because discovery describes the server across all supported versions; task calls still require a 2025-11-25
session. A subscriptions capability is intentionally absent.
Handle resultType
Every successful modern result has one of:
resultType: "complete": processing is finishedresultType: "input_required": fulfill the returned input requests and retry the original request
For input_required, preserve requestState, collect a response for each named entry in inputRequests, and send those
values as inputResponses on the retry. The input request method determines the required client capability. For
example, this request metadata advertises elicitation:
{
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
Do not synthesize resultType for a 2025-11-25 response. AppTheory deliberately preserves the old wire shape.
Handle the modern validation errors
AppTheory exports and returns these 2026-07-28 error codes:
| Code | Name | Action |
|---|---|---|
-32020 |
Header mismatch | Make protocol metadata and routing headers match the JSON-RPC body |
-32021 |
Missing required client capability | Advertise every capability needed by the returned input requests |
-32022 |
Unsupported protocol version | Choose a value from error.data.supported |
These errors return a JSON-RPC error body with HTTP 400. -32021 includes
error.data.requiredCapabilities; -32022 includes error.data.supported and error.data.requested.
In particular, a sessionless request with an unknown or future protocol header now receives -32022 instead of first
failing as a missing legacy session.
Rollout
- Deploy the upgraded AppTheory runtime without changing existing clients.
- Verify a session-ful canary still initializes, calls tools, streams/replays if used, and deletes its session.
- Add one stateless canary that calls
server/discover. - Verify its routing headers at the HTTP edge before enabling tool calls.
- Verify the client handles both result types and all three modern validation codes.
- Expand the stateless canary only after capability and multi-round input handling is ready.
For the complete runtime surface, see docs/integrations/mcp.md. For the Remote MCP deployment shape, see
docs/integrations/remote-mcp.md.