Migracja serwera MCP na specyfikację 2026-07-28: dwadzieścia minut, krok po kroku
Przeniesienie serwera MCP na specyfikację z dnia 2026-07-28 w około dwudziestu minutach: sesje zniknęły, pięć istotnych zmian, kroki związane z Python SDK 2.0 oraz przepisanie MRTR.
Źródła: Your MCP Server Is Running on a Deprecated Spec. Here’s the 20-Minute Migration.
Nic się nie zepsuło, a to właśnie jest niepokojące. 28 lipca 2026 roku Model Context Protocol opublikował swoją specyfikację 2026-07-28, która stanowi największą zmianę od pierwszego pojawienia się zdalnego MCP. Usunięto nagłówek, od którego zależały serwery, a model transporту uległ zmianie, mimo to zachowano kompatybilność. Serwery funkcjonowały dalej bez śladów błędów, ostrzeżeń ani sygnałów o błędnej kompilacji.
To właśnie jest ten cichy rodzaj długu technicznego. Pozostaje ukryty, dopóki ktoś nie potrzebuje rozszerzenia możliwości systemu, albo dopóki nie upłynie dwunastomiesięczny okres wycofywania i zależność przestanie być utrzymywana. Serwer nadal używający wersji z 2025-11-25 jest w tyle. Serwer korzystający z przestarzałego transportu HTTP+SSE używa obecnie czegoś, co już nie jest wspierane, a ponadto trzy funkcje mogą zostać wycofane w każdej chwili.
W dalszej części omówiono, co się zmieniło, dlaczego to zrobili utrzymujący system oraz jak nadrobić zaległości. Dla większości serwerów zajmuje to około dwudziestu minut pracy. Jedna zmiana dotyczy jednak rzeczywistej przepisania kodu dla niektórych serwerów, więc lepiej powiedzieć o tym od razu.
Dlaczego zastosowano sesje
Motywacje inżynieryjne wyjaśniają wszystko inne. MCP został wprowadzony pod koniec 2024 roku jako protokół zorientowany na sesje: klient nawiązuje połączenie za pomocą polecenia initialize, serwer wysyła Mcp-Session-Id, a każda kolejna prośba go zawiera. Takie rozwiązanie pasowało do pierwotnego przypadku, gdy na jednym komputerze znajdował się jeden klient i jeden serwer, komunikujący się przez stdio.
Następnie serwery przeniosły się na prawdziwą infrastrukturę, a projekt napotkał bariery. Inżynierowie Google opisali to w swoim opracowaniu na temat aktualizacji bez stanu: projekt, który był idealny dla pojedynczego lokalnego klienta, przestał funkcjonować, gdy serwery MCP zostały rozmieszczone na infrastrukturze typu cloud-native.
Zastanów się, czego wymaga identyfikator sesji. Albo routowanie typu „sticky”, dzięki któremu jeden klient zawsze łączy się z tą samą instancją, albo wspólna baza danych sesji, do której może uzyskać dostęp każda instancja. Zwykła usługa HTTP nagle potrzebuje równoważenia obciążenia uwzględniającego powinowactwo oraz narzędzi takich jak Redis, by choćby zapewnić transport danych, zanim będzie mogła wykonywać jakiekolwiek użyteczne zadania.
W publikacji Davida Soriego Parry i Dena Delimarskygo stwierdza się wprost: MCP przechodzi z protokołu dwukierunkowego z pamięcią stanu na protokół bezstanowy oparty na zapytaniach i odpowiedziach, co było jedną z najczęściej proszonych zmian ze strony programistów dążących do niezawodności i skalowalności. Pilność tej zmiany wynika z jej rozmiaru – SDK typu Tier 1 mają blisko pół miliarda pobierania miesięcznie, a SDK dla TypeScript i Pythona osiągnęły po miliardie pobierania łącznie. Protokół na taką skalę nie może nadal wymagać, aby przy każdym wdrożeniu rozwiązywano problem powinowactwa sesji.
Zatem sesja przestała istnieć. Każda prośba zawiera własną wersję protokołu, identyfikator klienta oraz informacje o jego możliwościach, co oznacza, że każda prośba może dotrzeć do dowolnej instancji za zwykłym balansem typu round-robin bez wspólnego przechowywania danych. Wszystko poniżej wynika z tego.
Pięć zmian, które należy zrozumieć
1. Brak procedury handshaking, brak nagłówka sesji
Wymiana komend initialize i initialized oraz nagłówek Mcp-Session-Id zostały oficjalnie wycofane (SEP-2575 i SEP-2567). Każda prośba funkcjonuje samodzielnie, zawierając wersję protokołu, identyfikator klienta oraz informacje o jego możliwościach w sekcji _meta. Prośba zgodnie z nowymi specyfikacjami wygląda w ten sposób:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"},
"_meta":{"io.modelcontextprotocol/clientInfo":
{"name":"my-app",
"version":"1.0"}
}}}
Klient, który chce z góry poznać możliwości serwera, może skorzystać z nowego RPC server/discover, które jest opcjonalne i nie stanowi już obowiązkowego rytuału nawiązywania połączenia.
Częstym obawą jest to, że aplikacje nie będą już mogły przechowywać stanu. W rzeczywistości nadal mogą to robić. Usunięcie informacji o sesji z protokołu nie zobowiązuje aplikacji do bycia bezstanową. Gdy serwer wymaga ciągłości, narzędzie powinno utworzyć wyraźny identyfikator, który model później zwróci jako argument. To działa lepiej niż przechowywanie stanu w samym mechanizmie transmisji, ponieważ model może zobaczyć ten identyfikator i przekazać go z jednego narzędzia na drugie. Widzialny stan jest lepszy od niewidzialnego stanu.
2. Dwa obowiązkowe nagłówki
Od teraz żądania HTTP w Streamable muszą zawierać pola Mcp-Method i Mcp-Name (SEP-2243), a serwer powinien potwierdzić, że odpowiadają one żądaniu. Korzyści dla infrastruktury: brama, ogranicznik szybkości lub WAF mogą kierować ruch i mierzyć jego ilość za pomocą tych nagłówków, unikając jednocześnie analizy JSON. Wszyscy, którzy porzucili ograniczniki szybkości na poziomie poszczególnych narzędzi ze względu na to, że nazwa narzędzia była ukryta w treści żądania, mają teraz rozwiązanie tego problemu.
3. Odpowiedzi listy możliwe do załadowania do pamięci cache
Wyniki z tools/list, prompts/list, resources/list oraz resources/read teraz zawierają pola ttlMs i cacheScope (SEP-2549) i są zwracane w określonej kolejności. Klienci mogą przechowywać w pamięci podręcznej katalog narzędzi oraz utrzymywać stabilność cache zapytań między ponownymi połączeniami. Ponieważ duża część rachunku za tokeny agenta to powtarzające się wysyłanie definicji narzędzi, funkcja ta służy również do obniżania kosztów.
4. Stricterzne zasady autoryzacji
Wprowadzono cztery zmiany, z których jedna może wyjaśniać błąd, z którym już się zmagałeś:
- Serwery autoryzacji powinny zwracać parametr
isszdefiniowany w RFC 9207, a klienci muszą go zweryfikować przed użyciem kodu (SEP-2468), co eliminuje lukę bezpieczeństwa związaną z pomyłkami. - Klienci ustawiają
application_typepodczas dynamicznego rejestracji klienta (SEP-837), dzięki czemu serwery autoryzacji przestają odrzucać przekierowanialocalhostdla aplikacji desktopowych i CLI. Jeśli proces OAuth w aplikacji CLI kiedykolwiek zawodził z powodu błęduredirect_uri, to prawdopodobnie jest to jego przyczyna. - Udostępnione przez klienta dane uwierzytelniające są powiązane z instytucją, która je utworzyła, i nie mogą być ponownie używane w różnych serwerach autoryzacji (SEP-2352).
- Sama dynamiczna rejestracja klienta została formalnie uznana za przestarzałą na rzecz dokumentów metadanych identyfikatora klienta. Nadal funkcjonuje, ale zostanie usunięta w przyszłej wersji.
5. Lista przestarzałych rozwiązań
Słowo „przestarzałe” ma tu duże znaczenie. Funkcje Roots, Sampling and Logging (SEP-2577) są przestarzałe, ale nadal działają, przy czym pozostaje im co najmniej dwanaście miesięcy na dalsze funkcjonowanie, więc nowe implementacje nie powinny ich stosować. Przestarzałym jest również transport HTTP+SSE, który również ma rok na przejście na nowsze rozwiązania.
Moduł Tasks został przeniesiony, a nie uznany za przestarzały. Przeszedł z eksperymentalnego jądra do rozszerzenia io.modelcontextprotocol/tasks, jest dostępny poprzez metodę tasks/get oraz aktualizowany za pomocą nowej metody tasks/update (SEP-2663). Powiadomienia o zmianach są teraz przekazywane przez jeden strumień subscriptions/listen, do którego klienci mogą się zapisać.
Najlepszą wiadomością jest formalna polityka uznawania elementów za przestarzałe, obejmująca okres co najmniej dwunastu miesięcy. Artykuł na Real Python dodaje, że minimalny okres 90 dni dotyczy wyłącznie aktywnych zagrożeń bezpieczeństwa, co stanowi dłuższy termin powiadomienia niż kiedykolwiek wcześniej w tym ekosystemie. Ta polityka może być ważniejsza od wszystkiego innego w tym wydaniu, ponieważ odróżnia protokół służący do eksperymentów od tego, na którym można budować biznes.
Migracja, krok po kroku
Przewodnik wykorzystuje SDK w Pythonie, którego przemiana nazwy jest najbardziej problematyczna spośród czterech, chociaż struktura pozostaje taka sama w TypeScript, Go i C#.
Minuty 0 do 2: podjęcie decyzji. Jeśli serwer wykorzystuje próbkowanie, wywoływanie lub inne metody, wymaga on prawdziwej przepracowywania, o czym mowa poniżej. Jeśli udostępnia jedynie narzędzia i zasoby, można kontynuować.
Minuty 2 do 5: aktualizacja SDK. SDK w Pythonie osiągnęło wersję 2.0.0 w dniu opublikowania specyfikacji, a polecenie pip install mcp ładuje teraz wersję 2.x.
pip install --upgrade "mcp>=2"
Jedna istotna zmiana, o której należy wiedzieć: SDK przeniesiono z httpx na httpx2. Jeśli httpx jest używany gdzie indziej w twoim drzewie zależności, rozwiąż to natychmiast.
Minuty 5 do 10: przemień nazwę klasy. Dotyczy to wszystkich serwerów w Pythonie. FastMCP nazywa się teraz MCPServer – nie ma już aliasu ani mechanizmu przejściowego:
# Before, on mcp 1.x
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo")
# After, on mcp 2.x
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("Demo")
W tej samej wersji dostępne są jeszcze trzy zmiany nazw:
# Wire types are snake_case now
result.isError # → result.is_error
tool.inputSchema # → tool.input_schema
# The error class matches the new capitalisation
except McpError: # → except MCPError:
mcp-types jest teraz osobnym pakietem, ale mcp.types pozostaje obsługiwaną ścieżką importu, więc te importy nadal działają. Uwaga: osoby korzystające z samodzielnego pakietu fastmcp zamiast oficjalnego SDK nie są tym dotknięte. To inny projekt z własnymi wersjami 3.x, a jednym z powodów przemiany nazwy jest oddzielenie tych dwóch rozwiązań.
Minuty 10 do 15: usunięcie mechanizmów sesji. Słowniki sesji, timerzy do czyszczenia oraz instancja Redis stworzona wyłącznie do przechowywania stanu sesji mogą zostać usunięte. Jeśli naprawdę potrzebna jest ciągłość pomiędzy wywołaniami, należy użyć wzorca handle:
# Instead of hiding state in a session the model can't see:
@mcp.tool()
def open_dataset(path: str) -> str:
"""Open a dataset and return a handle for subsequent calls."""
handle = register_dataset(path) # your own store, your own TTL
return handle # the model now HOLDS this
@mcp.tool()
def query_dataset(handle: str, query: str) -> list[dict]:
"""Query a previously opened dataset."""
return lookup(handle).query(query)
Minuty 15 do 18: walidacja nowych nagłówków. Serwer musi sprawdzić, czy przychodzące wartości Mcp-Method i Mcp-Name są zgodne z żądaniem. SDK obejmuje standardową ścieżkę działania, ale w przypadku niestandardowego bramy lub ręcznie napisanego mechanizmu transportu należy to sprawdzić od początku do końca.
Minuty 18 do 20: poprawa kodu błędu. Łatwo o jego przeoczenie, co powoduje mylące zachowanie klienta. Błędy związane z brakiem zasobu powinny używać standardowego kodu JSON-RPC invalid-params -32602, a nie własnego kodu MCP -32002.
Gotowe do wdrożenia
Jeden MCPServer obsługuje obie ery protokołu, więc klient z 2025 roku nadal może korzystać z przeniesionego serwera bez konieczności konfiguracji po żadnej ze stron. Dlatego można to wdrożyć w zwykły wtorek, bez konieczności ustalania specjalnego dnia dla wszystkich klientów.
Gdy zajmuje to więcej czasu
Serwery wykorzystujące próbkowanie, wywoływanie lub inne metody muszą przejść na zupełnie nowy model działania, który w Real Python określany jest jako najważniejszy punkt na liście migracji. Wcześniej serwer mógł wysłać żądanie i otrzymać odpowiedź od klienta poprzez otwarty dwukierunkowy strumień danych. Projekt bez stanu nie posiada takiego strumienia, dlatego zamiast tego stosuje się wielokrotne żądania typu round-trip (SEP-2322).
Nowy mechanizm funkcjonuje w następujący sposób: serwer odpowiada kodem resultType: „input_required” wraz z pytaniami wymagającymi odpowiedzi, a klient powtarza pierwotne żądanie, podając swoje odpowiedzi w polu inputResponses. To zmienia sposób pisania narzędzi – obsługa nie może przerwać działania w połowie i czekać na odpowiedź. Dla jednej operacji logicznej może zostać wywołana kilka razy i musi prawidłowo kontynuować pracę po otrzymaniu danych wejściowych, dlatego wszystko, co jest przechowywane w zmiennych lokalnych podczas przerwy, musi znajdować się w miejscu dostępnym po ponownym próbie.
Skutki są rzeczywiste. Kierownik produktu w Supabase powiedział, że implementacja tej funkcji od dawna znajdowała się na planie rozwoju, ale nie była możliwa, ponieważ ich serwer MCP działa bez przechowywania stanu, natomiast MRTR umożliwia to, pozwalając narzędziom najpierw potwierdzić coś z użytkownikiem – na przykład koszt nowego projektu lub zapytanie, które mogłoby usunąć dane. Napisanie takiego narzędzia staje się nieco trudniejsze, natomiast jego działanie bez przechowywania stanu w dużych skali staje się możliwe.
Co daje nowy protokół
Manufact hostuje tysiące serwerów MCP i utrzymuje otwarte oprogramowanie mcp-use. Okazało się, że wersja SDK v2 jest o około 83% mniejsza i o 25% szybsza dzięki nowemu podziałowi na klienta i serwer. Według zestawienia ekosystemu Agentic AI Foundation serwer teraz funkcjonuje jak każda inna usługa HTTP, odpowiadając z instancji wybranej przez mechanizm rotacyjnego rozdzielenia ruchu, przy czym bramy routują dane i ograniczają szybkość ich przesyłania za pomocą nagłówków. Dwunastomiesięczna polityka rozwoju oznacza, że protokół nie będzie już dalej ewoluować.
Przyjęcie tego otwartego standardu było szybkie. W ciągu zaledwie kilku dni dostawcy infrastruktury, utrzymywacze SDK, platformy chmurowe oraz producenci narzędzi ogłosili swoje wsparcie, opublikowali informacje dotyczące migracji oraz wypuścili wersje gotowe do użycia w produkcji. SDK Agents firmy Cloudflare obsługiwało te specyfikacje od samego początku, Amazon Bedrock AgentCore dostarcza bezstanowy rdzeń, a do grona uczestników dołączyły Microsoft Foundry, Netlify, Figma, Supabase oraz Honeycomb. Honeycomb podaje, że prawie co piąta miesięczna interaktywna zapytanie pochodzi teraz od agentów, co tłumaczy znaczenie tej kwestii. Agenci są już daleko po fazie demonstracyjnej.
Pozostanie na wersji 1.x
To uzasadniona decyzja. Można przytrzymać się tej wersji i czekać:
# Buys you time, keeps security patches coming
pip install "mcp>=1.28,<2"
Wiedz dwie rzeczy podczas korzystania z tego rozwiązania. Linia 1.x jest w trybie konserwacyjnym i obejmuje jedynie poprawki bezpieczeństwa. Ponadto rozszerzenie Tasks nie znalazło się jeszcze w wersji Python SDK 2.0, więc zostało pominięte w podstawowej specyfikacji, mimo że nie trafiło do SDK. Dla użytkowników Pythona, którzy polegają na Tasks, oczekiwanie jest właściwym rozwiązaniem. Ustaw przypomnienie w kalendarzu na dwunasty miesiąc od publikacji Roots, Sampling and Logging – okna deprecjacji wydają się niekończące, dopóki się nie skończą.
Nebezpieczeństwo cichej deprecjacji
Zmiana powodująca problemy jest głośna: powoduje awarię kompilacji, zwraca błędy i jest szybko naprawiana. Deprecjacja natomiast jest celowo cicha. Serwer działa, testy przechodzą i nic nie wyświetla czerwonych komunikatów, podczas gdy koszty narastają: transport z datą wygaśnięcia, brak łatwego skalowania poziomego oraz zależność w trybie konserwacyjnym, podczas gdy ekosystem rozwija się dalej. Wartość w MCP-Protocol-Version to data, więc warto sprawdzić, jaki jest jej aktualny wiek.
Dla większości serwerów nadrobienie zaległości zajmuje co najwyżej popołudnie, a rzeczywła praca trwa mniej niż pół godziny. Serwery wykorzystujące metody próbkowania lub wywoływania powinny założyć sobie jeden dzień i najpierw przeczytać specyfikację MRTR. W obu przypadkach należy to zrobić, zanim dwanaście miesięcy cicho zamieni się w dwa lata.