Handshake: which MCP clients will break your server after the 2026-07-28 spec split? A developer built Handshake, an agent that checks whether a Model Context Protocol (MCP) server will keep working with a given client after the 2026-07-28 spec revision, which removes initialize, Mcp-Session-Id, ping, logging/setLevel and resources/subscribe while adding server/discover, per-request _meta, a required resultType and cache hints. The tool joins stored spec, version and client-support facts in Sanity via Sanity Context MCP, with a deterministic function rather than the model assigning each verdict color; on 18 held-out labeled cells it scored 16 correct versus 6 for keyword search. This is a submission for the Sanity Challenge, Path One: Ship an Agent That Queries Real Content https://dev.to/challenges/sanity-2026-09-16 Will my MCP server still work with client X after the 2026-07-28 spec split? Paste a manifest into Handshake and you get a grid of verdicts, one per feature and client, each with its sources. The spec and client-support content lives in Sanity, and the agent reads it through Sanity Context MCP GROQ over a dataset, plus a Knowledge Base . A plain function picks each colour, not the model. On 18 held-out cells I labeled from stored quotes, Handshake gets 16 right. Keyword search gets 6. On 28 July 2026 the Model Context Protocol removed its own handshake: revision 2026-07-28 drops initialize , Mcp-Session-Id , ping , logging/setLevel , and resources/subscribe , and adds server/discover , per-request meta , a required resultType , and cache hints on list results. Roots, Sampling, and Logging are deprecated, and the earliest removal date on the registry is 28 July 2027. Client docs didn't all keep up: Cursor's MCP page still lists Roots as Supported, and still lists SSE, which the spec deprecated in March 2025. Handshake is for people who ship MCP servers. Paste a server/discover result, an initialize result, or a short manifest. Rows are the features the server depends on, columns are clients, and each cell gets a colour: compute verdict picks the colour by joining three stored facts: where the feature sits in the spec, which protocol versions the server advertises, and a support claim with a URL and the date I read it. Gemini only writes the paragraph under the grid. If it tries to relabel a cell, the page still shows the function's answer. The demo has eight scenarios. These four make the case. initialize and logging/setLevel : it still speaks the legacy era, which has those methods. Claude is amber because Anthropic's 28 July post says modern support is rolling out, not finished. Cursor is grey on supportedVersions to 2026-07-28 but still requires Mcp-Session-Id , and There's no hosted copy of the Next app, so the quickest way in is the public dataset project hmeltser , no login : first five feature documents, as JSON https://hmeltser.api.sanity.io/v2025-01-01/data/query/production?query= %5B type%3D%3D%22feature%22%5D%5B0...5%5D%7Bkey%2Cname%7D . The Sanity Studio https://handshake-mcp.sanity.studio/ needs a Sanity login; more links are at the end. The grid needs no API key: without SANITY CONTEXT TOKEN , lookups use the same fixture data seeded into the public dataset. That's what the screenshots show, and the colours match the seeded documents. Two GIFs: that manifest turning into the grid, and a cell's sources plus the migration advice. The source isn't public yet, so the parts that matter are quoted inline below. Copyright 2026 Manoj Kumar. The core is lib/verdict/compute.ts . Around it: data/ : revisions, features, clients, and claims. data/heldout.ts is the quote-labeled set; data/golden.ts is a rules-consistency file whose score I don't treat as accuracy. lib/manifest/parse.ts turns a paste into feature keys plus a flag for "this server advertises only 2026-07-28". lib/agent/loop.ts is an eight-step tool loop; lib/agent/gemini.ts calls the free Gemini API. npm test covers the claims, held-out quotes, consistency file, mock loop, and Gemini retry. npm run eval prints the held-out comparison first. I wrote the components myself; button styling uses class-variance-authority , clsx , and tailwind-merge . Three excerpts, copied verbatim from the source. 1. The agent reads Sanity through Context MCP. With a token set, the agent's groq query calls the groq query tool on the handshake-data endpoint. From lib/agent/execute.ts : js async function liveGroq query: string : Promise