Blog/MI-ágensek
MCP 2026-07-28 migrációs útmutató: mi változik az állapotmentes MCP szervereknél
Az MCP 2026-07-28 eltávolítja a sessionöket és az initialize kézfogást. Szerveroldali változások: _meta, server/discover, MRTR, engedélyezés, migrációs checklist.
Balázs Csorba··9 perc olvasás
- MCP
- Protocol migration
- Stateless APIs
- OAuth
- Agents

A lényeg röviden
- Az MCP 2026-07-28, 2026. július 28-án kiadva, eltávolítja az initialize kézfogást és az Mcp-Session-Id fejlécet, így minden kérés maga hordozza a verzióját és a képességeket.
- A szervereknek implementálniuk kell a server/discover-t; a kliensek hívhatják elsőként, vagy küldhetnek bármilyen kérést, és kezelniük kell az UnsupportedProtocolVersionError-t.
- A Multi Round-Trip Requests leváltja a szerver által kezdeményezett elicitationt, samplinget és rootsot: a szerver input_required eredményt ad vissza, a kliens pedig inputResponses-szal újraküldi.
- A hívások közötti állapot explicit handle-ökbe kerül, amelyek eszközargumentumként mennek tovább, a requestState-et pedig integritásvédetten kell kezelni, mert támadó kontrollálja.
- A Roots, a Sampling, a Logging és a Dynamic Client Registration deprecated, a legkorábbi eltávolítás a 2027. július 28-án vagy később megjelenő első revízióban esedékes.
Az MCP 2026-07-28 a Model Context Protocol 2026. július 28-án kiadott revíziója, és az állapottartó, sessionalapú protokollból állapotmentes kérés/válasz protokollt csinál belőle. Az initialize kézfogás és az Mcp-Session-Id fejléc eltűnt, minden kérés leírja magát, és a szerverek egy hívás közben már nem küldhetnek kérést a kliensnek. Bárki számára, aki MCP szervert üzemeltet, ez a legnagyobb breaking change, ami a távoli MCP megjelenése óta volt.
Ez a cikk megmutatja, mi változik valójában annak, aki MCP szervert ír, 2026. szeptemberében: hogyan áll össze egy állapotmentes kérés, mi váltja fel a szerver által kezdeményezett kéréseket, hová kerül a hívások közötti állapot, mi változott az engedélyezésben, és mikor jönnek a deprecated feature-ök. Jön egy migrációs checklist is, egy teszttervvel. Minden alább a hivatalos changelogből és a kiadási bejegyzésből származik; ahol a spec szövege az igazság forrása, oda linkelek.
Miért dobta el az MCP a sessionöket?
Az MCP azért dobta el a protokollszintű sessionöket, mert azok miatt nehezen lehetett szervert skálázni: egy session egy szerverpéldányon élt, így minden későbbi kérésnek ugyanazt a példányt kellett elérnie. Ha megszűnnek, bármelyik kérés bármelyik példányra kerülhet egy szokásos load balancer mögött.
A 2026-os roadmap (2026. március 9.) a „Transport Evolution and Scalability” témát teszi az első helyre a négy prioritás közül, és közvetlenül megnevezi a problémát: az állapottartó sessionök összeütköznek a load balancer-ekkel, a horizontális skálázáshoz pedig kerülőutak kellettek. A gyakorlatban ez sticky routingot, megosztott session store-t vagy mindkettőt jelentette. A serverless platformoknál rosszabb volt a helyzet, mert ott eleve nincs hosszú életű folyamat, amely egy sessiont tartana.
A kiadási bejegyzés egy mondatban megfogalmazza a célt: minden kérés mostantól bármelyik szerverpéldányra kerülhet egy egyszerű round-robin load balancer mögött, közös tároló nélkül. A changelog 9 nagy és 12 kisebb változást sorol fel az előző revízióhoz, a 2025-11-25-höz képest. A nagyok többsége ennek az egyetlen döntésnek a következménye.
Hogyan működik egy állapotmentes MCP kérés?
Egy állapotmentes MCP kérés magában hordoz mindent, amire a szervernek szüksége van: a protokollverzió és a kliens képességei minden hívásban a _meta mezőben utaznak, a HTTP kérések pedig a fejlécekben megismétlik a metódust és az eszköz nevét. Nincs kézfogás, amit meg kellene jegyezni.
A 2025-11-25 alatt a kliens initialize-t küldött, visszakapta a képességeket és egy session ID-t, megerősítette notifications/initialized-del, majd a session ID-t minden hívásra rátette. A 2026-07-28 alatt die verziózási szabályok kérésenként érvényesek:
- Az
io.modelcontextprotocol/protocolVersionés azio.modelcontextprotocol/clientCapabilitiesminden kérés_metamezőjében kötelező. Egy kérés, amelyben ezek nincsenek, hibás, és-32602-t (Invalid params) kap HTTP 400-zel. - Az
io.modelcontextprotocol/clientInfolegyen minden kérésben, a szerverek pedig adják vissza azio.modelcontextprotocol/serverInfo-t minden eredmény_metamezőjében. Mindkettő önbevallás, és nem szabadhat biztonsági döntéseket. - Ha a szerver nem támogatja a kért verziót,
UnsupportedProtocolVersionError-t (-32022) ad vissza egysupportedlistával, és a kliens a lista egyik verziójával újrapróbálkozik. - A szervereknek kötelező implementálniuk az új
server/discoverRPC-t, amely verziókat, képességeket és identitást hirdet. A kliensek hívhatják elsőként, de nem kötelesek. - Streamable HTTP-n a POST kéréseknek hordozniuk kell az
MCP-Protocol-Version,Mcp-Method, éstools/call,resources/readilletveprompts/getesetén aMcp-Namefejlécet (SEP-2243). Ha egy fejléc ellentmond a törzsnek, a szerver 400-at adHeaderMismatchhibával (-32020). A gatewayek és a WAF-ek mostantól fejlécek alapján tudnak útvonalazni és sebességkorlátot szabni anélkül, hogy JSON-t parseolnának.
Egy tools/call kérés az új revízióban így néz ki (szemléltető példa, a spec mezőneveit követve):
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search_issues
{"jsonrpc": "2.0", "id": 7, "method": "tools/call",
"params": {"name": "search_issues", "arguments": {"query": "status = Open"},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {"elicitation": {}},
"io.modelcontextprotocol/clientInfo": {"name": "my-agent", "version": "1.4.0"}
}}}Mi váltja fel a szerver által kezdeményezett kéréseket? Multi Round-Trip Requests
A Multi Round-Trip Requests (MRTR, SEP-2322) a szervertől a kliens felé menő elicitation/create, sampling/createMessage és roots/list kéréseket váltja fel. Ahelyett, hogy a szerver egy nyitva tartott streamen, a hívás közben meghívná a klienst, egy „input required” eredménnyel zárja a kérést, a kliens pedig újraküldi az eredeti kérést, a válaszokkal együtt.
Az MRTR oldal a specben definiálja a folyamatot. A szerver InputRequiredResult-et ad vissza resultType: "input_required" mezővel, egy inputRequests térképpen (a kulcsok a szerver által választott ID-k, az értékek elicitation, sampling vagy roots kérések), és egy opcionális, átlátszatlan requestState-tel. A kliens összegyűjti a válaszokat, majd újraküldi az eredeti hívást inputResponses-szal, ugyanazokkal a kulcsokkal, visszaküldi a requestState-et, és új JSON-RPC id-t használ. Ezzel az első kérés befejeződött; az újraküldés önálló kérés, amelyet bármelyik példány kezelhet.
Egy megerősítést igénylő eszköz rövidített közbenső eredménye így néz ki:
{"jsonrpc": "2.0", "id": 1, "result": {
"resultType": "input_required",
"inputRequests": {
"confirm_transition": {
"method": "elicitation/create",
"params": {"mode": "form", "message": "Move PROJ-42 to Done?",
"requestedSchema": {"type": "object",
"properties": {"confirm": {"type": "boolean"}}, "required": ["confirm"]}}
}
},
"requestState": "<HMAC-protected blob>"
}}A spec három szabálya megváltoztatja, hogyan írod ezt a kódot:
- A
requestStatetámadó által kontrollált bemenet. Ha hatással van az engedélyezésre, az erőforrás-hozzáférésre vagy az üzleti logikára, meg kell védened az integritását (HMAC vagy AEAD), és el kell utasítanod azokat az állapotokat, amelyek nem mennek át az ellenőrzésen. A spec azt javasolja, hogy kösd bele a hitelesített Principalt, egy rövid lejáratot és az eredeti kérés digestjét. Ha egy állapotot legfeljebb egyszer szabad használni, ezt szerveroldalon kényszerítsd ki. - Csak a
tools/call, aprompts/getés aresources/readadhat visszaInputRequiredResult-et, és csak olyan kérés típusokkal, amelyeket a kliens a képességeiben deklarált. - Minden eredményhez most
resultTypekell:"complete"a normál eredményekhez. A kliensek a régebbi szerverektől érkező hiányzó mezőt complete-nek tekintik, az új szerver viszont mindig küldje el.
Az MRTR az időzítést is megváltoztatja. A kliens lehet, hogy soha nem küldi újra, ezért egy eszköz nem hagyhat félkész munkát hátra, amíg a válaszra vár. A mellékhatást a megerősítés után vidd végbe, nem előtte.
Hová kerül most az állapot? Handle-ök, Tasks és subscriptions
A hívások közötti állapot kikerül a transportból az eszközökbe: egy eszköz explicit handle-t gyárt, visszaadja, a modell pedig szokásos argumentumként adja tovább. A hosszú futású munka a Tasks extensiont használja, az változásértesítések pedig az új subscriptions/listen streamet.
Explicit handle-ök
A tools spec egy kosarat használ példaként: a create_basket a bsk_a1b2c3-at adja vissza, az add_item pedig a basket_id-t veszi paraméterként. A kiadási bejegyzés szerint ez jobban működik, mint a rejtett session-állapot, mert a modell látja a handle-t, és átadja az egyik eszköztől a másiknak. A spec design-megjegyzéseit érdemes átvenni a review checklistédbe: hitelesített szervereknél a handle név, nem jogosultság, ezért hívásonként ellenőrizd a hívó engedélyeit; a handle-ök maradjanak átlátszatlanok; a létrehozó eszköz leírásában mondd ki a megőrzési szabályt; és lejárt handle esetén adj egy eszközhívási hibát (tool execution error) vissza, hogy a modell maga kijavíthassa.
Tasks és subscriptions
A Tasks kikerült az experimentális magból a hivatalos io.modelcontextprotocol/tasks extensionbe (SEP-2663). A blokkoló tasks/result helyére polling jön tasks/get-tel, az új tasks/update a kliens felől érkező bemenetet szállítja, a tasks/list pedig megszűnt. Az extensionöket egy új extensions mező egyezteti ki a kliens- és szerverképességekben.
A régi HTTP GET végpont és a resources/subscribe helyére a subscriptions/listen lép: egyetlen hosszú életű POST válaszstream, amelyben a kliens feliratkozik olyan értesítéstípusokra, mint a toolsListChanged. A stream folytathatósága is eltűnt: ha a válaszstream elszakad, elveszik a folyamatban lévő kérés, és a kliensnek új azonosítóval újra kell küldenie. Ez az idempotencia a te problémád. Ha egy eszközhívás kétszer is elküldhető, akkor biztonságosan kétszer lefuthat, vagy hordozzon egy kulcsot, amivel felismered a duplikátumot.
A listázási eredményeket olcsóbb cache-elni. A tools/list, prompts/list, resources/list, resources/read és resources/templates/list tartalmaznia kell a ttlMs és cacheScope mezőket ("public" vagy "private"), és a szervereknek determinisztikus sorrendben kell visszaadniuk az eszközöket. A stabil eszközlista melegen tartja a kliens prompt cache-ét, és ez költségkérdés (lásd prompt caching és routing).
Mi változott az MCP engedélyezésében?
A 2026-07-28 engedélyezési változások lezárom egy engedélyezőszerver-összekeveredési rést, a kliens credentialöket ahhoz a szerverhez kötik, aki kiállította őket, és formálisan elavultnak jelölik a Dynamic Client Registrationet a Client ID Metadata Documents (CIMD) javára.
- Issuer-validáció (SEP-2468). Az engedélyezőszervereknek az
issparamétert kellene bele foglalniuk az engedélyezési válaszba a RFC 9207 szerint, a klienseknek pedig egy jelen lévőiss-t ellenőrizniük kell a rögzített issuer ellen, mielőtt beváltják a kódot. - Credentialök issuer szerint kulcsolva (SEP-2352). A klienseknek a tárolt credentialöket issuer-azonosító szerint kell kulcsolniuk, nem szabad más engedélyezőszerverrel újrahasznosítaniuk őket, és újra kell regisztrálniuk, ha az engedélyezőszerver megváltozik.
application_typea regisztrációnál (SEP-837). Ezért láttak egyes desktop- és CLI-kliensekredirect_urihibákat a localhost callbackeknél.- CIMD DCR helyett. A CIMD esetén a kliens ID egy HTTPS URL, amely egy JSON dokumentumra mutat, amiben legalább
client_id,client_nameésredirect_urisvan. Az engedélyezőszerverek aclient_id_metadata_document_supportedmezővel jelzik a támogatást. A DCR a visszafelé kompatibilitás miatt még mindig működik.
Ha a szervered csak tokeneket validál, ennek nagy része a kliensre és az engedélyezőszerverre esik. A te szervered feladata nem változik, és továbbra is szigorú: csak azokat a tokeneket fogadd el, amelyek neked lettek kiállítva, és soha ne add tovább őket felsőbb szintű API-knak. Az MCP szerver biztonsági checklist foglalkozik ezzel az oldallal.
Mi deprecated, és mikor ne siessünk a migrációval?
A Roots, a Sampling és a Logging deprecated (SEP-2577), és ugyanígy a Dynamic Client Registration és a régi HTTP+SSE transport. Eddig semmit nem távolítottak el, szóval a valódi trade-off nem az, hogy „migrálok vagy törem”, hanem hogy mennyi ideig üzemeltetsz egy szervert, amely még mindkét korszakot szolgálja.
A deprecated feature-ök registryje a Roots, a Sampling, a Logging és a DCR legkorábbi eltávolítását arra a revízióra teszi, amely 2027. július 28-án vagy később jelenik meg. A javasolt migrációk konkrétak: a könyvtárakat add át eszközparamétereken vagy konfiguráción keresztül a Roots helyett, hívd közvetlenül az LLM szolgáltatót a Sampling helyett, és logolj stderr-re vagy OpenTelemetrybe a Logging helyett. A ping és a logging/setLevel már kikerült a protokollból; a log szint most kérésenként mint io.modelcontextprotocol/logLevel utazik.
A terepen lévő kliensek nem egyszerre fognak átállni, ezért a spec definiál egy visszafelé kompatibilitási utat. Egy modern kliens először modern kéréssel próbál, és csak akkor esik vissza az initialize-re, ha egy 400 válasz törzse nem modern JSON-RPC hiba. Egy szerver, amely csak az új revíziót beszéli, a HTTP GET és DELETE kérésekre 405-öt válaszoljon, hagyja figyelmen kívül az Mcp-Session-Id-t anélkül, hogy kiállítana egyet, és hagyja figyelmen kívül a Last-Event-ID-t.
A véleményem: ha minden kliensed SDK-alapú, és te irányítod őket, egy lépésben migrálj. Ha olyan harmadik felek hosztjait szolgálod ki, amelyeket nem kontrollálsz, futtasd egy ideig mindkét korszakot, és figyeld az MCP-Protocol-Version-t a hozzáférési naplókban, hogy eldöntsd, mikor ejtsd el a legacy útvonalat. A négy Tier 1 SDK (TypeScript, Python, Go és C#) támogatja a revíziót, Rustban beta, így a migráció nagyrészt SDK-frissítés meg a fenti designváltozások.
| 2025-11-25 mechanizmus | 2026-07-28 | Mit kell változtatni a szervereden |
|---|---|---|
az initialize kézfogás | Eltávolítva; verzió és képességek minden _meta-ban | Olvasd kérésenként; adj vissza -32022-t a támogatott verziókkal |
| Semmi | server/discover (a szervereknek implementálniuk kell) | Hirdesd a verziókat, képességeket és az identitást |
Mcp-Session-Id | Eltávolítva | Vidd az állapotot explicit, autorizált handle-ökbe |
| Szerver által kezdeményezett elicitation, sampling, roots | MRTR: input_required + újraküldés | Adj vissza InputRequiredResult-et; írd alá a requestState-et |
GET stream, resources/subscribe | subscriptions/listen | A GET és DELETE kérésekre 405-öt válaszolj |
Last-Event-ID folytathatóság | Eltávolítva | Tedd biztonságossá az eszközhívások újraküldését |
Experimentális tasks, tasks/result | Tasks extension, tasks/get polling | Pollolj; hagyd ki a tasks/list-et |
| Csak JSON törzs | Mcp-Method / Mcp-Name fejlécek | Utasítsd el a fejléc-törzs eltéréseket (-32020) |
Nem található erőforrás -32002 | -32602 | Frissítsd a hiba-leképezést és a teszteket |
MCP 2026-07-28 migrációs checklist és tesztterv
Egy MCP szerver átállítása 2026-07-28-ra lényegében arról szól, hogy frissítsd az SDK-t, vedd ki minden sessionre épülő feltételezést, és bizonyítsd, hogy két egymás utáni kérés két különböző példányra eshet. Ebben a sorrendben dolgoznék:
- Frissíts egy Tier 1 SDK-ra, amely 2026-07-28-at beszél, és előbb olvasd el a migrációs jegyzeteit; az SDK-k elnyelik a legtöbb transportváltozást.
- Keress a kódodban session ID-kre és kapcsolatonkénti cache-ekre. Mindegyiket cseréld explicit handle-re vagy a kérésben szereplő adatra.
- Implementáld a
server/discover-t, és add vissza aserverInfo-t az eredmény_metamezőjében. - Írd át minden szerver által kezdeményezett kérést MRTR-re, ahol a
requestStateintegritása védett, és kösd a felhasználóhoz, a lejárathoz és a kéréshez. - Add hozzá a
resultType,ttlMséscacheScopemezőket, és rendezd atools/list-et determinisztikusan. - Ellenőrizd az
Mcp-MethodésMcp-Namefejléceket a törzssel szemben, és frissítsd a hibakódokat (-32602,-32020→-32022). - Cseréld le a Roots, Sampling és Logging elemeket eszközparaméterekkel, közvetlen szolgáltatóhívásokkal és OpenTelemetryvel. A trace kontextusnak mostantól dokumentált
_metakulcsai vannak (traceparent, SEP-414). - Döntsd el, meddig tartasz mindkét korszakot, és naplózd minden kérés protokollverzióját.
Tesztterv
- Futtass két példányt round-robin mögött, és a több hívásból álló munkafolyamat minden lépését küldd a másikra.
- Szakíts meg egy válaszstreamet a hívás közben, és ellenőrizd, hogy az újraküldött hívás nem végez dupla munkát.
- Módosítsd, játsszad vissza és járts le egy
requestState-et; mindhármat el kell utasítani. - Mutass be egyik felhasználó handle-jét a másik felhasználó tokenjével; ennek el kell buknia.
- Irányíts egy régi 2025-11-25 klienst a szerverre, és erősítsd meg a választott visszaesést.
Az állapotmentes transport megváltoztatja azt is, hogyan kell gondolkodni az eszköztervezésen, mert a handle-ök és a megerősítések mostantól az eszközeid sémáiban vannak. Erről a cikkben írtam: azokról az MCP eszközökről, amelyeket az ügynökök jól választanak ki. Ha a saját szervereidre tervezel ilyen migrációt, az része annak, amit AI mérnökként csinálok.
Források
- The 2026-07-28 Specification – MCP blog, 2026. július 28.
- MCP 2026-07-28 Key Changes (changelog)
- MCP 2026-07-28: Versioning and Compatibility
- MCP 2026-07-28: Streamable HTTP transport
- MCP 2026-07-28: Multi Round-Trip Requests
- MCP 2026-07-28: Tools (state handles)
- MCP 2026-07-28: Client registration (CIMD)
- MCP 2026-07-28: Deprecated features registry
- The 2026 MCP Roadmap – MCP blog, 2026. március 9.
- RFC 9207: OAuth 2.0 Authorization Server Issuer Identification
Gyakori kérdések
Támogatja még az MCP 2026-07-28 az initialize kézfogást?
Nem. A 2026-07-28 revízió eltávolítja az initialize-et és a notifications/initialized-et. Helyette minden kérés a _meta mezőben hordozza a protokollverzióját és a kliens képességeit. Egy szerver továbbra is kiszolgálhat régebbi klienst úgy, hogy a 2025-11-25 viselkedést is implementálja, a modern kliensek pedig akkor esnek vissza az initialize-re, ha egy 400 válasz törzse nem felismert modern JSON-RPC hiba.
Hogyan tartsak állapotot az MCP eszközhívások között session nélkül?
Gyárts egy explicit handle-t egy eszközben, például egy kosár- vagy munkafolyamat-azonosítót, add vissza az eredményben, és fogadd el szokásos argumentumként a későbbi hívásokban. Tárold az állapotot szerveroldalon azzal a kulccsal, hívásonként ellenőrizd a hívó engedélyét a handle-re, maradjon a handle átlátszatlan, és adjon a szerver egyértelmű hibát, ha a handle lejárt.
Mi a requestState az MCP Multi Round-Trip Requestsben?
A requestState egy átlátszatlan string, amelyet a szerver az input_required eredménnyel ad vissza, és a kliens az újraküldéskor visszaküld. Ez teszi lehetővé, hogy egy állapotmentes szerver folytassa a munkáját. A spec támadó által kontrollált bemenetnek tekinti: ha hatással van az engedélyezésre vagy az üzleti logikára, védd HMAC-kel vagy AEAD-del, kösd a felhasználóhoz, egy rövid lejárathoz és az eredeti kéréshez, és utasítsd el, ami nem megy át az ellenőrzésen.
Mikor távolítják el a Roots, a Sampling és a Logging elemet az MCP-ből?
A 2026-07-28 revízióban deprecatedek, de még teljesen működnek. A deprecated feature-ök registryje a legkorábbi eltávolításként azt a spec revíziót adja meg, amely 2027. július 28-án vagy később jelenik meg, a tényleges eltávolítást viszont a maintainer dönti el. A javasolt helyettesítők: a Roots helyett eszközparaméterek vagy konfiguráció, a Sampling helyett közvetlen LLM szolgáltatóhívás, a Logging helyett pedig stderr vagy OpenTelemetry.