MCP 2026-07-28: Як специфікація без стану змінює дизайн віддалених серверів
Специфікація MCP 2026-07-28 переходить у безстановий режим: без сеансів чи процедури взаємодії, а також без MRTR, завдань та підказок кешу. Які зміни відбуваються для віддалених серверів та як їх мігрувати.
Джерела: MCP Just Changed Its Architecture: Why the 2026 Specification Makes MCP Truly Cloud-Native
Переломний момент для MCP
Ревізія 2026-07-28 Протоколу контексту моделі є значно важливішою подією, ніж звичайне оновлення версії. Вона скасовує одне з основних припущень MCP, а саме те, що віддалений сервер організований навколо сеансу протоколу, пов’язаного з підключенням. MCP відійшла від моделі зі станом та двостороннього обміну даними до моделі без стану з запитами та відповідями, яка функціонує як звичайна розподілена інфраструктура HTTP. У повідомленні про кандидата на випуск його назвали найбільшою ревізією з моменту запуску протоколу, а остаточна специфікація була оприлюднена 28 липня 2026 року.
Stateful MCP не був нездатний до роботи. Проблема полягала у тому, що стан на рівні протоколу створював операційні обмеження, які ускладнювали роботу на сучасних хмарних платформах. Для віддаленого розгортання можливо було знадобитися пам’ятати ідентифікатор сеансу, прив’язати цей сеанс до певного бекенду, координувати стан між копіями та підтримувати функціонування механізмів довготривалої комунікації для взаємодій, які насправді були просто запитами та відповідями. Це піддається керуванню у невеликих масштабах. У великих масштабах це створює ті самі проблеми, з якими роками борються веб-системи з функцією sticky-session.
У новому дизайні сесія протоколу була видалена, а процедури initialize та initialized також прибрані. Кожен запит містить необхідні метадані клієнта, а сервери стають доступними через пряме виявлення. Взаємодія між сервером та клієнтом реорганізована у формат багатократних запитів, HTTP-заголовки несуть метадані маршрутизації, клієнти отримують підказки щодо кешування у відповідях на запити до списків та ресурсів, тривалі операції переміщуються до розширення Tasks, управління життєвим циклом розширень урегулюовано, а також запроваджена суворіша політика виходу з ужитку. У результаті отримується ядро MCP, яке легко інтегрується після звичайних балансерів навантаження, шлюзів, брандмауерів веб-додатків та безсерверних чи автомасштабованих рішень.
Один психологічний модель допомагає. Старий віддалений MCP функціонував як протокол розподіленого діалогового з’єднання, тоді як нова версія працює як HTTP API, чия станова поведінка чітко визначається на рівні додатку або розширення.
Чому MCP, заснований на сеансах, виявився непідходящим
Фразу „становий MCP перестав працювати“ потрібно розглядати уважно, адже становий MCP не перестав функціонувати раптово. Сталося так, що стан, керований протоколом, почав все гірше підходити до інфраструктури, де розгорталися сервери MCP.
У попередній версії клієнт ініціював зв’язок за допомогою запиту initialize, а сервер відповідав значенням Mcp-Session-Id, яке мусив міститися в кожному наступному запиті. Це пов’язувало логічного клієнта із сеансом на стороні сервера. Власний приклад ранньої та пізньої версій від розробників чітко демонструє різницю: у старій схемі був необхідний запит на ініціалізацію перед фактичним викликом інструменту, тоді як протокол 2026 дозволяє надсилати виклик інструменту безпосередньо як окремий самодостатній запит.
Операційні наслідки мають більше значення, ніж заощаджена HTTP-запит. Уявіть собі сервіс MCP із вісьмома репліками за балансувальником навантаження. За наявності сеансів перший запит створює сеанс на інстанції A, а другий запит змушений знову доходити до інстанції A, якщо тільки стан сеансу не є спільним. Це змушує обирати між двома стратегіями: «липке» маршрутизування, коли один і той самий клієнт постійно звертається до однієї і тієї самої інстанції, або спільний сховище сеансів, яке може читати кожна інстанція. Обидві стратегії пов’язують поведінку протоколу з топологією розгортання.
«Липке» маршрутизування позбавляє систему гнучкості, оскільки балансувальник навантаження більше не може направляти кожен запит до тієї інстанції, яка має вільну потужність. Один вузол може бути перевантажений, тоді як інший залишається без роботи, оскільки сеанси прив’язані до певних інстанцій, а перехід на резервний варіант ускладнюється, якщо початковий стан зберігається на вузлі, який зник.
Зберігання сеансів у спільному сховищі вирішує частину проблеми, але створює проблеми, характерні для розподілених систем. Кожен сеанс перетворюється на запис, який необхідно створювати, копіювати, призупиняти дію, видаляти та підтримувати доступністю в будь-який час. У цьому випадку сервер MCP є додатком, який містить підсистему керування станом сеансів, розташовану на кількох машинах. Кандидатська версія продукту вказує на «липкі сеанси» та спільні сховища як інфраструктуру, яка більше не є необхідною на рівні протоколу після зникнення сеансів.
Kubernetes, платформи для автомасштабування контейнерів, хмарні функції та безсерверні середовища роблять цю проблему ще більш очевидною. Запит може потрапити на под A, цей под може зникнути під час масштабування, а наступний запит — на под F. Для безстанового HTTP-сервісу це цілком нормально, але це завдає проблем протоколу, коректність якого передбачає наявність стану, пов’язаного зі з’єднанням.
Старий протокол мав ще одну концептуальну невідповідність. Він використовував двосторонню модель, у якій сервери могли надсилати запити до клієнта. Процеси отримання даних, вибірки та відображення структури залежали від цього підходу, що було доцільним за наявності постійного каналу зв’язку. Однак постійні двосторонні потоки навантажують інфраструктуру, адже фаєрволи, проксі, шлюзи, засоби автоскейлінгу, середовища без серверів та пули з’єднань мають власні таймаути та цикли життя. Підтримання відкритого потоку лише для того, щоб сервер міг пізніше поставити запитання, принципово відрізняється від звичайних запитів та відповідей у форматі HTTP.
Розробник, який протестував його самостійно, навів конкретний приклад переваг. Він назвав новий безстановий протокол значно простішим для реалізації як з боку клієнта, так і з боку сервера, та зазначив, що додатки більше не відстежують ідентифікатори сеансів на сервері чи не спрямовують сеанс назад на певну машину. Він також створив переглядач MCP без стану та випустив нову інтеграцію Datasette MCP.
Отже, суть не в тому, що стан є поганим. Прихований стан протоколу є дорогим у утриманні, тоді як явний стан додатку піддається керуванню.
Сеанс та процедура взаємодії зникли
Першою зміною, яку помічають користувачі, є те, що сеанс протоколу більше не існує. У 2026-07-28 зникає обмін даними initialize та notifications/initialized, а також заголовок Mcp-Session-Id. Кожен запит тепер містить версію протоколу та можливості клієнта у полі _meta. Клієнт, який хоче дізнатися про сервер заздалегідь, може викликати функцію server/discover. У остаточному списку змін обидві видалені частини — сеанс та процедура встановлення зв’язку — класифікуються як значні зміни.
Раніше процес виглядав так: спочатку відбувалося встановлення зв’язку, а потім — справжній запит:
Client
|
| initialize
v
MCP Server
|
| Mcp-Session-Id = ABC
v
Client
|
| tools/call + Mcp-Session-Id: ABC
v
Same logical server session
Тепер дзвінок може відбутися безпосередньо:
Client
|
| tools/call
| protocol version
| capabilities
| client metadata
v
Load Balancer
|
+----> MCP Instance A
|
+----> MCP Instance B
|
+----> MCP Instance C
Запит тепер містить усі контекстні дані, необхідні рівню протоколу для його розуміння. Крім того, Streamable HTTP копіює ключові метадані у заголовки, наприклад, у цьому запиті:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
Тіло запиту залишається джерелом істини, тоді як HTTP-запакування надає метадані, які можуть використовуватися проміжними серверами. Специфікація вимагає, щоб проміжні сервери та канали передачі відхиляли несумісні комбінації заголовків та тіла запиту за потреби.
Видалення сеансу не означає, що додатки не можуть мати стан. Стан додатку просто стає частиною моделі даних. Наприклад, процес покупок може повернути ідентифікатор кошика:
{
"basket_id": "bsk_8f2a..."
}
і наступне викликання інструменту передасть цей хендл назад разом із елементом:
{
"basket_id": "bsk_8f2a...",
"item_id": "SKU-123"
}
На серверній стороні ідентифікатор шукається в Redis, PostgreSQL, DynamoDB, Cosmos DB, сховищі об’єктів або будь-якій іншій підходящій системі. Механізм передачі даних MCP більше не керує цим станом. Розробники рекомендують використовувати явні ідентифікатори, такі як basket_id та browser_id, як спосіб заміни прихованого протокольного стану.
Це призводить до архітектурного розділення, яке показано тут:
MCP protocol state
|
v
NONEApplication state
|
v
Explicit IDs + external state store
Long-running task state
|
v
Tasks extension + durable task store
Це, мабуть, найважливіша ідея в усій цій версії.
Метадані та виявлення за запитом
Якщо процес встановлення зв’язку відсутній, як сервер дізнається, яку версію протоколу та які можливості підтримує клієнт? Відповідь — це метадані за запитом. Зарезервовані поля _meta знаходяться в просторі імен io.modelcontextprotocol/*, а версія протоколу та можливості клієнта додаються до кожного запиту, без необхідності одноразових переговорів, які б з’являлися у пам’яті з’єднання. Коли клієнт вирішує ідентифікувати себе, його ідентичність також передається у вигляді метаданих за запитом, а сервери можуть додати свої метадані до результату. Концептуально запит виглядає ось так:
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "search",
"arguments": {
"query": "MCP stateless architecture"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
},
"io.modelcontextprotocol/clientInfo": {
"name": "my-agent",
"version": "3.2.0"
}
}
}
}
Коли інформація на початку є корисною, сервер реалізує server/discover. Остаточний ченджлог робить цей механізм обов’язковим для серверів, щоб клієнти могли дізнатися про підтримувані версії протоколу, можливості та ідентичність сервера перед виконанням будь-яких інших дій. Це зручно, коли клієнту потрібно вибрати свою поведінку на основі того, що підтримує сервер.
Тут існує тонка різниця. Клієнти можуть вирішити не викликати server/discover, але сервери зобов’язані його надавати. Тому MCP більше не потребує механізму відкриття інформації для встановлення сеансу, проте все ще пропонує формальний спосіб активного перевірення можливостей. Цей підхід схожий на зрілі HTTP-API, де кожен запит можна індивідуально інтерпретувати, а необов’язкові кінцеві точки відкриття інформації чи метадані надають більш детальну інформацію.
Маршрутизація за принципом round-robin та масштабування до нуля
Тут дизайн найбільш очевидно проявляє свою ефективність у хмарній архітектурі. Без сеансів протоколу кінцева точка MCP може працювати за допомогою звичайного балансувальника навантаження зі звичайним механізмом розподілу за принципом «коло-робін». У офіційному оголошенні це представлено як бажаний результат: кілька інстанцій MCP, розподіл за принципом «коло-робін» та відсутність спільного сховища сеансів протоколу.
Візьмемо три репліки за балансувальником навантаження:
+------------------+
| Load Balancer |
+---------+--------+
|
+------------+------------+
| | |
v v v
MCP Pod A MCP Pod B MCP Pod C
Запит 1 може потрапити до A, запит 2 — до C, а запит 3 — до B. Жодне правило протоколу не вимагає, щоб усі три запити потрапили до однієї й тієї самої інстанції, що саме є бажаною властивістю хмарних систем.
Припустимо, що горизонтальний автоскалер подів вирішує, що протягом ночі потрібна лише одна копія. Дві інстанції можуть зникнути. Коли пізніше надходить запит, може бути запущена нова інстанція, яка зможе негайно його обробити, оскільки їй не потрібно спочатку відновлювати сеанс протоколу. Архітектура стає такою:
Сам сервіс MCP є безстановим, а бізнес-дані зберігаються стабільно поза ним.
Однак існує один недолік. Безстановий MCP не змушує автоматично кожен додаток MCP скорочувати свою роботу до нуля. Якщо додаток зберігає кошик, робочий процес, розмову, транзакцію чи завдання лише у оперативній пам’яті, він просто створює проблему прихованого стану на наступному рівні.
Справжнє зведення до нуля вимагає, щоб все, що має вижити після зупинки процесу, знаходилося у міцній інфраструктурі. Одним із можливих варіантів для продакшну є використання Redis для короткочасної координації, PostgreSQL або керованої NoSQL-бази даних для зберігання постійного стану додатку, а також сховища об’єктів для великих файлів. Аутентифікація також здійснюється поза межами процесу, за допомогою систем авторизації OAuth чи OIDC, а не на основі даних з локальної пам’яті.
Компроміс є очевидним. Протокол уможливлює використання безстанової інфраструктури, і тепер розробник додатку несе відповідальність за вирішення питань щодо того, який стан має зберігатися, де він знаходиться, як він авторизовується, як довго він залишається та як його очищують. Це більш здорові межі проектування систем.
Керування станом самостійно
Явні ідентифікатори можуть стати найбільш значущим результатом цієї моделі. Візьмемо агента для закупівель на основі ШІ, якому наказано замовити 100 GPU, отримати схвалення та подати замовлення. Дизайн, заснований на сеансах, міг би легко приховати цей процес у стані сеансу MCP. Нова архітектура спрямована на те, щоб все було видимим – створення запиту повертає ідентифікатор:
create_purchase_request()
|
v
purchase_request_id = pr_123
|
v
request_approval(pr_123)
|
v
approval_id = appr_789
|
v
submit_purchase(pr_123, appr_789)
Стан більше не є неявною частиною HTTP-сесії. Це дані домену, і це має велику перевагу, оскільки дані домену можна захистити, перевірити, версіонувати, копіювати та запитувати незалежно. Запис стану концептуально може виглядати ось так:
{
"purchase_request_id": "pr_123",
"user_id": "user_42",
"status": "awaiting_approval",
"items": [
{
"sku": "GPU-H100",
"quantity": 100
}
],
"created_at": "2026-08-21T08:00:00Z"
}
Сервер MCP спочатку розшифровує ідентифікатор та перевіряє автентифікацію. Це також покращує можливості спостереження. Замість фрази „сесія ABC виконала певну дію“ система може повідомити, що запит на покупку pr_123 було переміщено з статусу draft у approved, що є конкретним сигналом у бізнес-сенсі.
Безпеку також легше аналізувати. Непрозорий ідентифікатор сам по собі ніколи не є достатньою формою автентифікації, і сервер все одно має підтвердити, що автентифікований користувач має право змінювати стан даних, пов’язаних із цим ідентифікатором. Розширення Tasks ставиться до ідентифікаторів завдань так само: сервери повинні генерувати ідентифікатори, які важко вгадати, а відсутність елемента tasks/list є свідомим вибором з міркувань конфіденційності, адже ніхто не може перелічити ідентифікатори завдань інших людей.
Багатократні запити типу round-trip
Відмова від постійних запитів від сервера до клієнта створює ще одну базову проблему. Розгляньмо виклик інструменту, схожий на цей:
delete_customer_data(customer_id=123)
Сервер не може безпечно видалити щось, поки користувач не підтвердить це, отримавши запит на кшталт „Видалити 48 записів?“. Класична модель може залишати канал відкритим та просити клієнта надати додаткову інформацію. Безстановий дизайн не може покладатися на постійно відкрите з’єднання, і саме для подолання цієї проблеми існують багатокрокові запити, або MRTR.
MRTR охоплює одну логічну операцію, яка потребує кількох обмінів даними без постійного з’єднання чи сеансу з боку сервера. Під час очікування підтвердження, уточнень чи збору зразків жоден механізм не утримує HTTP-з’єднання відкритим чи не використовує режим „липкого“ з’єднання. Натомість взаємодія перетворюється на ланцюг окремих HTTP-запитів, з’єднаних між собою за допомогою стану продовження. Клієнт спочатку запитує про виконання певної дії, наприклад tools/call для інструменту видалення даних. Сервер утримується від відправки власного RPC-запиту до клієнта, поки початкова операція залишається у призупиненому стані, та відповідає проміжним результатом, у якому зазначається необхідність додаткових даних:
{
"resultType": "input_required",
"inputRequests": {
"confirm": {
"type": "elicitation",
"message": "Delete 48 records?",
"schema": {
"type": "boolean"
}
}
},
"requestState": "..."
}
Клієнт збирає відповіді та повторно надсилає початковий запит із ними у додатку:
Client
|
| tools/call
v
Server
|
| input_required
| requestState
v
Client
|
| user confirmation
v
Client
|
| same operation + inputResponses + requestState
v
Any MCP instance
Таким чином операція розділяється на кілька HTTP-запитів-відповідей, без необхідності підтримувати відкритий канал зв’язку. У офіційній версії MRTR описується як заміна для серверно-ініційованих схем elicitation/create, sampling/createMessage та roots/list.
Ключовим полем є requestState. Усе, що потрібно серверу для продовження роботи, поміщається туди у вигляді непрозорого токена, який підписується, шифрується або іншим чином захищається від змін. Специфікація не вимагає зберігання всього стану додатку в одному центральному сховищі MCP-сеансів, а інформація, необхідна для продовження взаємодії, просто надсилається у наступному запиті. Це схоже на токен продовження, і головною перевагою є те, що довга логічна взаємодія більше не означає довгого фізичного з’єднання.
HTTP-заголовки та підказки кешу
Перехід на безстанову архітектуру сам по собі підвищує масштабованість, крім того, протокол стає простішим для роботи з інфраструктурою HTTP. Запити HTTP у форматі стрімінгу містять стандартизовані заголовки, такі як Mcp-Method та Mcp-Name, тож шлюзи та балансувальники навантаження можуть приймати рішення щодо маршрутизації, авторизації, обмежень швидкості та збору даних без необхідності розпаковувати тіло запиту JSON-RPC. Тіло запиту залишається джерелом автентичності, і будь-яка розбіжність між копійованим заголовком та відповідним полем тіла призводить до відхилення запиту.
Шлюз може прочитати ці два значення:
Mcp-Method = tools/call
Mcp-Name = search
і застосовувати перевірки політики такого типу:
tools/call + search -> route/search-cluster
tools/call + execute -> route/execution-cluster
resources/read -> route/resource-cluster
Це забезпечує чітке розділення контрольної та даних площин, оскільки проміжний елемент може оцінити операційну категорію запиту, не розуміючи схеми JSON додатку.
У цій версії також додається метадана кешування через ttlMs та cacheScope. Відповідь у вигляді списку може містити їх ось так:
{
"result": {
"tools": [
...
],
"ttlMs": 60000,
"cacheScope": "public"
}
}
Семантика навмисно нагадує механізм HTTP cache-control. ttlMs вказує клієнту, протягом якого часу результат вважається актуальним, а cacheScope визначає, чи можна безпечно його поширювати. Остаточна специфікація розділяє значення "public" та "private" та попереджає розробників не використовувати параметр cacheScope замість перевірок авторизації. Критерій актуальності визначається наступним чином:
fresh_until = response_received_time + ttlMs
Зазвичай клієнт повинен знову отримувати дані, коли йому потрібен результат, а цей результат вже застарів, а не використовувати TTL як обов’язковий інтервал опитування. Для реалізацій, які все ж таки використовують опитування, специфікація рекомендує використання ефекту джиттеру та стратегії backoff.
Каталоги інструментів роблять це значення очевидним. Якщо сервер перелічує 250 інструментів, а під’єднується 500 агентів, постійні виклики tools/list від кожного з них створюють великий трафік у контрольній площині. Розумний TTL дозволяє клієнтам повторно використовувати каталог, а детерміноване порядкування запобігає зайвим змінам у серіалізованому наборі інструментів, що може підтримувати стабільність кешів запитів LLM. Саме з цієї причини у хроніці змін рекомендується детерміноване порядкування. Ще одна перевага: з’єднання SSE, які залишаються відкритими, більше не є єдиним способом дізнатися про зміни в списку, тож можуть одночасно функціонувати як механізм оновлення кешу, так і сповіщення про зміни.
Довготривалі завдання
API без стану для запитів та відповідей все ще мають обробляти завдання, які тривають хвилини чи години. Розгляньмо такий дзвінок:
run_ml_training_job()
Це може надіслати завдання на розподілену обробку даних, почекати на GPU, виконати кілька етапів, створити контрольні точки та завантажити результати. Підтримання відкритого HTTP-з’єднання протягом усього цього процесу є крихким. Архітектура 2026-07-28 вирішує цю проблему за допомогою розширення Tasks, яке ідентифікується як io.modelcontextprotocol/tasks.
Для підтримуваного tools/call сервер може відповісти ідентифікатором завдання замість кінцевого результату:
{
"resultType": "task",
"task": {
"taskId": "task_7b93...",
"status": "working"
}
}
Клієнт може потім запитати про статус:
tasks/get(taskId)
І продовжуйте отримувати дані до тих пір, поки статус завдання не стане completed, failed або cancelled. Розширення також пропонує tasks/update для додаткових даних та tasks/cancel для скасування.
Одна відмінність є критично важливою. Основний протокол є безстановим, тоді як розширення Tasks навмисно забезпечує зберігання стану:
Core MCP
|
+---- Stateless request/response
Tasks extension
|
+---- Durable asynchronous state machine
Це не суперечність. Це розділення обов’язків. Завдання може бути прив’язане до зовнішньої системи обробки завдань, як у цьому потоці:
MCP tools/call
|
v
Create task
|
v
Queue / workflow engine
|
+--> Kubernetes Job
|
+--> Azure Batch
|
+--> AWS Step Functions
|
+--> Databricks Job
|
+--> CI/CD pipeline
Клієнти використовують ідентифікатор завдання MCP як стабільний інструмент для керування станом цього зовнішнього робочого процесу. У продакшн-середовищах не слід зберігати стан завдань лише у словнику всередині процесу. Розширення описує завдання як стабільні машини станів та рекомендує стабільно зберігати ідентифікатори завдань, щоб опитування продовжувалося після збою клієнта чи перезавантаження сервера.
Залишилася одна тонкощів у реалізації. Розширення Tasks все ще може потребувати направлення запитів до тієї системи, яка зберігає стан завдання. Остаточна пропозиція передбачає, щоб Mcp-Name передавав ідентифікатор завдання для операцій tasks/get, tasks/update та tasks/cancel, що дозволяє проміжним елементам надсилати додаткові запити до системи, яка зберігає стан, за потреби. Повна взаємодія між клієнтом, сервером MCP та двигуном завдань показана на цій діаграмі послідовностей:
Client MCP Server Task DB / Engine
| | |
|--- 1. tools/call ------>| |
| |--- 2. Register Task ----->| (Status: working)
|<-- 3. Return taskId ----| |
| | |
|--- 4. tasks/get ------->| |
| \--- 5. Query state ----->| (Status: working)
|<-- 6. Status: working --/ |
| | |
|--- 7. tasks/get ------->| |
| \--- 8. Query state ----->| (Status: completed)
|<-- 9. Final Result -----/ |
У типовому сценарії клієнт починає виконання завдання за допомогою tools/call, а сервер записує стабільний запис завдання у спільний бекенд, такий як Redis, PostgreSQL чи двигун робочих процесів, наприклад AWS Step Functions або Kubernetes. Потім він негайно повертає taskId та початковий статус working. Перше HTTP-з’єднання закривається коректно, що звільняє мережеві ресурси, а клієнт періодично перевіряє прогрес за допомогою tasks/get.
Тож точне архітектурне твердження полягає не в тому, що все в MCP є безстановим. Сам ядро MCP є безстановим, а станова поведінка моделюється явно через дані додатку та розширення, такі як Tasks.
Агент для обробки даних у продакшені та операцій з машинним навчанням
Уявіть собі продакшенну платформу ШІ, яка надає інструменти MCP агенту корпорації. Цей агент має такі інструменти:
search_dataset()
inspect_schema()
run_sql()
start_training_job()
get_training_metrics()
deploy_model()
rollback_deployment()
Користувач потім просить наступне: знайти найновіший набір даних про відхід клієнтів, проаналізувати його, навчити кандидатську модель, порівняти показники з моделлю у продакшені та розгорнути її лише у разі, якщо покращення становить принаймні 5%.
У рамках старої архітектури зі станом система могла підтримувати тривалу сесію протоколу для відстеження взаємодії, що пов’язувало логічний робочий процес користувача з одним екземпляром сервера. У новій архітектурі процес можна спроєктувати явно. Перший виклик може бути пошуком:
search_dataset("customer churn latest")
і сервер повертає ідентифікатор набору даних:
{
"dataset_id": "ds_2026_08_20_0042"
}
Наступний запит перевіряє схему через цей ідентифікатор:
inspect_schema("ds_2026_08_20_0042")
Схема походить з системи метаданих. Наступний запит ініціює навчання:
start_training_job("ds_2026_08_20_0042")
Сервер MCP створює тривалий завдання:
task_id = "task_train_98af..."
Саме навчання відбувається поза процесом MCP. Клієнт періодично запитує його:
tasks/get("task_train_98af...")
і завдання може проходити через низку станів:
QUEUED
|
RUNNING
|
EVALUATING
|
INPUT_REQUIRED
|
RUNNING
|
COMPLETED
У стані INPUT_REQUIRED система може запитати про схвалення розгортання, зазначивши, що кандидат на 7,2% кращий, але це призведе до збільшення витрат на GPU на 18%. MRTR може задати це питання, не підтримуючи активний зв’язок. Клієнт відповідає ось так:
inputResponses = {
"approve": true
}
і запит продовжується.
Тепер уявіть сервер MCP, який працює на шести репліках Kubernetes:
Ingress
|
Load Balancer
|
+------+------+------+------+
| | | | |
MCP1 MCP2 MCP3 MCP4 MCP5
|
v
Task Store
|
+-------+-------+
| |
Redis PostgreSQL
|
v
Workflow Engine
|
+-----+------+
| |
GPU Job Model Registry
Тут перший запит tools/call надсилається на MCP2, наступний — на MCP5, запит на перевірку статусу завдання — на MCP1, а спроба підтвердження — на MCP3. Нічого не ламається, оскільки протокол більше не передбачає, що сесія прив’язана до одного конкретного сервера. У разі зупинки MCP3 його замінює Kubernetes. Якщо кількість реплік з шести на дві зменшується протягом ночі, робочий процес залишається функціональним, оскільки стан завдань та додатків зберігається поза процесом. Саме тут специфікація доводить свою практичну цінність.
Авторизація та посилення безпеки
Окрім безстанових змін відбуваються значущі покращення безпеки. У остаточній версії вимагається суворіше дотримання правил OAuth та OIDC: сервери авторизації повинні надавати параметр iss згідно з описом у RFC 9207, а клієнти MCP мають перевіряти цей емітент перед використанням коду авторизації, щоб запобігти атакам на плутанину з серверами авторизації. Креденціалі клієнта також прив’язані до емітента, який їх створив, тому їх повторне використання з іншим сервером авторизації заборонено. Функція динамічної реєстрації клієнтів залишається для сумісності, але формально вважається застарілою; її заміною є документи метаданих Client ID.
Модель загроз ефективно змінюється з урахуванням відсутності стану, хоча це також створює певні обов’язки. У продакшн-середовищі необхідно автентифікувати кожен запит та дозволити виконання певної операції з інструментом чи ресурсом. Система має перевіряти конкретні ідентифікатори стану проти автентифікованого користувача, запобігати переліку ідентифікаторів завдань та шифрувати конфіденційні дані стану як у збереженому вигляді, так і під час передачі. Розгляньмо запис на кшталт цього:
basket_id = bsk_123
user_id = user_456
Ніхто не повинен робити висновок, що наявність bsk_123 достатня для дій щодо кошика. Перш за все сервер має перевірити право власності, зокрема таким чином:
authenticated_subject == basket.owner
А потім застосовуються дозволи, специфічні для інструменту.
Процес поширення контексту відстеження W3C також задокументований; він передається через _meta за допомогою параметрів traceparent, tracestate та baggage. Відстеження дій у межах хоста, клієнта MCP, сервера MCP та послуг нижчого рівня стає значно простішим, і розробники прямо пов’язують це з трекінгом, сумісним з OpenTelemetry. Тому здатність до спостереження має бути частиною проекту з самого початку. Шлях запиту, який підлягає відстеженню, може виглядати так:
User Request
|
v
Agent
|
| traceparent
v
MCP Client
|
| traceparent
v
MCP Gateway
|
v
MCP Server
|
v
Database / Queue / API
Отриманий слід може показати всю ланцюгову залежність причин та наслідків, а не набір не пов’язаних між собою HTTP-транзакцій.
Розширення стають першокласними
Розширення також отримують формальний статус. Вони вже існували, проте раніше не мали розвиненого життєвого циклу на рівні основного протоколу. Тепер кожне розширення має ідентифікатор у форматі reverse-DNS, чітке узгодження можливостей, власний репозиторій, незалежну систему версіонування та окремий етап у процесі SEP.
Причина полягає у тому, що MCP розвивається швидше, ніж окрема монолітична версія протоколу може безпечно еволюціонувати. Функція Supporting Tasks не повинна змушувати кожну реалізацію виконувати асинхронні розподілені завдання, а мінімальний сервер командного рядка не повинен бути змушений використовувати MCP Apps. Більші екосистеми стандартів дотримуються того ж підходу — зберігають ядро маленьким та стабільним, а спеціалізовані функції переміщують у модулі, які змінюються за власним графіком.
У цьому випуску особлива увага приділяється двом розширенням. MCP Apps додає інтерактивний інтерфейс, генерований сервером, усередині інфреймворку з ізоляцією, а Tasks — асинхронне виконання. Отримана ієрархія виглядає так:
MCP
|
+----------+----------+
| |
Core Protocol Extensions
| |
Stateless HTTP +-----+------+
| |
Tasks MCP Apps
Це надає MCP набагато більш стабільний спосіб еволюції.
Зняття з використання та оновлення
У цій версії навмисно впроваджено формальний цикл життя функцій. Хроніка змін визначає стани «Активний», «Знятий з використання» та «Видалений» та встановлює мінімальний термін у дванадцять місяців для зняття з використання, щоб розробники додатків мали передбачуваний період міграції та не змушені були робити термінові зміни щоразу, коли змінюється протокол.
«Roots», «Sampling» та «Logging» входять до списку для зняття з використання. Офіційні рекомендації щодо міграції передбачають заміну «Roots» на явні параметри інструментів, URI ресурсів або конфігурацію сервера, заміну «Sampling» на пряму інтеграцію з постачальниками LLM та заміну «Logging» на stderr або OpenTelemetry. Старий спосіб передачі даних HTTP+SSE також знятий з використання, а більш рекомендованим варіантом є Streamable HTTP.
Експериментальний API завдань від 2025-11-25 позначає ще одну межу міграції. Тепер він знаходиться у розширенні io.modelcontextprotocol/tasks із переробленим життєвим циклом, заснованим на функціях tasks/get, tasks/update та tasks/cancel. Функція tasks/list була видалена, оскільки відображення списку завдань без сеансу викликає проблеми з обмеженням доступу та конфіденційністю.
Для організації, яка мігрує існуючі системи MCP, найбезпечніша послідовність дій виглядає так:
- Оновіть SDK, а потім знайдіть код, який використовує
Mcp-Session-Id. Уважно перегляньте словники, ключі яких пов’язані з сеансами, реєстри з’єднань та правила маршрутизації „sticky-session“, створені за старою моделлю. - Відокреміть стан протоколу від стану додатку, надавши кожному елементу, який представляє реальний бізнес-стан, чіткий ідентифікатор та перемістивши його до відповідного надійного сховища.
public та private має наслідки для безпеки.Чинна документація щодо міграції на TypeScript SDK також відображає перехідну реальність. Реалізації можуть підтримувати новий протокол, зберігаючи при цьому механізми сумісності для клієнтів попередньої ери, тож міграція може відбуватися поступово без необхідності масштабної заміни всієї екосистеми.
Що це означає для архітектури MCP
Найсуттєвішою наслідком є те, що MCP тепер розділяє чотири аспекти, які раніше змішувалися між собою:
- Шар протоколу визначає значення повідомлень.
- Шар транспортування передає запити через HTTP або stdio.
- Шар додатків зберігає стан, контекст авторизації, робочі процеси та те, що ідентифікує бізнес-об’єкт.
- Шар розширень надає необов’язкові функції, такі як асинхронні завдання та додатки MCP.
Структура шарів виглядає так:
+----------------------------+
| MCP Protocol |
| JSON-RPC + request model |
+-------------+--------------+
|
+-------------v--------------+
| Transport |
| stdio / Streamable HTTP |
+-------------+--------------+
|
+-------------v--------------+
| Application Layer |
| explicit IDs + databases |
+-------------+--------------+
|
+-------------v--------------+
| Extensions |
| Tasks / MCP Apps / others |
+----------------------------+
Це забезпечує набагато кращу масштабованість, ніж спроба вмістити все в одну абстракцію сесії з обмеженнями підключення, і приводить MCP у відповідність із давно усталеною практикою розподілених систем: обробка запитів без зберігання стану, стійкий зовнішній стан, чіткі ідентифікатори, семантика кешу, ідемпотентні спроби, асинхронне керування завданнями та розподілений трекінг.
Компроміси
Існують певні витрати. Основною перевагою є горизонтальна масштабованість, але ціною є те, що керування станом стає завданням самого додатку. Розробникам доводиться вирішувати, як створюються механізми керування станом, як довго вони існують, де зберігаються, як здійснюється доступ та як очищуються застарілі дані.
Оскільки можливості клієнта та метадані передаються з кожним запитом, об’єм даних, які надсилаються, трохи зростає. Додаткові байти зазвичай невеликі, проте системи з високою пропускною здатністю повинні уникати зайвого повторення даних про можливості клієнта.
MRTR уможливлює роботу без стану HTTP для обмінників, яким раніше були потрібні запити, ініційовані сервером, хоча водночас більш відкрито відображає машину станів взаємодії. Клієнт повинен розпізнавати значення input_required, зберігати стан запиту, збирати відповіді та правильно повторювати спробу.
Завдання забезпечують тривалу обробку, але це коштує наявності сховища завдань — ще одного стійкого підсистеми. Це не є дефектом, а просто явний стан, який замінює прихований стан протоколу.
Кешування підвищує ефективність, але неправильні значення cacheScope можуть створити проблеми з безпекою. Відповідь, неправильно позначена як "public", може стати доступною у різних контекстах авторизації, і інструкції щодо кешування попереджають, що діапазон кешу не замінює авторизацію на примітивному рівні.
Безстановий ядро не слід розглядати як менш ефективну архітектуру. Краще описати його як розподіл обов’язків більш розумно.
Концептуальна зміна
Якщо запитати, де відбувається логічна взаємодія, стара модель неявно вказувала на те, що вона відбувається всередині сеансу MCP, пов’язаного з підключенням. Нова модель натомість запитує, який саме стан дійсно потрібен для виконання операції, і відповідь є чіткою: ідентифікатор домену, ідентифікатор завдання, контекст авторизації чи токен стану запиту, необхідний для продовження роботи. Така абстракція дозволяє краще масштабуватися.
Транзакції мають ідентифікатори транзакцій, робочі потоки Kubernetes — ідентифікатори завдань, кошики покупок — ідентифікатори кошиків, пайплайни CI — ідентифікатори виконання, а завдання навчання — ідентифікатори виконання. Тепер додатки MCP можуть використовувати ту саму термінологію.
Що додає ця версія
Це оновлення — це не просто виправлення протоколу. Воно переводить MCP від інтеграції з агентами, орієнтованими на з’єднання, до хмарних дистрибуйованих систем, причому елементи цих змін є наступними:
- Видалення
Mcp-Session-Idпозбавляє протокол зв’язку семантики сесії. - Відмова від процедури взаємодії робить кожен запит самостійною операцією обміну даними.
server/discoverдозволяє виявляти можливості без додаткової семантики сесії.Mcp-MethodтаMcp-Nameроблять трафік MCP сумісним із звичайними інструментами HTTP.ttlMsтаcacheScopeнадають клієнтам та шлюзам спільну термінологію для визначення свіжості та обміну даними.- MRTR відмовляється від ідеї, що для того, щоб сервер міг щось запитати у клієнта, необхідне з’єднання, яке ніколи не закривається.
- Завдання є стійкою абстракцією для роботи, яка триває довше, ніж один HTTP-запит.
- Експліцитні ідентифікатори виводять стан бізнесу за межі прихованих транспортних метаданих та переносять його до власної моделі даних додатку.
- Розширення запобігають надмірному збільшенню об’єму основного коду, дозволяючи екосистемі розвиватися швидко.
- Більш суворі правила авторизації відповідають способу функціонування справжніх реалізацій OAuth та OIDC.
- Конвенції контексту трасування з OpenTelemetry полегшують спостереження за розподіленими системами MCP.
- Формальна політика виходу з ужитку забезпечує екосистемі передбачуваний спосіб змін.
Безстанова модель значно полегшує реалізацію MCP, а інструменти explorer та Datasette від незалежних розробників демонструють, що ця простота перетворюється на корисні інструменти. Його опис старого протоколу як такого, що вимагає ініціалізації сеансу, та нового протоколу як єдиного самодостатнього запиту — це саме та операційна зміна, до якої прагнули адміністратори.
Висновок для архітекторів полягає у тому, що MCP не видаляв стан. Він видаляв прихований стан, який належав протоколу, замінюючи його на явний, складовий стан, який належить додатку. Ця зміна дозволяє серверу MCP переходити від такого поєднання:
sticky sessions
+
shared session store
+
long-lived connections
+
connection affinity
і щодо цього:
stateless request handling
+
ordinary load balancing
+
external durable state
+
explicit handles
+
asynchronous task primitives
Для корпоративних розгортань це є великою перевагою, адже це набагато краще підходить до Kubernetes, автомасштабування, виконання без серверів, API-шлюзів, розгортання без перерв, маршрутизації між кількома регіонами, розподіленого відстеження та великих платформ з кількома орендарями. Простіше кажучи, ця специфікація перетворює MCP зі стандарту для виклику інструментів агентами на інфраструктуру, яка природним чином вписується в сучасні розподілені системи ШІ.