Przejdź do treści
Wróć do bloga
6 min czytania

MCP bez sesji: jak podłączyć asystenta AI do firmowych danych według nowej specyfikacji

Model Context Protocol to standard, przez który asystent AI pyta Twoje systemy o dane: zamówienia, faktury, zgłoszenia. Wersja specyfikacji z 28 lipca 2026 zmienia jego fundament: serwer MCP przestaje pamiętać klienta między zapytaniami. Dla zespołu, który ma to wdrożyć, oznacza to jedno: serwer MCP można teraz stawiać jak każde inne API.

MCPAgenci AIIntegracje

Do tej pory rozmowa z serwerem MCP zaczynała się od uzgodnienia: klient wysyłał initialize, serwer odpowiadał i nadawał identyfikator sesji w nagłówku Mcp-Session-Id. Każde kolejne zapytanie musiało trafić tam, gdzie tę sesję zapamiętano. Przy jednej instancji to nie problem. Przy trzech za load balancerem trzeba było kleić klientów do konkretnej maszyny albo trzymać sesje we wspólnej bazie.

Co zmieniła wersja 2026‑07‑28

Autorzy specyfikacji piszą wprost, że MCP zmienia się z protokołu dwukierunkowego, który trzyma stan, w bezstanowy protokół zapytanie i odpowiedź. Każde zapytanie niesie teraz w polu _meta wersję protokołu i możliwości klienta, więc serwer można postawić, jak to ujęli, za zwykłym load balancerem typu round robin, bez współdzielonego magazynu. Z długiej listy zmian dla firmy liczy się pięć:

  • Nie ma już handshake'u initialize ani nagłówka Mcp-Session-Id. Serwer, który potrzebuje stanu między wywołaniami, wydaje własny identyfikator i przyjmuje go jako zwykły argument narzędzia.
  • Każde zapytanie POST musi mieć nagłówek Mcp-Method, a wywołania narzędzi, zasobów i promptów także Mcp-Name. Gateway może po nich routować i liczyć ruch bez czytania treści. Serwer ma obowiązek odrzucić zapytanie, w którym nagłówek nie zgadza się z treścią: kod HTTP 400 i błąd -32020.
  • Każdy serwer musi obsługiwać metodę server/discover, która podaje obsługiwane wersje protokołu, możliwości i tożsamość serwera.
  • Sampling, Roots i Logging są oznaczone jako wycofywane. Działają dalej, a nowa polityka cyklu życia gwarantuje co najmniej dwanaście miesięcy, zanim cokolwiek zniknie. Nowy kod nie powinien na nich polegać.
  • Dynamic Client Registration (RFC 7591) ustępuje miejsca dokumentom Client ID Metadata. Klient musi też sprawdzić parametr iss z RFC 9207, jeśli serwer autoryzacji go zwraca, a dane uwierzytelniające są odtąd przypisane do serwera autoryzacji, który je wydał.

Większość zmian w autoryzacji dotyczy klientów, czyli asystentów i ich bibliotek. Po stronie serwera najwięcej zyskuje wdrożenie: kontener, kilka replik, load balancer bez sticky sessions, a do tego żadnego Redisa na same sesje. Oficjalny SDK dla Pythona w wersji 2.0.0 wyszedł tego samego dnia co specyfikacja i według notatki wydania obsługuje z jednego serwera zarówno nową wersję protokołu, jak i wszystkich klientów z wersji z 2025 roku.

Bezstanowość ma swoją cenę. Serwer nie może już sam zagadnąć klienta w trakcie wywołania. Jeśli narzędzie potrzebuje decyzji użytkownika, na przykład potwierdzenia zwrotu pieniędzy, zwraca wynik input_required z pytaniem, a klient ponawia to samo wywołanie z odpowiedzią. Specyfikacja nazywa ten wzorzec Multi Round‑Trip Requests. Narzędzia tylko do odczytu, od których najrozsądniej zacząć, w ogóle go nie potrzebują.

Serwer: jedno narzędzie, jedna tabela, tylko odczyt

Poniżej kompletny serwer. Tworzy małą bazę SQLite z dwoma zamówieniami i wystawia jedno narzędzie, get_order_status, które zwraca status zamówienia po numerze. Klasa MCPServer to dawny FastMCP. W wersji 2.0.0 importuje się ją z mcp.server, co sprawdziliśmy, uruchamiając ten kod.

Python

import sqlite3

from mcp.server import MCPServer

DB_PATH = "orders.db"

# Demo data: one table, two orders.
with sqlite3.connect(DB_PATH) as db:
    db.execute("CREATE TABLE IF NOT EXISTS orders (id TEXT PRIMARY KEY, status TEXT)")
    db.executemany("INSERT OR REPLACE INTO orders VALUES (?, ?)",
                   [("A-1001", "shipped"), ("A-1002", "awaiting payment")])

mcp = MCPServer("orders")


@mcp.tool()
def get_order_status(order_id: str) -> str:
    """Return the status of one order by its ID."""
    # Read-only connection: the tool cannot change data even by mistake.
    with sqlite3.connect(f"file:{DB_PATH}?mode=ro", uri=True) as db:
        row = db.execute("SELECT status FROM orders WHERE id = ?", (order_id,)).fetchone()
    return row[0] if row else f"No order {order_id}"


if __name__ == "__main__":
    mcp.run("streamable-http", port=8765, json_response=True)
server.py. Wymaga Pythona 3.10 lub nowszego i pip install mcp==2.0.0. Uruchomienie: python server.py.

Opis narzędzia, który zobaczy model, pochodzi z docstringu, a schemat argumentów z adnotacji typów. Połączenie z bazą jest otwierane w trybie mode=ro, więc nawet błędne zapytanie nie zmieni danych. Serwer domyślnie nasłuchuje tylko na 127.0.0.1, czyli tak, jak specyfikacja zaleca przy pracy lokalnej. Opcja json_response=True sprawia, że odpowiedź przychodzi jako pojedynczy obiekt JSON, a nie strumień SSE, co ułatwia test.

Wywołanie bez sesji

Teraz jedno zapytanie curl do świeżo uruchomionego procesu. Bez initialize, bez identyfikatora sesji. Wersja protokołu idzie w nagłówku MCP-Protocol-Version i w polu _meta, metoda i nazwa narzędzia w nagłówkach Mcp-MethodMcp-Name.

Bash

curl -s http://127.0.0.1:8765/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: get_order_status" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
       "params": {"name": "get_order_status",
                  "arguments": {"order_id": "A-1001"},
                  "_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
                            "io.modelcontextprotocol/clientCapabilities": {}}}}'
Wymaga działającego server.py z poprzedniego listingu.

HTTP

HTTP/1.1 200 OK
content-type: application/json

{"jsonrpc":"2.0","id":1,"result":{"content":[{"text":"shipped","type":"text"}],
 "isError":false,"resultType":"complete","structuredContent":{"result":"shipped"},
 "_meta":{"io.modelcontextprotocol/serverInfo":{"name":"orders","version":""}}}}
Odpowiedź, którą dostaliśmy, bez nagłówków date, servercontent-length. Linie podzielone dla czytelności.

To było pierwsze zapytanie, jakie ten proces w ogóle obsłużył, a w odpowiedzi nie ma nagłówka sesji. Dwie kopie tego serwera za load balancerem odpowiedzą na nie tak samo. Serwer sam dodał też wymagane w nowej wersji pole resultType i zalecane serverInfo, bez żadnego kodu po naszej stronie.

Sprawdziliśmy również, co się dzieje, gdy nagłówki kłamią. Po zmianie Mcp-Name na delete_order przy niezmienionej treści SDK odrzuca zapytanie dokładnie tak, jak każe specyfikacja:

HTTP

HTTP/1.1 400 Bad Request

{"jsonrpc":"2.0","id":1,"error":{"code":-32020,
 "message":"mcp-name header does not match the request body's 'name' parameter"}}
Ten sam curl z nagłówkiem Mcp-Name: delete_order.

Brak nagłówka Mcp-Method kończy się tym samym kodem -32020. Jedna rzecz działa inaczej, niż można by się spodziewać po lekturze changelogu: zapytanie bez nagłówka MCP-Protocol-Version SDK traktuje jako ruch od starszego klienta, odpowiada błędem Missing session ID i nadaje nagłówek mcp-session-id. Specyfikacja na to pozwala, bo serwer może obsługiwać klientów sprzed 2026‑07‑28. W praktyce znaczy to, że bezstanowość dostajesz dopiero wtedy, gdy Twój asystent też mówi nową wersją protokołu. Dopóki łączą się starsze klienty, sesje w starym trybie wciąż istnieją.

Zanim podłączysz prawdziwe dane

Przykład ma dwa zamówienia w pliku. Firmowa baza ma dziesiątki tysięcy rekordów i dane klientów. Przed pierwszym podłączeniem asystenta przejdź tę listę:

Pięć rzeczy do sprawdzenia

  1. 01Tylko odczyt na poziomie bazy, nie nazwy narzędzia. Osobny użytkownik bazy z prawem SELECT do wybranych tabel albo replika. Tryb mode=ro z przykładu to ta sama zasada w małej skali.
  2. 02Wąskie narzędzia. get_order_status(order_id) odpowiada na jedno pytanie i zwraca jedną wartość. Narzędzie w rodzaju run_sql(query) oddaje modelowi całą bazę. Ogranicz też liczbę zwracanych wierszy.
  3. 03Uwierzytelnienie od pierwszego dnia. Specyfikacja zaleca je dla wszystkich połączeń i wymaga sprawdzania nagłówka Origin, żeby strona w przeglądarce nie mogła rozmawiać z Twoim lokalnym serwerem. Wybierając serwer autoryzacji, sprawdź obsługę Client ID Metadata Documents, bo Dynamic Client Registration jest wycofywane, a po stronie klienta sprawdź walidację iss.
  4. 04Log każdego wywołania na wejściu. Nagłówki Mcp-MethodMcp-Name pozwalają proxy zapisać, kto wywołał które narzędzie, i przepuścić tylko nazwy z listy dozwolonych. Specyfikacja ostrzega, żeby pośrednik nie ufał tym nagłówkom w zapytaniach bez nowej wersji protokołu, bo nikt ich wtedy nie porównuje z treścią.
  5. 05Nic nowego na Sampling, Roots i Logging. Katalogi i pliki przekazuj jako parametry narzędzi, model wywołuj bezpośrednio przez API dostawcy, a logi kieruj na stderr albo do OpenTelemetry.

Źródła

  1. 01Model Context Protocol, Specification 2026‑07‑28: Key Changesopublikowano 28 lipca 2026
  2. 02Model Context Protocol, Specification 2026‑07‑28: Streamable HTTPopublikowano 28 lipca 2026
  3. 03Model Context Protocol Blog, The 2026‑07‑28 Specificationopublikowano 28 lipca 2026
  4. 04modelcontextprotocol/python-sdk, release v2.0.0opublikowano 28 lipca 2026
  5. 05PyPI, mcp 2.0.0opublikowano 28 lipca 2026

Więcej z bloga

5 min czytania

Jev: model, który zwraca decyzję zamiast zdania

TypeSafe AI wypuściło 15 września model, który nie pisze tekstu. Oddaje wybraną opcję i prawdopodobieństwo, kosztuje 0,042 dolara za milion tokenów wejściowych, a za wyjście nie płaci się nic. Sprawdzamy, co z tego zostaje po odjęciu marketingu.

Czytaj
6 min czytania

Umiejętności agenta: dlaczego pięć działa lepiej niż sto

Przy puli pięciu skilli właściwy stanowi 29,6% tych, po które agent faktycznie sięga, przy stu już tylko 3,3%. W sierpniu publiczny rejestr skilli rozdawał klony, które kradły klucze SSH. Cztery zasady dla zespołu, który pracuje z agentami.

Czytaj

Opisz proces, który zabiera najwięcej czasu

Wystarczy kilka zdań. Odpowiemy, czy da się go usprawnić, ile to mniej więcej kosztuje i czy w ogóle potrzebujesz do tego AI.