On July 28, 2026 the Model Context Protocol locks its 2026-07-28 specification — the biggest breaking change the protocol has shipped. The handshake and sessions are gone; the protocol goes stateless. If you run an MCP server, several things you rely on today stop working on that date.
I built mcp-vet, a zero-config CLI that scans your MCP server source (TypeScript, JavaScript, Python) for the exact patterns that break — and tells you what to change.
npx @booyaka/mcp-vet .
No account, no API key, no network calls. It parses your code locally (ts-morph for TS/JS, a bundled Python ast script for .py) and exits non-zero on anything BREAKING, so it drops straight into CI.
What changes on 2026-07-28
Breaking — these stop working:
-
Mcp-Session-Idheader and protocol-level sessions are removed. Client info and capabilities now travel in per-request_meta. -
initialize/notifications/initializedhandshake is removed. Protocol version, client info, and capabilities now arrive on every request. -
Error code
-32002(missing resource) becomes the JSON-RPC standard-32602Invalid Params. -
Legacy Tasks methods —
tasks/get·tasks/update·tasks/cancelargument shapes change, andtasks/listandtasks/resultare removed entirely (poll withtasks/get).
Deprecated — 12-month grace period: the roots, sampling, and logging capabilities.
It matches how servers are actually written
The trick to a useful migration linter is catching real code, not just raw method strings. mcp-vet matches:
-
literal method strings —
'tasks/list','sampling/createMessage','logging/setLevel', … -
SDK schema-constant registration —
server.setRequestHandler(InitializeRequestSchema, …)(how the official SDKs register handlers) mapsInitializeRequestSchema,ListRootsRequestSchema,CreateMessageRequestSchema,ListTasksRequestSchema, … to the right rule. -
SDK capability constructors — the Python SDK's
ClientCapabilities(roots=RootsCapability())is recognized structurally. -
sessionIdGenerator— flagged only when it's a real generator, not the migratedsessionIdGenerator: undefined.
Every finding carries a confidence (high / medium / low) so you can tune the signal with --min-confidence.
Validated on real servers — 0 false positives
Pointed at the official MCP TypeScript SDK's own example servers, it finds 6 real issues — including the sessionIdGenerator session usage that servers set but rarely spell out as a literal header — and stays quiet on the Mcp-Session-Id and initialize mentions that live only in comments:
legacy-routing.ts:36 BREAKING MCP_SESSION_ID req.headers['mcp-session-id']
legacy-routing.ts:41 BREAKING MCP_SESSION_ID sessionIdGenerator: () => randomUUID()
sse-polling.ts:34 DEPRECATED LOGGING_CAP capabilities: { logging: {} }
6 finding(s): 5 BREAKING, 1 DEPRECATED
Run across a broad corpus of the official reference servers (TypeScript and Python), it produced 0 false positives — precision from structural AST checks, not text matching.
Fix the mechanical one automatically
The -32002 → -32602 swap is purely mechanical, so it's auto-fixable — with a preview first:
npx @booyaka/mcp-vet . --fix --dry-run # show the rewrites, change nothing
npx @booyaka/mcp-vet . --fix # apply them
Drop it into CI
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npx @booyaka/mcp-vet . --github-annotations
It also emits SARIF 2.1.0 for GitHub code scanning, plus Markdown/JSON reports, --json for piping, and inline suppression comments. And it's a typed library, not just a CLI:
import { scan, applyFixes } from '@booyaka/mcp-vet';
const { findings } = scan(['./src'], { /* ... */ });
What it can't tell you (on purpose)
A few 2026-07-28 changes have no reliable static signal — the removed long-lived SSE push channel, the new required Mcp-Method / Mcp-Name headers, auth hardening, and JSON-Schema-2020-12 tool schemas. mcp-vet documents these and prints a reminder after every scan, so a clean result never pretends to mean "fully migrated."
The spec locks in days — better to find out now than when a client stops talking to your server.
Repo: https://github.com/Booyaka101/mcp-vet
Install: npx @booyaka/mcp-vet .

Top comments (1)
Stateless MCP is the kind of change that sounds simple in the spec and turns messy in the glue code around auth, retries, and session assumptions. I like that this checks source patterns locally and fails CI, because most breakage will sit in wrappers and samples people forgot they copied six months ago. The part I'd add to migration plans is exercising client-side assumptions too: a lot of tool reliability bugs only show up when the server is stateless but the client still behaves as if it owns a session.