
Gebruik je een remote MCP-server die leunt op Mcp-Session-Id, een initialize-handshake of state in één open verbinding? Dan is er werk te doen voor de MCP-specificatie van 2026-07-28. In die revisie verdwijnen protocolsessies uit de kern. Dat betekent niet dat je toepassing geen state meer mag hebben. Het betekent dat state expliciet, begrensd en testbaar moet zijn.
De veilige route is: inventariseer eerst waar je transportstate gebruikt, verplaats noodzakelijke context naar een expliciete applicatievorm, kies bewust hoe oude en nieuwe clients naast elkaar mogen bestaan, en test een onderbroken request alsof het een normale productiefout is.
Dit artikel is een documentatiegestuurde tutorial. De voorbeelden zijn geen beschrijving van een klantimplementatie of persoonlijk uitgevoerde migratie.
Wat verandert er voor je MCP server?
De MCP-revisie van 28 juli 2026 maakt de protocolkern stateless. De oude initialize/initialized-uitwisseling en de header Mcp-Session-Id verdwijnen. Een moderne request draagt zelf protocolversie, clientinformatie en clientcapabilities mee. Een client kan met server/discover eerst opvragen wat een server ondersteunt, maar hoeft dat niet altijd te doen. De officiële release-uitleg en het changelog beschrijven deze wijziging.
Het korte antwoord: je hoeft niet alle state te verwijderen. Je moet alleen stoppen met doen alsof de transportverbinding de eigenaar van je state is.
Dat is vooral relevant wanneer je nu een van deze patronen hebt:
- een map met data per
Mcp-Session-Id; - sticky sessions in een load balancer;
- een gateway die pas na het parsen van de JSON-body kan bepalen welke tool wordt aangeroepen;
- een meerstapsflow die alleen werkt zolang één SSE-verbinding open blijft;
- retries die een oude sessie als vanzelfsprekend beschouwen.
Het mentale model: protocolstate is niet hetzelfde als applicatiestate
Een protocol regelt hoe client en server praten. Een toepassing regelt welk werk, welke gebruiker en welke gegevens bij elkaar horen. Die twee lagen lopen in een sessie-ontwerp gemakkelijk door elkaar.
In de moderne MCP-revisie kan elke request op een andere serverinstance landen. Dat werkt goed met een gewone round-robin load balancer, maar alleen als de server niet stiekem afhankelijk is van de vorige verbinding. De specificatiewijziging verwijdert dus transportstate, niet automatisch bedrijfsdata of autorisatie.
Wat verdwijnt uit het protocol
Voor de moderne revisie zijn de handshake en Mcp-Session-Id niet meer de plek om context vast te houden. De specificatie voegt ook header-based routing toe: Mcp-Method en Mcp-Name geven een gateway of rate limiter eerder zicht op methode en toolnaam. Dat maakt routing eenvoudiger, maar is geen vrijbrief om de inhoudelijke controle in je server te verwijderen.
Wat mag blijven bestaan
Een exporttaak, gebruikerskeuze of langlopende operatie kan nog steeds state hebben. Geef die state dan een expliciete eigenaar:
| Soort state | Geschikte plek | Controle |
|---|---|---|
| Kort antwoord zonder vervolg | Nergens; maak de tool request-onafhankelijk | Parallelle requests geven hetzelfde resultaat |
| Langlopende taak | Database of queue, gekoppeld aan een job-ID en geautoriseerde principal | Job-ID mag niet door een andere gebruiker worden gelezen |
| Korte meerstapsvraag | Expliciet, kortlevend request-handle | TTL, integriteit en binding aan gebruiker/methode controleren |
| Inlog- en rechtencontext | Beveiligde identity-laag, niet in het model of in een losse sessieheader | Token, issuer, audience en scopes valideren |
Een expliciet handle is niet per definitie geheim. Behandel het als invoer van een niet-vertrouwde client. In de TypeScript SDK wordt requestState bijvoorbeeld teruggestuurd door de client; de documentatie adviseert daarom integriteitsbescherming, binding aan principal en verloopdatum. Een ondertekening beschermt de integriteit, maar versleutelt de inhoud niet. Zie de migratiehandleiding van de TypeScript SDK.
Stap 1: zoek verborgen sessieafhankelijkheden
Begin niet met een SDK-upgrade. Begin met een inventaris.
Zoek in server, client, gateway en infrastructuur op:
Mcp-Session-Id
sessionId
initialize
initialized
sticky session
connection map
SSE resume
Last-Event-ID
Leg voor elke vondst vier dingen vast:
- Welke informatie zit erachter?
- Wie is de eigenaar: transport, toepassing of identity-laag?
- Hoe lang mag die informatie bestaan?
- Wat gebeurt er als de volgende request op een andere instance of na een fout komt?
Als het antwoord op de laatste vraag “dan vinden we de sessie niet meer” is, heb je een migratiepunt gevonden.
Patroon: van verborgen sessie naar expliciete taak
Stel dat een tool een rapport maakt en een gebruiker vervolgens om bevestiging vraagt. Sla niet de hele werkcontext op onder een verbinding. Maak een taakrecord met een eigenaar, status en verloopdatum. Geef alleen een ondoorzichtig taak-ID terug. Controleer bij iedere vervolgcall opnieuw wie de taak mag zien of bevestigen.
Dat patroon maakt ook een herstart en een andere serverinstance begrijpelijk. Het vervangt geen goed autorisatiemodel: het taak-ID alleen mag nooit de toestemming zijn.
Stap 2: maak state en retries bewust
Een stateless protocol maakt retries niet automatisch veilig. Volgens het changelog gaat een lopende request verloren als de responsstream breekt; de client moet de request opnieuw uitvoeren met een nieuw request-ID. Als een tool vlak vóór die breuk al een e-mail, betaling of wijziging startte, kan blind opnieuw sturen dubbel werk veroorzaken.
Kies daarom per tool een van deze vormen:
- Leesactie: veilig opnieuw proberen als de bron zelf geen bijwerking heeft.
- Schrijfactie: gebruik een idempotency-key of laat de server aantonen dat dezelfde opdracht al verwerkt is.
- Langlopende actie: start een job, geef een job-ID terug en laat de client de status opvragen.
- Meerstapsinput: stuur alleen een kortlevend, getekend handle terug. Bind het aan gebruiker, methode, relevante parameters en een korte TTL.
Voorbeeld: een veilig state-handle ontwerpen
Dit is pseudo-code, geen kant-en-klare productiecode. Het laat zien welke controles het handle nodig heeft.
// patroon — het handle bevat geen geheimen en is niet leesbaar als toestemming
type PendingExport = {
principalId: string;
method: "exports/create";
exportId: string;
expiresAt: string;
};
async function createPendingExportHandle(input: PendingExport) {
assert(input.expiresAt > new Date().toISOString());
return signWithServerKey(input); // integriteit, geen versleuteling
}
async function continueExport(handle: string, currentPrincipalId: string) {
const pending = verifySignatureAndParse<PendingExport>(handle);
assert(pending.expiresAt > new Date().toISOString());
assert(pending.principalId === currentPrincipalId);
assert(pending.method === "exports/create");
return loadExportForPrincipal(pending.exportId, currentPrincipalId);
}
Het belangrijke deel is niet de functienaam, maar de grens: de client mag het handle terugsturen, maar de server verifieert altijd handtekening, geldigheid, gebruiker en toegestane handeling. Bewaar geen tokens, persoonsgegevens of ruwe prompts in een ondertekend maar niet-versleuteld handle.
Stap 3: kies expliciet voor modern, dual support of wachten
“De SDK is bijgewerkt” is geen compatibiliteitsstrategie. De TypeScript SDK v2-documentatie zegt expliciet dat een handmatig gemaakte client of server niet automatisch bytes voor 2026-07-28 op de draad zet. Moderne ondersteuning is een expliciete opt-in. Dezelfde gids beschrijft versionNegotiation en de fallback naar een legacy-era.
Voor een TypeScript-client kan het patroon er zo uitzien:
// voorbeeld — controleer de gebruikte SDK-release voordat je dit overneemt
const client = new Client(
{ name: "inventory-client", version: "1.0.0" },
{ versionNegotiation: { mode: "auto" } }
);
await client.connect(transport);
const era = client.getProtocolEra(); // "modern" of "legacy"
auto is geen excuus om de uitkomst te negeren. Log welk pad is gekozen en houd legacy alleen zolang dat een bewuste, tijdelijke keuze is.
| Keuze | Past wanneer | Vereiste grens |
|---|---|---|
| Direct modern | Je beheert client en server en hebt een kleine, testbare uitrol | Rollback, moderne regressietest en observability zijn klaar |
| Tijdelijk dual support | Oude externe clients aantoonbaar nog nodig zijn | Einddatum, testmatrix per era en telemetry per pad |
| Nog wachten | State, autorisatie of clientcompatibiliteit onbekend is | Eerst inventaris en proof of compatibility uitvoeren |
Voor langdurig werk is een job-queue soms eenvoudiger dan een complexe MCP-flow. En wanneer je een stabiel contract aan veel niet-MCP-clients aanbiedt, kan een gewone API de betere grens zijn. Kies MCP niet omdat het alle integratieproblemen wegneemt.
Stap 4: behandel routing, auth en logging als securitygrenzen
De nieuwe routingheaders kunnen een gateway helpen om op methode en toolnaam te routeren of limieten toe te passen. Valideer die informatie wel op consistente wijze: een edge-regel mag niet de enige bescherming zijn wanneer de toepassing daarna andere body-inhoud uitvoert.
Neem bij de migratie minstens deze controles mee:
- Autorisatie: controleer token, issuer, audience en scopes voor elke request; koppel opgeslagen credentials aan de issuer die ze uitgaf.
- Toolrechten: begin met een allowlist per principal en vraag menselijke bevestiging voor onomkeerbare acties.
- Handles: hanteer korte TTL's, integriteitscontrole en een binding aan de geautoriseerde principal.
- Redirects en callbacks: accepteer geen willekeurige callback-URL's of tokenuitwisseling bij een andere issuer.
- Logging: log protocolera, methode, toolnaam, status, latency en een gehashte correlatiesleutel. Redacteer tokens, volledige prompts, persoonlijke data en gevoelige toolargumenten.
De 2026-07-28-revisie verstevigt onder meer issuer-validatie en isolatie van credentials per authorization server. Die eisen zijn nuttig, maar vormen geen volledig dreigingsmodel voor jouw tools, data en gebruikers. De officiële release-notes beschrijven de auth-wijzigingen; de juiste limieten en controles blijven systeemafhankelijk.
Stap 5: test alsof de load balancer en het netwerk onvriendelijk zijn
Een goede test bewijst geen complete productiebetrouwbaarheid. Hij laat wel zien dat je migratie niet leunt op een toevallige verbinding of instance.
Gebruik vóór een gefaseerde uitrol minstens deze matrix:
| Test | Verwacht resultaat | Controlepunt |
|---|---|---|
| Moderne request op instance A, vervolgrequest op instance B | Geen verlies van toegestane applicatiestate | Geen afhankelijkheid van process-memory of sessieheader |
| Twee parallelle requests van dezelfde gebruiker | Geen state-lek of race condition | Eigenaar en idempotency-key worden afgedwongen |
| Gemanipuleerd of verlopen handle | Request wordt geweigerd zonder detaillek | Handtekening, principal, methode en TTL worden gecontroleerd |
| Gebroken response na gestart toolwerk | Geen onbedoelde dubbele actie | Idempotency of jobstatus maakt herstel expliciet |
| Oude client tegen dual-support server | Voorspelbaar legacy-pad of duidelijke compatibiliteitsfout | Era wordt gemeten en gelogd |
| Nieuwe client met verkeerde versie | Duidelijke protocolfout, geen stille downgrade | Foutcode en fallbackbeleid zijn bekend |
401 of 403 tijdens ontdekking |
Auth-fout, geen gok dat de server legacy is | Credentials en gatewaybeleid worden herzien |
Observability die echt helpt
Maak een dashboard of logquery voor deze velden:
timestamp, protocol_era, protocol_version, mcp_method, tool_name,
route, server_instance, auth_result, status_code, duration_ms,
retry_reason, idempotency_result, correlation_hash
Gebruik een hash of eigen correlatie-ID in plaats van een sessie-ID als opslageenheid voor gevoelige context. Kijk tijdens de gefaseerde uitrol vooral naar onverwachte legacy-fallbacks, fouten rond protocolversies, verlopen handles, retries en verschillen tussen instances.
Veelgemaakte fouten bij een sessieloze MCP-migratie
“Stateless” betekent dat alle state weg moet
Nee. Bedrijfsstate mag bestaan. Verborgen transportstate is het probleem. Maak de eigenaar, levensduur en autorisatie zichtbaar.
Een upgrade installeert automatisch het nieuwe wire protocol
Niet per se. In de TypeScript SDK v2 is moderne ondersteuning expliciet opt-in. Controleer voor jouw SDK de release, de transportentrypoints en de ingestelde versieonderhandeling.
Een signed handle bevat geen gevoelige data
Ook niet per se. Een handtekening maakt een payload niet onleesbaar. Stop er geen geheimen of persoonsgegevens in zonder passende versleuteling en dataminimalisatie.
Een mislukte response mag altijd opnieuw
Nee. Een server kan de toolactie al hebben gestart. Maak schrijfoperaties idempotent of gebruik een jobstatus die de client kan ophalen.
Besliskader: wanneer is dit de juiste stap?
Migreer direct wanneer je de state-eigenaar kent, client en server kunt testen en een rollback hebt. Kies tijdelijk dual support wanneer oude clients echt nodig zijn, maar geef het een einddatum en meet het gebruik. Wacht wanneer de migratie alleen “waarschijnlijk” werkt: onbekende state en onbekende autorisatie zijn redenen om eerst een kleine, afgesloten testopstelling te maken.
De belangrijkste ontwerpvraag is niet “hoe hou ik mijn sessie vast?” maar: “welke context heeft deze tool werkelijk nodig, wie mag die context gebruiken en hoe herstel ik veilig na een fout?” Dat is dezelfde controlelus die nodig is om AI-agenten in productie betrouwbaar te maken. Voor teams die ook coding agents inzetten, blijft code review en een beperkte uitvoeringsgrens nodig; zie Coding agents veilig inzetten in een ontwikkelworkflow.
Samenvatting
De MCP-specificatie van 2026-07-28 haalt sessions uit het protocol, niet uit je toepassing. Een veilige migratie maakt state expliciet, beschermt handles, kiest compatibiliteit bewust en test het gedrag bij parallelle calls, oude clients en gebroken streams.
Wil je een MCP-server, gateway of agentworkflow laten toetsen op state, permissies en testbaarheid? Neem contact op om een MCP- of agentarchitectuur te bespreken.
Bronnen
- Model Context Protocol, David Soria Parra en Den Delimarsky. The 2026-07-28 Specification, gepubliceerd 2026-07-28, geraadpleegd 2026-08-25. Ondersteunt de stateless kern, metadata, routingheaders, MRTR en auth-wijzigingen; bewijst geen volledige ecosystemcompatibiliteit.
- Model Context Protocol-project. Key Changes — 2026-07-28, gepubliceerd 2026-07-28, geraadpleegd 2026-08-25. Ondersteunt de verwijdering van protocol-level sessions en het gedrag bij verbroken responsstreams; is geen implementatiehandleiding voor elke SDK.
- Model Context Protocol TypeScript SDK. Supporting protocol revision 2026-07-28, publicatiedatum niet vermeld op de geraadpleegde hoofdbranch, geraadpleegd 2026-08-25. Ondersteunt expliciete modern-protocolopt-in, version negotiation en de behandeling van
requestState; geldt niet automatisch voor andere SDK's of vastgepinde oudere releases.