Trefon.
← Wszystkie notatki 9 min

MCP od środka: JSON-RPC, transporty i negocjacja możliwości

Model Context Protocol na łączu: wiadomości JSON-RPC 2.0, handshake initialize i negocjacja możliwości, narzędzia, zasoby i prompty, stdio kontra Streamable HTTP, ile kontekstu kosztuje każdy schemat narzędzia i model bezpieczeństwa, który musisz zapewnić sam.

Jacek Trefon
  • deep dive
  • MCP
  • agenci
  • harnessy
  • JSON-RPC
Kod ↗

Model Context Protocol (MCP) to dziś sposób, w jaki większość harnessów agentowych podłącza narzędzia napisane przez kogoś innego. amber też go obsługuje. Pod warstwą marketingu kryje się mały, czytelny protokół: JSON-RPC 2.0 przez potok albo HTTP, do tego handshake (uzgadnianie), który mówi, kto może co robić. Poniżej to, co naprawdę płynie po łączu.

JSON-RPC 2.0

Każda wiadomość MCP to obiekt JSON-RPC 2.0 jednego z trzech rodzajów:

  • żądanie, z id, method i params, które oczekuje odpowiedzi;
  • odpowiedź, z tym samym id i albo result, albo error;
  • powiadomienie, z method i bez id, które nie oczekuje odpowiedzi.

Żądania może wysyłać każda ze stron. Serwer też może prosić klienta o różne rzeczy.

Handshake

Sesja zaczyna się od tego, że klient ogłasza swoją wersję protokołu i swoje możliwości (capabilities):

{"jsonrpc": "2.0", "id": 1, "method": "initialize",
 "params": {"protocolVersion": "2025-06-18",
            "capabilities": {"roots": {"listChanged": true}, "sampling": {}},
            "clientInfo": {"name": "my-harness", "version": "1.0.0"}}}

Serwer odpowiada własną wersją i możliwościami, takimi jak "tools": {"listChanged": true}. Klient wysyła wtedy powiadomienie notifications/initialized i zaczyna się normalny ruch.

Możliwości to kontrakt. Funkcji, której nie zadeklarowano w handshake’u, nie wolno używać, więc klient, który nigdy nie zaoferował sampling, nigdy nie zostanie poproszony o wygenerowanie odpowiedzi modelu dla serwera.

Co oferują serwery

  • Narzędzia: funkcje, które model może wywołać. tools/list zwraca nazwę, opis i inputSchema (JSON Schema) każdego narzędzia. tools/call uruchamia jedno z nich, a wynik to tablica content z tekstem, obrazami albo osadzonymi zasobami, z isError przy niepowodzeniach. Od rewizji 2025-06-18 narzędzie może też zadeklarować outputSchema i zwracać structuredContent.
  • Zasoby: dane, które klient może odczytać, identyfikowane przez URI: pliki, rekordy, dokumenty. Zasoby są listowane i odczytywane (resources/list, resources/read); nie są wykonywane.
  • Prompty: szablony promptów wielokrotnego użytku, które może wywołać użytkownik (prompts/list, prompts/get).

Klienci z kolei mogą zaoferować serwerom, jeśli to zadeklarują: roots, czyli granice systemu plików albo URI, w obrębie których serwer może działać; sampling (próbkowanie), dzięki czemu serwer może poprosić model klienta o wygenerowanie odpowiedzi; oraz elicitation (prośba o dane), dzięki czemu serwer może poprosić użytkownika o wprowadzenie danych.

Gdy zmienia się zestaw narzędzi serwera, serwer wysyła notifications/tools/list_changed, a klient ponownie pobiera listę.

Transporty

  • stdio: klient uruchamia serwer jako podproces, a wiadomości płyną jako JSON rozdzielany znakami nowej linii przez stdin i stdout. To prosty, lokalny i najczęstszy sposób uruchamiania serwera.
  • Streamable HTTP: dla serwerów zdalnych, jeden endpoint HTTP. Klient wysyła wiadomości przez POST, a serwer może odpowiedzieć bezpośrednio albo otworzyć strumień Server-Sent Events na kolejne wiadomości. Nagłówek Mcp-Session-Id łączy żądania w jedną sesję. Streamable HTTP zastąpił wcześniejszy transport HTTP plus SSE w rewizji 2025-03-26, która określiła też OAuth 2.1 do autoryzacji.

Ile to kosztuje w kontekście

Nazwa, opis i schemat każdego narzędzia muszą być w kontekście modelu, żeby model mógł go użyć. Pięćdziesiąt narzędzi po około 200 tokenów to 10K tokenów w każdym żądaniu, zanim zacznie się rozmowa. MCP sprawia, że łatwo podłączyć wiele serwerów i niepostrzeżenie przepalić ten budżet. Pomaga to samo, co w notatce o zarządzaniu kontekstem:

  • udostępniaj tylko te narzędzia, których potrzebuje zadanie;
  • pisz krótkie i konkretne opisy;
  • nie zmieniaj bloku narzędzi, żeby cache prefiksu mógł go ponownie wykorzystać.

Model bezpieczeństwa, który zapewniasz sam

MCP definiuje okablowanie, a nie zaufanie. Trzy rzeczy traktuj jako wrogie, dopóki nie okaże się inaczej:

  1. Opisy narzędzi to część promptu. Złośliwy albo przejęty serwer może umieścić w opisie instrukcje, a model czyta go jako kontekst. Serwery, które podłączasz, sprawdzaj tak samo jak zależności.
  2. Wyniki narzędzi to niezaufane dane. Pobrana strona internetowa albo dokument mogą zawierać prompt injection. Nie pozwalaj, żeby wyniki uruchamiały destrukcyjne działania bez sprawdzenia.
  3. Wywołania mają skutki uboczne. Zapis plików, wysyłanie wiadomości czy uruchamianie poleceń powinny wymagać potwierdzenia albo mieć ściśle ograniczony zakres. Roots istnieją po to, żeby ograniczać, do czego serwer może sięgnąć; używaj ich.

Zasady, których się trzymam

  1. Do narzędzi lokalnych wybieraj stdio, a do zdalnych Streamable HTTP z OAuth.
  2. Używaj ustrukturyzowanego wyjścia (outputSchema) tam, gdzie narzędzie zwraca dane, żeby wyniki parsowały się bez zgadywania.
  3. Wyznacz budżet na listę narzędzi tak jak na każdą inną część kontekstu.
  4. Skutki uboczne kontroluj w harnessie, a nie zdawaj się na dobrą wolę serwera.

Źródła: specyfikacja Model Context Protocol, rewizje 2024-11-05, 2025-03-26 i 2025-06-18, oraz specyfikacja JSON-RPC 2.0.

Masz podobny problem?

Opisz swój problem

30-minutowa rozmowa techniczna z inżynierem, który to buduje. Bez działu sprzedaży, bez slajdów.