agentarium.pl

MCP (Model Context Protocol) — kompletny poradnik: czym jest, jak go używać i jak zbudować własny serwer

Redakcja agentarium.pl Publikacja: 40 min czytania
  • Poziom: średnio zaawansowany
  • Początkujący
  • Zaawansowani
  • Biznes
  • Deweloperzy

Czego się nauczysz

  • Czym naprawdę jest MCP — otwartym standardem podłączania agentów do systemów zewnętrznych, a nie kolejnym frameworkiem ani formatem jednego dostawcy.
  • Jak to działa pod spodem — host, klient, serwer, trzy prymitywy (narzędzia, zasoby, prompty), dwa transporty i realne komunikaty JSON-RPC, które lecą po drucie.
  • Jak podłączyć serwer w praktyce — w aplikacji Claude, w Claude Code, w ChatGPT, w VS Code, w Cursorze i w Gemini CLI, z prawdziwymi fragmentami konfiguracji.
  • Z czym MCP łączy się najlepiej — jedenaście kategorii integracji, które realnie się bronią, i to, czego się po nich nie spodziewać.
  • Kiedy MCP jest złym pomysłem — i co wtedy wybrać zamiast: skill, instrukcje projektu, RAG, skrypt, hook albo zwykłe API.
  • Ile to kosztuje w tokenach — bo koszt kontekstowy podłączonych serwerów to najczęściej pomijany punkt całej dyskusji o MCP.
  • Na co uważać — zatrute opisy narzędzi, podmiana definicji po zatwierdzeniu, prompt injection przez dane zwracane z serwera, konkretne CVE i „śmiertelna triada”.
  • Jak zbudować własny serwer — od dziesięciolinijkowego „hello world”, przez serwer użytkowy, po produkcyjny, z aktualnym kodem w Pythonie i TypeScripcie.

Poradnik jest podzielony na pięć części o rosnącym stopniu trudności. Części 1, 3 i 4 są w całości zrozumiałe bez znajomości programowania. Część 2 wchodzi w mechanikę protokołu. Część 5 jest dla osób, które chcą napisać własny serwer.

Jeśli dopiero zaczynasz albo interesuje Cię przede wszystkim łączenie MCP z automatyzacjami w Zapierze, Make czy n8n, zacznij od krótszego wprowadzenia: MCP w praktyce — proste przykłady i kiedy warto go użyć.

Spis treści


Wersja dla zabieganych

MCP (Model Context Protocol) to otwarty standard opisujący, jak agent AI rozmawia z zewnętrznymi systemami. Piszesz jeden serwer MCP nad swoim systemem, a korzysta z niego każdy klient obsługujący standard — Claude, ChatGPT, Cursor, VS Code, Gemini CLI. To zamiana problemu „M asystentów razy N systemów” na „M plus N”.

Serwer MCP wystawia trzy rzeczy: narzędzia (akcje, które model może wywołać sam), zasoby (dane, które aplikacja może wczytać do kontekstu) i prompty (gotowe polecenia, które wybiera użytkownik). Komunikacja idzie po JSON-RPC, lokalnie przez standardowe wejście/wyjście procesu albo zdalnie po HTTP.

Używaj MCP wtedy, gdy agent musi coś realnie odczytać z zewnętrznego systemu albo do niego zapisać — i szczególnie wtedy, gdy alternatywą jest ręczne kopiowanie danych z innego narzędzia do czatu. Nie używaj go do przekazywania wiedzy i procedur — od tego są skille i instrukcje projektu. Największe realne ryzyka to koszt kontekstowy (definicje narzędzi zajmują okno kontekstowe, zanim zadasz pytanie) oraz bezpieczeństwo (serwer MCP to kod działający na Twoich uprawnieniach, a jego opisy narzędzi trafiają wprost do promptu modelu).

Standard powstał w Anthropic i został ogłoszony 25 listopada 2024. W grudniu 2025 trafił pod Agentic AI Foundation przy Linux Foundation, ze współzałożycielami Anthropic, Block i OpenAI. Aktualna rewizja specyfikacji to 2026-07-28 — i jest to rewizja przełomowa, bo uczyniła protokół bezstanowym.


Część 1. Czym jest MCP i skąd się wziął

Definicja w jednym zdaniu

MCP to otwarty standard opisujący, w jaki sposób aplikacja z modelem językowym podłącza się do zewnętrznych narzędzi i danych.

Popularna analogia mówi, że MCP jest „USB-C dla AI”. Jest w niej sporo racji: podobnie jak USB-C, MCP standaryzuje złącze, a nie to, co jest po drugiej stronie kabla. Producent monitora nie musi wiedzieć, jakiego masz laptopa, a autor serwera MCP nie musi wiedzieć, którego asystenta użyjesz.

Analogia ma jednak granicę i warto ją znać. USB-C przesyła prąd i dane według sztywnych, przewidywalnych reguł. MCP przesyła opisy w języku naturalnym, na podstawie których model decyduje, co wywołać. To znaczy, że w kabel wbudowany jest element niedeterministyczny — i że treść płynąca tym kablem może wpływać na zachowanie modelu. To rozróżnienie wraca w części 4, przy bezpieczeństwie.

Problem, który to rozwiązuje

Przed MCP każda integracja asystenta z systemem była pisana osobno. Jeśli miałeś pięciu asystentów i dziesięć systemów firmowych, w najgorszym razie oznaczało to pięćdziesiąt integracji — każda z własnym uwierzytelnianiem, własnym formatem błędów i własnym cyklem utrzymania. To klasyczny problem M×N.

MCP zamienia go w M+N. Autor systemu pisze jeden serwer. Autor asystenta implementuje jednego klienta. Wszystko pomiędzy jest kwestią konfiguracji.

Drugi, mniej oczywisty problem to przenośność. Integracja napisana pod konkretnego asystenta znika razem z decyzją o zmianie narzędzia. Serwer MCP zostaje — i to jest ten sam argument, który przemawia za pisaniem skilli zamiast wiązania wiedzy firmowej z jednym dostawcą.

Historia w pięciu datach

DataCo się wydarzyło
25 listopada 2024Anthropic ogłasza MCP i publikuje specyfikację, SDK oraz zestaw gotowych serwerów (Google Drive, Slack, GitHub, Git, Postgres). Pierwsi partnerzy: Block, Zed, Replit, Sourcegraph. Pierwsza rewizja specyfikacji nosi numer 2024-11-05.
26 marca 2025Rewizja 2025-03-26: pełny framework autoryzacji na bazie OAuth 2.1, nowy transport Streamable HTTP zastępujący stary HTTP+SSE, adnotacje narzędzi.
18 czerwca 2025Rewizja 2025-06-18: ustrukturyzowane wyniki narzędzi, serwer MCP formalnie jako OAuth Resource Server, wymóg Resource Indicators (RFC 8707), nowy prymityw elicitation.
9 grudnia 2025Anthropic przekazuje MCP pod Agentic AI Foundation działającą przy Linux Foundation. Współzałożyciele fundacji: Anthropic, Block, OpenAI. Model techniczny zarządzania zostaje bez zmian — decyzje nadal podejmują maintainerzy.
28 lipca 2026Rewizja 2026-07-28: MCP staje się protokołem bezstanowym. Znikają sesje protokołu, handshake initialize i żądania inicjowane przez serwer. Pojawia się metoda server/discover i cache’owalne listy narzędzi.

Pomiędzy tymi datami mieści się jeszcze rewizja 2025-11-25 (OpenID Connect Discovery, ikony narzędzi, eksperymentalne zadania długobieżne) oraz uruchomienie oficjalnego rejestru serwerów we wrześniu 2025 — który do dziś opisuje się jako wersja podglądowa.

Ostrzeżenie, które oszczędzi Ci kilku godzin. Większość materiałów o MCP w polskim i angielskim internecie opisuje protokół w kształcie z połowy 2025 roku: z handshakiem initialize, identyfikatorami sesji i żądaniami wysyłanymi przez serwer do klienta. Rewizja 2026-07-28 to wszystko usunęła. Jeśli czytasz poradnik, który nie podaje, o której rewizji mówi — załóż, że jest nieaktualny w warstwie transportu i cyklu życia połączenia. Trzy prymitywy serwera są natomiast stabilne od pierwszej wersji i można je opisywać bez zastrzeżeń.

Czym MCP nie jest

To najczęstsze źródło nieporozumień, więc wyliczmy wprost:

  • MCP nie jest frameworkiem do budowania agentów. Nie zastępuje LangChaina, LlamaIndeksa ani żadnego innego frameworka. Opisuje wyłącznie warstwę komunikacji między agentem a systemem zewnętrznym.
  • MCP nie jest systemem RAG. Nie indeksuje dokumentów, nie liczy embeddingów, nie robi wyszukiwania semantycznego. Może natomiast udostępnić agentowi wyszukiwarkę, która to robi.
  • MCP nie zastępuje function callingu. Function calling to zdolność modelu do wywołania funkcji. MCP to standard opisujący, skąd te funkcje się biorą i jak się z nimi rozmawia. MCP jest warstwą standaryzacji nad function callingiem, nie jego alternatywą.
  • MCP nie jest API gateway’em. Nie robi rate limitingu, autoryzacji biznesowej ani transformacji danych. Te rzeczy musisz zbudować w swoim serwerze albo przed nim.
  • MCP nie jest gwarancją bezpieczeństwa. Standard definiuje wymagania, ale nie audytuje serwerów. Anthropic mówi to wprost o własnym katalogu konektorów: sprawdza je pod kątem kryteriów listingu, ale nie audytuje ich pod kątem bezpieczeństwa.

MCP a skille, RAG, function calling i reszta

MechanizmCo daje agentowiKiedy sięgaszKiedy to zły wybór
Promptjednorazową instrukcjęzadanie jednorazowe, eksperymentgdy robisz to samo co tydzień
Instrukcje projektustałe fakty o kontekście pracy„ten projekt używa pnpm”, „piszemy po polsku”gdy fakt dotyczy tylko jednego typu zadania
Skillprocedurę ładowaną na żądaniepowtarzalny workflow, format wyjściagdy potrzebujesz dostępu do systemu
MCPdostęp do systemu zewnętrznegoagent musi coś odczytać z albo zapisać do Gmaila, Jiry, bazygdy chodzi o wiedzę, nie o dostęp
RAGwyszukiwanie po dużym zbiorze dokumentówtysiące stron dokumentacji, baza wiedzygdy dokumentów jest kilkanaście
Function callingwywołanie funkcji w Twoim kodziepiszesz własnego agenta, masz jedno APIgdy chcesz, by z narzędzia korzystali też inni
Hook / skryptwymuszenie deterministycznecoś musi się wydarzyć zawszegdy potrzebna jest ocena sytuacji

Najkrótsza wersja tego rozróżnienia — i zdanie, które warto zapamiętać z całego artykułu:

MCP daje agentowi nowe ręce. Skill daje mu know-how, jak tych rąk używać. Hook pilnuje, żeby nie zapomniał.

Te mechanizmy się nie wykluczają. Dojrzały setup w firmie wygląda tak: serwer MCP do Jiry (dostęp), skill „jak piszemy opisy zgłoszeń” (procedura), instrukcje projektu z nazwami boardów (fakty), hook blokujący commit bez numeru zgłoszenia (wymuszenie).


Część 2. Jak to działa pod spodem

Ta część jest najbardziej techniczna z pierwszych czterech. Jeśli interesuje Cię wyłącznie praktyczne używanie MCP, możesz przejść od razu do części 3 — ale warto wrócić tu później, bo bez tej mechaniki nie da się zrozumieć, skąd biorą się ograniczenia i ryzyka opisane w części 4.

Host, klient, serwer

W MCP występują trzy role i mylenie ich to najczęstszy błąd w rozmowach o tym protokole:

  • Host — aplikacja, z której korzystasz: aplikacja Claude, ChatGPT, VS Code, Cursor, Twój własny agent. To host trzyma model, okno kontekstowe i decyduje, co pokazać użytkownikowi.
  • Klient — komponent wewnątrz hosta, który utrzymuje połączenie z jednym serwerem. Jeśli podłączysz trzy serwery, host prowadzi trzech klientów.
  • Serwer — program wystawiający narzędzia, zasoby i prompty. Może działać lokalnie jako proces na Twoim komputerze albo zdalnie jako usługa HTTP.

Model nie rozmawia z serwerem bezpośrednio. Model produkuje żądanie wywołania narzędzia, host je przechwytuje, klient wysyła je do serwera, a wynik wraca do kontekstu modelu. Ta pośrednia rola hosta jest tym, co w ogóle umożliwia zatwierdzanie operacji przez człowieka.

Trzy prymitywy serwera

To fundament, stabilny od pierwszej wersji standardu. Kluczowe jest nie tylko co każdy z nich robi, ale kto o nim decyduje:

PrymitywKto sterujeCo to jestPrzykład
Narzędzia (tools)modelakcje, które model może wywołać sam, na podstawie opisu i kontekstu rozmowyutworz_zgloszenie, wyszukaj_klienta, wyslij_maila
Zasoby (resources)aplikacjadane identyfikowane adresem URI, które host wczytuje do kontekstuschemat bazy danych, plik konfiguracyjny, profil użytkownika
Prompty (prompts)użytkownikgotowe polecenia, które użytkownik wybiera świadomiekomenda „/podsumuj-sprint” wystawiona przez serwer Jiry

To rozróżnienie ma konsekwencje praktyczne. Skoro narzędzia wywołuje model, ich opisy muszą być pisane dla modelu, a nie dla człowieka. Skoro zasobami steruje aplikacja, nie masz gwarancji, że host w ogóle je pokaże — wiele hostów obsługuje dziś narzędzia znacznie lepiej niż zasoby. Skoro prompty wybiera użytkownik, są zwykle wystawiane jako komendy ze slashem.

Specyfikacja dodaje przy narzędziach ważne zastrzeżenie: ze względów bezpieczeństwa host powinien zawsze utrzymywać człowieka w pętli i umożliwiać odrzucenie wywołania.

Prymitywy po stronie klienta

Serwer też może czegoś potrzebować od klienta. W aktualnej rewizji aktywny jest jeden taki mechanizm:

  • Elicitation — serwer prosi użytkownika (za pośrednictwem klienta) o dodatkowe dane w trakcie wykonywania zadania. Ma dwa tryby: formularz (proste pola: tekst, liczba, wybór z listy) oraz przekierowanie na zewnętrzny adres URL. Specyfikacja stawia tu twardą granicę: serwer nie może prosić w formularzu o hasła, klucze API ani dane płatnicze — dla takich rzeczy musi użyć trybu URL.

Dwa starsze mechanizmy — sampling (serwer prosi klienta o wygenerowanie tekstu modelem) i roots (klient informuje serwer, na których katalogach ma pracować) — zostały w rewizji 2026-07-28 oznaczone jako przestarzałe. Jeśli spotkasz je w tutorialu, to sygnał, że materiał jest sprzed lipca 2026.

Transporty: stdio i Streamable HTTP

Są dwa oficjalne transporty i wybór między nimi to pierwsza decyzja architektoniczna przy pisaniu serwera.

stdio — klient uruchamia serwer jako proces potomny i rozmawia z nim przez standardowe wejście i wyjście. Zalety: zero konfiguracji sieciowej, naturalny dostęp do lokalnych plików, poświadczenia bierzesz ze zmiennych środowiskowych. Wady: serwer żyje tylko na tej jednej maszynie, a każdy użytkownik musi go u siebie zainstalować.

Streamable HTTP — serwer jest usługą pod jednym adresem URL, klient wysyła do niego żądania metodą POST. Odpowiedź może być pojedynczym JSON-em albo strumieniem zdarzeń. Zalety: jeden serwer dla całej firmy, aktualizacje bez akcji po stronie użytkowników, prawdziwa autoryzacja OAuth. Wady: trzeba to gdzieś hostować i porządnie zabezpieczyć.

Stary transport HTTP+SSE (dwa osobne endpointy) został zastąpiony przez Streamable HTTP już w marcu 2025 i w rewizji 2026-07-28 formalnie oznaczony jako przestarzały, z minimum dwunastomiesięcznym oknem wycofania. Nie buduj na nim nic nowego.

Dwa wymagania bezpieczeństwa, które specyfikacja stawia wprost przy Streamable HTTP i które łatwo przeoczyć:

  1. Serwer musi walidować nagłówek Origin, żeby uniemożliwić atak typu DNS rebinding. Przy nieprawidłowym Origin odpowiada kodem 403.
  2. Serwer działający lokalnie powinien nasłuchiwać wyłącznie na 127.0.0.1, nigdy na 0.0.0.0.

Powód, dla którego to nie jest teoria: badanie firmy Knostic z lipca 2025 zidentyfikowało 1862 serwery MCP wystawione publicznie do internetu; w ręcznie zweryfikowanej próbce 119 z nich wszystkie udostępniały listę narzędzi bez jakiegokolwiek uwierzytelnienia.

Co realnie leci po drucie

Protokołem transportowym jest JSON-RPC 2.0. W rewizji 2026-07-28 nie ma już fazy inicjalizacji — każde żądanie samo deklaruje wersję protokołu i możliwości klienta w polu _meta. Odkrywanie możliwości serwera odbywa się metodą server/discover, którą serwer musi implementować.

Pobranie listy narzędzi wygląda tak:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Odpowiedź serwera:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "tools": [
      {
        "name": "get_weather",
        "title": "Weather Information Provider",
        "description": "Get current weather information for a location",
        "inputSchema": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City name or zip code"
            }
          },
          "required": ["location"]
        }
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}

Zwróć uwagę na trzy rzeczy. Po pierwsze, description i inputSchema to jedyne, co model wie o tym narzędziu — cała jakość działania zależy od tego, jak są napisane. Po drugie, pole resultType jest w tej rewizji obowiązkowe. Po trzecie, ttlMs i cacheScope to nowość: lista narzędzi jest teraz cache’owalna, co bezpośrednio obniża koszt kontekstowy przy kolejnych sesjach.

Samo wywołanie narzędzia:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "New York" }
  }
}

I odpowiedź:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "content": [
      {
        "type": "text",
        "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
      }
    ],
    "isError": false
  }
}

To wszystko. Protokół jest naprawdę prosty — cała trudność MCP leży w tym, co wystawiasz i jak to opisujesz, a nie w warstwie transportowej.

Warto znać jeszcze jedno rozróżnienie, bo wraca w części 5. Specyfikacja rozdziela błędy protokołu (nieznane narzędzie, źle sformułowane żądanie) od błędów wykonania narzędzia (padło API, walidacja odrzuciła dane). Te pierwsze to błąd JSON-RPC. Te drugie wracają jako zwykły wynik z flagą isError: true — i to jest celowe, bo klient powinien przekazać taki błąd modelowi, żeby model mógł sam się poprawić.

Autoryzacja i tożsamość

Przy transporcie stdio autoryzacja OAuth nie jest stosowana — poświadczenia bierzesz ze zmiennych środowiskowych. Przy HTTP obowiązuje pełny model oparty o OAuth 2.1, w którym serwer MCP jest Resource Serverem, a nie serwerem autoryzacyjnym.

Praktyczne minimum, które musi zrobić autor zdalnego serwera:

  1. Wystawić metadane chronionego zasobu pod /.well-known/oauth-protected-resource, wskazujące serwer autoryzacyjny.
  2. Odpowiadać kodem 401 z nagłówkiem WWW-Authenticate, w którym podaje adres tych metadanych i wymagane uprawnienia.
  3. Walidować, że token został wystawiony właśnie dla niego. Specyfikacja stawia tu twarde „musi”: serwer musi odrzucić każdy token, który nie jest przeznaczony dla niego.
  4. Nigdy nie przekazywać otrzymanego tokenu dalej. Jeśli serwer MCP woła zewnętrzne API, bierze na to osobny token.

Punkty 3 i 4 wyglądają na formalność, ale to one blokują dwie najgroźniejsze klasy ataków: token passthrough (serwer staje się otwartym proxy do eksfiltracji danych) i confused deputy (serwer wykorzystuje swoje zaufane uprawnienia w imieniu atakującego). Po stronie klienta odpowiednikiem jest parametr resource z RFC 8707, który wiąże token z konkretnym serwerem — klient musi go wysyłać niezależnie od tego, czy serwer autoryzacyjny go obsługuje.

Dla firm istnieje osobne, stabilne rozszerzenie: Enterprise-Managed Authorization. Zamiast każdorazowego logowania użytkownika do każdego serwera, dostawca tożsamości organizacji (np. Okta czy Entra ID) staje się autorytatywnym decydentem, a klient wymienia asercję tożsamości na token dostępu. Zysk: jedna polityka, SSO i — co ważniejsze — natychmiastowa centralna rewokacja dostępu we wszystkich klientach MCP naraz.


Część 3. Jak używać MCP bez pisania kodu

Gdzie MCP w ogóle działa

NarzędzieJak podłączaszOgraniczenia
Aplikacja Claude (web, desktop, mobile, Cowork)katalog konektorów w ustawieniach albo własny adres URL serwera zdalnegotylko serwery zdalne; wspólny katalog dla wszystkich powierzchni Claude
Claude Codekomenda claude mcp add lub plik .mcp.json w repozytoriumserwery lokalne i zdalne; zakresy: lokalny, projektowy, użytkownika
ChatGPTkonektory oraz „developer mode” z pełnym MCPdeveloper mode tylko w wersji webowej, wymaga serwerów zdalnych; dostępność zależy od planu
API OpenAI (Responses)narzędzie typu mcp w wywołaniu APItylko serwery zdalne; domyślnie każde wywołanie wymaga zatwierdzenia
API Anthropic (Messages)pole mcp_servers w wywołaniutylko serwery zdalne, nie obsługuje stdio
VS Code + GitHub Copilotplik .vscode/mcp.json albo konfiguracja użytkownikaklucz w pliku to servers, nie mcpServers — częste źródło błędów
Cursor~/.cursor/mcp.json (globalnie) lub .cursor/mcp.json (projekt)obsługuje podstawianie zmiennych środowiskowych
Gemini CLIsettings.json, klucz mcpServers, komenda gemini mcp adddla Streamable HTTP używa pola httpUrl, nie url
JetBrains AI Assistantkonfiguracja w ustawieniach IDEIDE JetBrains są też serwerem MCP dla zewnętrznych agentów

Podłączanie krok po kroku

Wariant A — gotowy konektor w aplikacji Claude. Najprostsza droga: wchodzisz do katalogu konektorów, wybierasz usługę, logujesz się przez OAuth. Warto wiedzieć, co oznaczają etykiety: verified to konektory przetestowane przez Anthropic pod kątem jakości i zgodności — nie jest to audyt bezpieczeństwa. Community to konektory przesiane, ale nierecenzowane dogłębnie. Po podłączeniu jedne i drugie mają te same uprawnienia.

Wariant B — serwer zdalny w Claude Code. Jedna komenda:

claude mcp add --transport http notion https://mcp.notion.com/mcp

Jeśli serwer wymaga statycznego tokenu zamiast OAuth:

claude mcp add --transport http secure-api https://api.example.com/mcp \
  --header "Authorization: Bearer your-token"

Wariant C — serwer lokalny. Zwróć uwagę na --, które oddziela opcje od komendy uruchamiającej serwer:

claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

Wariant D — konfiguracja w repozytorium. Plik .mcp.json w katalogu projektu jest wersjonowany razem z kodem, więc cały zespół dostaje ten sam zestaw serwerów:

{
  "mcpServers": {
    "shared-server": {
      "type": "http",
      "url": "https://example.com/mcp"
    }
  }
}

Pułapka. Wpis z polem url, ale bez type, jest traktowany jako serwer lokalny i po cichu pomijany. To najczęstszy błąd konfiguracyjny w MCP. Druga pułapka: serwery z zakresu projektowego wymagają zatwierdzenia w sesji interaktywnej, ale w trybie nieinteraktywnym ładują się bez pytania — o czym warto pamiętać, uruchamiając agenta w CI.

Dla porównania ten sam serwer w VS Code — zwróć uwagę na inną nazwę klucza:

{
  "servers": {
    "github": { "type": "http", "url": "https://api.githubcopilot.com/mcp" }
  }
}

Jak sprawdzić, że działa

Pierwsza linia diagnostyki to lista serwerów w Twoim kliencie. W Claude Code:

claude mcp list

Statusy są jednoznaczne: połączony, wymaga uwierzytelnienia albo nie udało się połączyć.

Drugą linią jest MCP Inspector — oficjalne narzędzie diagnostyczne, dostępne w trzech wariantach: przeglądarkowym, terminalowym i skryptowalnym z wiersza poleceń. Ten ostatni nadaje się do CI:

npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list

I wywołanie konkretnego narzędzia z argumentami:

npx @modelcontextprotocol/inspector --cli node build/index.js \
  --method tools/call --tool-name mytool --tool-arg key=value

Trzy najczęstsze problemy i ich przyczyny:

  • Serwer w ogóle się nie pojawia — najczęściej zła ścieżka do interpretera albo brakujące type w konfiguracji. Uruchom komendę serwera ręcznie w terminalu: serwer stdio powinien milczeć i czekać. Traceback albo natychmiastowe wyjście to prawdziwy błąd.
  • Serwer jest, ale model nie używa narzędzi — to prawie zawsze wina opisów. Model wybiera narzędzie wyłącznie na podstawie nazwy, opisu i schematu argumentów.
  • Serwer działa raz, potem przestaje — sprawdź, czy token nie wygasł i czy serwer nie loguje przypadkiem na standardowe wyjście (patrz część 5).

Z czym MCP łączy się najlepiej

Kryterium doboru jest zaskakująco proste i warto je zapamiętać: MCP wygrywa tam, gdzie inaczej kopiowałbyś dane z innego narzędzia do czatu.

KategoriaPrzykładyCo realnie zyskujeszCzego się spodziewać
Zarządzanie pracąJira, Asana, Notion, Linearagent czyta zgłoszenie i od razu pracuje nad zadaniemduże projekty zwracają dużo danych — trzeba filtrować
Repozytoria i CIGitHub, Azure DevOpsprzegląd PR-ów, tworzenie zgłoszeń, czytanie logów buildównajpoważniejszy wektor prompt injection (patrz część 4)
MonitoringSentry, systemy obserwowalności„pokaż mi najczęstszy błąd z ostatniej doby i znajdź go w kodzie”najczystszy przypadek użycia MCP
Bazy danychPostgreSQL i podobneodpowiedzi na pytania o dane bez pisania SQL-a ręczniedomyślnie tylko do odczytu, zawsze
Płatności i CRMStripe, HubSpot, Salesforcesprawdzenie statusu klienta i historii płatności bez przełączania kartdane wrażliwe — najostrzejszy reżim uprawnień
Poczta i kalendarzGmail, Outlook, Kalendarz Googleumawianie, wyszukiwanie ustaleń w mailachklasyczne miejsce na wyciek danych
Dyski i dokumentyGoogle Drive, SharePoint, Dropboxpraca na dokumentach bez pobierania ich ręcznieprzy dużych zbiorach lepszy RAG
KomunikatorySlack, Teams, Discordpodsumowania wątków, wyszukiwanie decyzjidużo szumu w danych wejściowych
DesignFigmagenerowanie kodu z projektujakość zależy od dyscypliny w pliku projektowym
Infrastruktura chmurowaAWS, Cloudflare, Google Clouddiagnostyka, przegląd konfiguracjiuprawnienia do zapisu tylko przez osobne konto serwisowe
Automatyzacja przeglądarki i systemu plikówPlaywright, serwery plikowe, Gittesty end-to-end, praca na lokalnym repozytoriumnajszersze uprawnienia, najwięcej podatności historycznie

Kombo MCP + skill

To najważniejszy praktyczny wniosek całego artykułu, więc rozpiszmy go na konkretnym przykładzie.

Podłączasz serwer MCP do Jiry. Agent od tej chwili potrafi utworzyć zgłoszenie. Ale nie wie, że w Waszej firmie każde zgłoszenie ma mieć tytuł w trybie rozkazującym, sekcję „kroki reprodukcji”, etykietę zespołu i szacowanie w punktach. Za pierwszym razem podpowiadasz mu to w prompcie. Za piątym masz dość.

Wtedy piszesz skill zgloszenie-jira z opisem: „Tworzy zgłoszenie w Jirze zgodnie ze standardem zespołu. Użyj, gdy użytkownik prosi o założenie buga, taska albo zgłoszenia”. W ciele skilla umieszczasz szablon i zasady. Od tej chwili wystarczy: „załóż zgłoszenie na ten błąd z Sentry”.

Efekt: MCP do Sentry (dostęp do błędu) + MCP do Jiry (dostęp do zapisu) + skill (wiedza, jak to opisać) + instrukcje projektu (nazwy boardów i etykiet). Cztery różne mechanizmy, każdy robi dokładnie jedną rzecz. To jest wzorzec, do którego warto dążyć — i powód, dla którego pytanie „skille czy MCP?” jest źle postawione.


Część 4. Kiedy używać, kiedy nie i na co uważać

Test czterech pytań

Zanim podłączysz kolejny serwer MCP, odpowiedz sobie na cztery pytania. Jeśli na którekolwiek odpowiadasz „nie”, prawdopodobnie MCP nie jest tym, czego szukasz.

  1. Czy agent musi coś odczytać z zewnętrznego systemu albo do niego zapisać? Jeśli chodzi o wiedzę, procedurę albo format wyjścia — to nie jest zadanie dla MCP.
  2. Czy zrobisz to więcej niż raz? Jednorazowe pobranie danych szybciej załatwisz kopiuj-wklej niż konfiguracją serwera.
  3. Czy jesteś gotów dać temu serwerowi dostęp na swoich uprawnieniach? Bo dokładnie to robisz. Jeśli odpowiedź brzmi „w sumie nie wiem, co ten serwer robi” — nie podłączaj go.
  4. Czy zysk przewyższa koszt kontekstowy? Serwer wystawiający czterdzieści narzędzi, z których używasz dwóch, kosztuje Cię w każdej sesji.

Kiedy odpuścić i co zamiast

SytuacjaZamiast MCP użyj
Potrzebujesz raz pobrać danekopiuj-wklej albo załącznik
Agent nie wie, jak coś zrobićskilla
Agent nie zna stałego faktu o projekcieinstrukcji projektu
Masz tysiące dokumentów do przeszukaniaRAG
Coś musi się zadziać zawsze i identycznieskryptu, hooka albo kroku w CI
Piszesz własnego agenta i masz jedno API do zawołaniazwykłego narzędzia w kodzie
Proces jest krytyczny i nie znosi zmiennościklasycznej integracji, bez modelu w środku
Chcesz dać agentowi dostęp do produkcyjnej bazy z prawem zapisunie rób tego; zbuduj wąskie, audytowane narzędzia do konkretnych operacji

Koszt kontekstu — punkt, który wszyscy pomijają

Definicje wszystkich narzędzi ze wszystkich podłączonych serwerów trafiają do okna kontekstowego modelu, zanim zadasz pierwsze pytanie. To nie jest detal.

Anthropic opisał ten problem we własnym materiale inżynieryjnym z listopada 2025. Dla scenariusza łączącego dysk z systemem CRM naiwne podejście — wszystkie definicje narzędzi w kontekście, każdy wynik pośredni przechodzący przez model — zużywało 150 000 tokenów. Po przestawieniu na ładowanie narzędzi na żądanie i przetwarzanie danych poza kontekstem: 2 000 tokenów, czyli redukcja o 98,7%. Drugi materiał tej samej firmy podaje, że mechanizm wyszukiwania narzędzi ograniczył zużycie kontekstu o około 85% i jednocześnie podniósł trafność wyboru narzędzia.

Dwie uwagi metodologiczne: to liczby z materiałów jednego dostawcy, dotyczące wybranych scenariuszy, a nie niezależne benchmarki. Nie znam publicznych, niezależnych pomiarów tego zjawiska. Ale kierunek jest niekwestionowany i widać go w produktach — mechanizmy filtrowania i odroczonego ładowania narzędzi pojawiły się w API Anthropic, w API OpenAI, w Gemini CLI i w Claude Code.

Co z tym zrobić w praktyce:

  • Trzymaj podłączone tylko te serwery, których używasz w danym projekcie. Zakres projektowy w .mcp.json jest do tego stworzony.
  • Wyłączaj pojedyncze narzędzia, jeśli Twój klient to umożliwia. Serwer wystawiający czterdzieści narzędzi rzadko potrzebuje wszystkich naraz.
  • Ogranicz rozmiar wyników. Narzędzie zwracające 200 rekordów zamiast dziesięciu kosztuje dwadzieścia razy więcej przy każdym wywołaniu.
  • Sprawdź, ile realnie zajmują Twoje serwery. Wiele klientów pokazuje to wprost; jeśli nie — porównaj zużycie tokenów w pustej sesji z podłączonymi serwerami i bez nich.

Bezpieczeństwo

To najpoważniejsza część tego artykułu i najczęściej pomijana w poradnikach. Serwer MCP to kod, który uruchamiasz na swoich uprawnieniach, a jego opisy narzędzi trafiają wprost do promptu modelu. Obie te rzeczy są wektorami ataku.

Zatruwanie opisów narzędzi (tool poisoning). Złośliwe instrukcje ukryte w opisie narzędzia są niewidoczne dla użytkownika, ale w pełni widoczne dla modelu. Invariant Labs zademonstrowało to w kwietniu 2025 na Cursorze: agent czytał lokalny plik konfiguracyjny z kluczami oraz klucze SSH i wysyłał je do serwera atakującego, podczas gdy użytkownik w oknie potwierdzenia widział tylko niewinną nazwę narzędzia. Obrona: przeglądaj opisy narzędzi, nie tylko kod; instaluj wyłącznie serwery ze źródeł, którym ufasz.

Podmiana definicji po zatwierdzeniu (rug pull). Serwer, który raz uzyskał Twoją zgodę, może przy kolejnym uruchomieniu wystawić zupełnie inne narzędzia. Obrona: przypinaj wersje pakietów, hashuj definicje narzędzi i alarmuj, gdy opis się zmieni.

Line jumping. Trail of Bits opisał w kwietniu 2025 problem, którego nie da się rozwiązać zgodą użytkownika: opisy narzędzi trafiają do kontekstu modelu w momencie połączenia, zanim zadziała jakikolwiek mechanizm zatwierdzania. Serwer może wpłynąć na zachowanie modelu, nie będąc ani razu wywołanym. Obrona: odłączaj nieużywane serwery; nie trzymaj podłączonego serwera „na wszelki wypadek”.

Wstrzyknięcie instrukcji przez dane zwracane z serwera. To dziś najgroźniejsza klasa, bo nie wymaga złośliwego serwera — wystarczy złośliwa treść w uczciwym systemie. Invariant Labs pokazało w maju 2025 atak na serwer MCP GitHuba: atakujący zakłada zgłoszenie w publicznym repozytorium z ukrytym poleceniem, użytkownik prosi agenta o przegląd zgłoszeń, a agent wciąga dane z prywatnych repozytoriów i publikuje je w automatycznie utworzonym pull requeście. Autorzy podkreślają, że to nie jest błąd w kodzie serwera, tylko problem architektoniczny na poziomie systemu agentowego. Analogiczny scenariusz opisano dla serwera do bazy danych, gdzie MCP działał na poświadczeniach omijających kontrolę dostępu na poziomie wierszy.

Śmiertelna triada. Simon Willison sformułował w czerwcu 2025 regułę, która porządkuje całą tę dyskusję. Niebezpieczne jest połączenie trzech rzeczy naraz: (1) dostępu do prywatnych danych, (2) ekspozycji na niezaufaną treść, (3) możliwości komunikacji na zewnątrz. Każde z osobna jest do opanowania. Wszystkie trzy razem to gotowy kanał eksfiltracji — a MCP wyjątkowo ułatwia ich nieświadome zestawienie, bo zachęca do podłączania narzędzi z wielu źródeł. Obrona: wytnij trzeci element. Tryb tylko do odczytu, brak wyjścia na zewnątrz albo brak automatycznego publikowania — którykolwiek z nich rozbraja układ.

Podatności w konkretnych komponentach. Rok 2025 przyniósł serię poważnych CVE: krytyczne wykonanie kodu w popularnym mostku mcp-remote (CVSS 9.6), krytyczna podatność w samym MCP Inspectorze umożliwiająca atak z poziomu przeglądarki (CVSS 9.4) oraz dwie podatności w oficjalnym serwerze plikowym Anthropic, pozwalające wyjść poza zatwierdzony katalog. Do tego pierwszy publicznie udokumentowany złośliwy serwer MCP w rejestrze npm we wrześniu 2025 — pakiet pozornie do wysyłki maili, który w jednej z kolejnych wersji zaczął po cichu wysyłać kopię każdej wiadomości na adres atakującego. Wniosek: śledź CVE dla komponentów, których używasz, i przypinaj wersje.

Skala problemu. Wspomniane wcześniej badanie Knostic: 1862 serwery MCP wystawione publicznie, w zweryfikowanej próbce 119 — sto procent bez uwierzytelnienia. Ankieta firmy Equixly z marca 2025 wśród popularnych implementacji serwerów wskazała wstrzykiwanie komend jako najczęstszą klasę podatności (43% znalezisk), przed SSRF (30%) i przechodzeniem po katalogach (22%); autorzy nie podali jednak wielkości próby, więc traktuj to jako sygnał, nie jako twardą statystykę.

Warto też wiedzieć, że OWASP prowadzi dziś dwie listy dotykające tego obszaru: roboczą OWASP MCP Top 10 (na jej szczycie: złe zarządzanie tokenami i ekspozycja sekretów) oraz OWASP Top 10 for Agentic Applications 2026.

Najczęstsze błędy

ObjawPrzyczynaCo zrobić
Model ignoruje narzędzie, choć serwer działaopis napisany dla człowieka, nie dla modelunapisz, co narzędzie robi i kiedy go użyć, słowami, których używa użytkownik
Odpowiedzi są wolne i drogiezbyt wiele podłączonych serwerów narazodłącz nieużywane, ogranicz zakres do projektu
Model gubi się przy wyborze narzędziadwa serwery z podobnymi narzędziamitrzymaj jeden serwer na obszar, prefiksuj nazwy
Model dostaje ścianę tekstu i traci wąteknarzędzie zwraca surowy, wielki JSONzwracaj to, czego model potrzebuje; dodaj limit i paginację
Agent wykonuje dziesięć wywołań zamiast jednegonarzędzia zbyt drobnoziarnisteprojektuj narzędzia wokół zadań użytkownika, nie wokół endpointów API
Model nie potrafi się poprawić po błędzienarzędzie rzuca surowy wyjątek technicznyzwracaj czytelny komunikat: co poszło źle i jak to naprawić
Klucze API wyciekająsekrety w pliku konfiguracyjnym MCPużywaj magazynu poświadczeń; agent potrafi odczytać ten plik i wysłać go dalej
Wszystko działało, po aktualizacji przestałobrak przypiętych wersjiprzypnij wersje serwerów i weryfikuj zmiany w definicjach narzędzi
Serwer stdio nie odpowiadalogi wypisywane na standardowe wyjścieloguj wyłącznie na standardowe wyjście błędów
Ktoś w firmie podłączył serwer, o którym nikt nie wiebrak polityki i allowlistywersjonuj konfigurację MCP razem z kodem
„Wdrożyliśmy MCP” bez konkretnego przypadku użyciamylenie standardu z rozwiązaniemzacznij od jednego zadania, które ktoś dziś robi ręcznie
Mylenie MCP ze skillemnierozróżnianie dostępu od wiedzypatrz tabela w części 1

Checklista wdrożeniowa dla firmy

Do skopiowania i przerobienia pod siebie:

  • Mamy listę dozwolonych serwerów MCP, trzymaną w kontroli wersji, a nie w głowach deweloperów.
  • Każdy serwer przeszedł przegląd źródła albo pochodzi od dostawcy, któremu świadomie ufamy.
  • Wersje serwerów są przypięte; zmiany w definicjach narzędzi generują alert.
  • Serwery dotykające baz danych działają domyślnie tylko do odczytu, na koncie bez uprawnień omijających kontrolę dostępu.
  • Operacje zapisujące i usuwające wymagają zatwierdzenia przez człowieka.
  • Sekrety leżą w magazynie poświadczeń, nie w plikach konfiguracyjnych.
  • Serwery lokalne działają w kontenerze lub sandboksie z minimalnymi uprawnieniami.
  • Żaden serwer nie jest wystawiony do internetu bez uwierzytelnienia.
  • Wywołania narzędzi są logowane i audytowalne.
  • Zakresy uprawnień są minimalne; nie ma uprawnień typu „pełny dostęp”.
  • Przeprowadziliśmy analizę śmiertelnej triady dla każdego zestawu podłączonych serwerów.
  • Wiemy, ile tokenów kosztuje nasz zestaw serwerów w pustej sesji.
  • Ktoś jest właścicielem tej konfiguracji i przegląda ją co kwartał.

Część 5. Zbuduj własny serwer MCP

Ta część jest dla osób, które piszą kod. Cały kod poniżej pochodzi z aktualnej dokumentacji oficjalnych SDK, w wersjach obsługujących rewizję 2026-07-28.

Uwaga krytyczna dla osób, które budowały serwery wcześniej. Oba oficjalne SDK przeszły na linię 2.x, dopasowaną do bezstanowej rewizji protokołu (stan na 24.09.2026: Python mcp 2.2.0 z 7.09.2026, TypeScript @modelcontextprotocol/server 2.1.0 z 23.09.2026). Linia 1.x nadal dostaje poprawki błędów i bezpieczeństwa — w TypeScripcie przez co najmniej 6 miesięcy od wydania v2 — ale nowe projekty zaczynaj od 2.x. W Pythonie klasa FastMCP z mcp.server.fastmcp została zastąpiona przez MCPServer z mcp.server. W TypeScripcie pakiet @modelcontextprotocol/sdk rozbito na @modelcontextprotocol/server i @modelcontextprotocol/client, a server.tool() zastąpiło server.registerTool(). Jeśli masz w projekcie pip install mcp bez ograniczenia wersji, świeża instalacja wciągnie wersję 2 i wywali się na imporcie. Kod z tutoriali sprzed lipca 2026 po prostu nie zadziała.

Poziom 1. Hello world

Instalacja:

uv add "mcp[cli]"      # albo: pip install "mcp[cli]"

Cały serwer — narzędzie, zasób i prompt w dwudziestu linijkach:

from mcp.server import MCPServer

mcp = MCPServer("Demo")


@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b


@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"


@mcp.prompt()
def summarize(text: str) -> str:
    """Summarize a piece of text in one sentence."""
    return f"Summarize the following text in one sentence:\n\n{text}"

Nazwa funkcji staje się nazwą narzędzia, docstring staje się opisem, a adnotacje typów — schematem argumentów. To wszystko, co dostaje model.

Wersja z wejściem uruchomieniowym:

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."


if __name__ == "__main__":
    mcp.run()

Strażnik if __name__ == "__main__": nie jest kosmetyką — wszystko, co ładuje ten plik (narzędzia deweloperskie, testy), importuje go, a bez strażnika import zamieniałby się w uruchomienie serwera.

Podgląd w Inspectorze:

uv run mcp dev server.py

Podłączenie do Claude Code:

claude mcp add bookshop -- uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py

Ten sam serwer w TypeScripcie:

npm install @modelcontextprotocol/server zod tsx
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

function createServer(): McpServer {
    const server = new McpServer({ name: 'bookshop', version: '1.0.0' });

    server.registerTool(
        'search-books',
        {
            description: 'Search the catalog by title or author',
            inputSchema: z.object({
                query: z.string().describe('Title or author to search for')
            })
        },
        async ({ query }) => ({
            content: [{ type: 'text', text: `Found 3 books matching ${query}.` }]
        })
    );

    return server;
}

void serveStdio(createServer);
console.error('bookshop MCP server running on stdio');

Zwróć uwagę na wzorzec fabryki: serveStdio przyjmuje funkcję budującą serwer, nie gotową instancję. To bezpośrednia konsekwencja bezstanowości protokołu.

Poziom 2. Serwer użytkowy

Różnica między zabawką a narzędziem, którego ktoś realnie użyje, sprowadza się do trzech rzeczy: walidacji wejścia, sensownych błędów i kontroli rozmiaru odpowiedzi.

Walidacja przez typy. W Pythonie ograniczenia zapisujesz deklaratywnie:

from typing import Annotated, Literal

from pydantic import Field

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def search_books(
    query: Annotated[str, Field(description="Title or author to search for.")],
    limit: Annotated[int, Field(ge=1, le=50, description="Maximum number of results.")] = 10,
    genre: Literal["fiction", "non-fiction", "poetry"] | None = None,
) -> str:
    """Search the catalog by title or author."""
    where = f" in {genre}" if genre else ""
    return f"Found 3 books matching {query!r}{where} (showing up to {limit})."

To nie jest ozdobnik. Wywołanie z limit=999 zwróci błąd narzędzia zanim Twoja funkcja się uruchomi, a model przeczyta ten błąd i spróbuje ponownie z poprawną wartością. Jedna linijka le=50 daje samopoprawiającego się agenta.

Błędy, z których model potrafi wyjść. Zwykły wyjątek wraca do modelu jako błąd wykonania narzędzia:

@mcp.tool()
def get_author(title: str) -> str:
    """Look up the author of a book in the catalog."""
    if title not in CATALOG:
        raise ValueError(f"No book titled {title!r} in the catalog.")
    return CATALOG[title]

Komunikat ma być instrukcją, nie diagnostyką. „Brak książki o tytule X w katalogu” jest użyteczne. KeyError at line 42 nie jest.

Adnotacje narzędzi. Informują hosta, czy operacja jest bezpieczna, żeby mógł automatycznie zatwierdzić odczyt i wymusić potwierdzenie przy operacji niszczącej:

from mcp.types import ToolAnnotations


@mcp.tool(
    title="Search the catalog",
    annotations=ToolAnnotations(read_only_hint=True, open_world_hint=False),
)
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."

Uwaga ze specyfikacji: adnotacje to wskazówki, nie gwarancje. Klient musi traktować je jako niezaufane, jeśli pochodzą z serwera, któremu nie ufa.

Zasoby i prompty. Zasób adresujesz URI, opcjonalnie z parametrami w szablonie:

@mcp.resource("config://app")
def get_config() -> str:
    """The active shop configuration."""
    return "theme=dark\nlanguage=en"


@mcp.resource("users://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """A customer's profile."""
    return f"User {user_id}: 12 orders since 2021."

Poziom 3. Serwer produkcyjny

Przejście na Streamable HTTP to w obu SDK zmiana jednej linijki — a potem kilka dni pracy nad wszystkim wokół.

Python:

if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=3001)

Klienci łączą się wtedy pod http://127.0.0.1:3001/mcp. Opcje przekazujesz do run(), nie do konstruktora — to częsty błąd dający nieczytelny TypeError. Warto znać domyślny limit rozmiaru żądania (4 MiB) oraz tryb json_response=True, który wyłącza strumieniowanie: wtedy tracisz raporty postępu i możliwość dopytania użytkownika w trakcie.

TypeScript:

import { createMcpHandler, McpServer } from '@modelcontextprotocol/server';
import * as z from 'zod/v4';

const handler = createMcpHandler(() => {
    const server = new McpServer({ name: 'notes', version: '1.0.0' });
    server.registerTool(
        'add-note',
        {
            description: 'Save a note',
            inputSchema: z.object({ text: z.string() })
        },
        async ({ text }) => ({ content: [{ type: 'text', text: `Saved: ${text}` }] })
    );
    return server;
});

Kluczowe zdanie z dokumentacji: fabryka uruchamia się raz na każde żądanie HTTP, świeża instancja obsługuje każde żądanie, a handler nie trzyma nic pomiędzy żądaniami. Rejestruj narzędzia wewnątrz fabryki, nigdy na współdzielonej instancji na zewnątrz. Dzięki temu endpoint jest bezstanowy i skaluje się poziomo bez żadnej dodatkowej pracy.

Handler nie ufa swojemu wywołującemu: nie waliduje nagłówka Host, nie waliduje Origin i nie sprawdza tokenu. To Twoje zadanie. Weryfikacja, że serwer w ogóle odpowiada — zwróć uwagę, że nie ma żadnego handshake’u, od razu leci tools/list:

curl -s -X POST http://127.0.0.1:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Do produkcji dochodzi jeszcze reszta listy: OAuth zgodnie z opisem z części 2, ograniczanie liczby żądań, logowanie wywołań z identyfikatorem korelacji, health check, kontener i wersjonowanie narzędzi. Zasada: traktuj serwer MCP jak każdą inną usługę produkcyjną, bo nią jest — z tą różnicą, że jej klientem jest model, który potrafi wywołać ją w sposób, którego nie przewidziałeś.

Jak pisać opisy narzędzi

To sekcja, która decyduje o tym, czy Twój serwer będzie użyteczny. Model wybiera narzędzie wyłącznie na podstawie nazwy, opisu i schematu argumentów. Nic więcej nie widzi.

Reguły nazewnictwa ze specyfikacji: od 1 do 128 znaków, tylko litery, cyfry, podkreślenie, myślnik i kropka; bez spacji i przecinków; unikalne w obrębie serwera. Unikalność jest per serwer — jeśli agregujesz kilka serwerów, prefiksuj nazwy sam.

# ŹLE — model nie ma pojęcia, kiedy tego użyć
@mcp.tool()
def process(data: str) -> str:
    """Processes the data."""

# DOBRZE — czynność, kontekst użycia i słowa, których używa użytkownik
@mcp.tool()
def find_customer_invoices(
    customer_email: Annotated[str, Field(description="Adres e-mail klienta, dokładne dopasowanie.")],
    status: Literal["paid", "unpaid", "overdue"] = "unpaid",
) -> str:
    """Znajduje faktury klienta po adresie e-mail. Użyj, gdy użytkownik pyta o
    faktury, płatności, zaległości albo status rozliczeń konkretnego klienta.
    Zwraca maksymalnie 20 najnowszych faktur."""

Trzy zasady, które podnoszą trafność najbardziej:

  1. Napisz, kiedy narzędzia użyć — nie tylko co robi. Zdanie „Użyj, gdy użytkownik pyta o…” z konkretnymi słowami jest wart więcej niż akapit opisu technicznego.
  2. Opisuj każdy argument. Opis pola trafia do schematu i to jedyna dokumentacja parametru, jaką dostaje model.
  3. Napisz, czego narzędzie NIE robi, jeśli łatwo je pomylić z innym. Jedno zdanie oszczędza serię błędnych wywołań.

Jeśli narzędzie tworzy jakiś stan trwający między wywołaniami — koszyk, sesję eksportu, długie zadanie — politykę wygasania też opisz w opisie narzędzia. Model widzi tylko to.

Co zwracać i w jakiej formie

Trzy zasady:

Zwracaj to, czego model potrzebuje, nie całą bazę. Pole content jest dla modelu i płacisz za nie tokenami przy każdym wywołaniu. Jeśli użytkownik pyta o status zamówienia, zwróć status — nie cały rekord z trzydziestoma polami audytowymi.

Używaj ustrukturyzowanego wyjścia, gdy dane mają iść do aplikacji. W Pythonie adnotacja typu zwracanego jest schematem wyjścia; w TypeScripcie deklarujesz outputSchema i zwracasz structuredContent. Dla zgodności wstecznej warto obok tego zwrócić czytelną wersję tekstową.

Zawsze przewiduj paginację przy listach. Metody listujące wspierają kursory, a od rewizji 2026-07-28 ich wyniki niosą też pola cache’owania (ttlMs, cacheScope). Lista narzędzi powinna mieć deterministyczną kolejność — to warunek sensownego cache’owania i lepszego trafiania w cache promptu.

Testowanie i dystrybucja

Testuj na trzech poziomach. Po pierwsze, testy jednostkowe samych funkcji — to zwykły kod, testujesz go zwyczajnie. Po drugie, kontrakt protokołu: Inspector w trybie wiersza poleceń wpina się w CI i sprawdza, że tools/list zwraca to, co ma. Po trzecie — i to jest test, który wszyscy pomijają — czy model wybiera właściwe narzędzie. Napisz pięć realistycznych poleceń użytkownika i sprawdź, czy agent trafia. To jedyny test, który mierzy jakość opisów.

Pułapka numer jeden przy stdio: nie pisz na standardowe wyjście. Standardowe wyjście jest kanałem protokołu — host parsuje każdą jego linię jako komunikat JSON-RPC. Jeden console.log albo print() psuje połączenie. Loguj na standardowe wyjście błędów. Python ma częściową siatkę bezpieczeństwa, ale nie jest szczelna: print() wykonany przy imporcie albo w skrypcie opakowującym nadal trafi na kanał protokołu.

Dystrybucja. Najprostsza droga to opublikowanie pakietu, który da się uruchomić bez instalacji (npx, uvx) — użytkownik wkleja jedną linijkę do konfiguracji. W zespole: .mcp.json w repozytorium, wersjonowany razem z kodem. Publicznie: wpis w oficjalnym rejestrze MCP, który jest źródłem danych dla katalogów w konkretnych aplikacjach. Zawsze wersjonuj i traktuj zmianę nazwy albo semantyki narzędzia jak zmianę łamiącą API — bo dla czyjegoś agenta dokładnie tym jest.

Ściąga

DecyzjaWybierzKiedy
Transportstdioserwer lokalny, dostęp do plików, jeden użytkownik
Streamable HTTPserwer firmowy, wielu użytkowników, OAuth
Prymitywnarzędziemodel ma to wywołać sam
zasóbaplikacja ma to wczytać do kontekstu
promptużytkownik ma to wybrać świadomie
Granulacja narzędziwokół zadań użytkownikazawsze; nie mapuj jeden do jednego na endpointy API
Uprawnieniatylko odczyt domyślniezawsze, dopóki nie ma twardego uzasadnienia
BłądisError z czytelnym komunikatembłąd wykonania — model ma się poprawić
błąd JSON-RPCbłąd protokołu — nieznane narzędzie, złe żądanie
Wynikkrótki tekst dla modeluzawsze
structuredContentgdy dane idą do aplikacji
Logowanie przy stdiostandardowe wyjście błędówzawsze, bez wyjątków

MCP w 2026 i co dalej

Stan faktyczny. MCP przestało być formatem jednego dostawcy. Rozwijają go maintainerzy pod Linux Foundation, a wspierają go wszystkie duże platformy: aplikacje i API Anthropic, ChatGPT i Responses API OpenAI, Gemini CLI i serwery Google Cloud, Copilot Studio, VS Code i Azure DevOps po stronie Microsoftu, AWS przez własny zestaw serwerów i usługi hostingowe, Cloudflare, JetBrains, Cursor. Najtwardsza publicznie dostępna miara skali pochodzi od samego projektu: oficjalne SDK notują rzędy setek milionów pobrań miesięcznie.

Kierunek techniczny jest jasny: zdalnie zamiast lokalnie. Rewizja 2026-07-28 została zaprojektowana pod hosting — bezstanowość, cache’owalne listy, nagłówki pozwalające bramie sieciowej autoryzować żądanie bez zaglądania w jego treść. Cloudflare potwierdza efekt praktyczny: serwery MCP działają dziś na jego platformie bez dodatkowej warstwy trzymającej stan.

Rozszerzenia zamiast puchnącego rdzenia. Projekt formalnie wprowadził mechanizm rozszerzeń — opcjonalnych, negocjowanych, domyślnie wyłączonych. Trzy warto znać: MCP Apps (narzędzia zwracają interaktywny interfejs renderowany w izolowanej ramce — ogłoszone w styczniu 2026 wspólnie przez Anthropic i OpenAI), Tasks (zadania długobieżne z odpytywaniem o status) oraz opisane wcześniej Enterprise-Managed Authorization.

Skille i MCP się zbliżają, ale nie zastępują. Grupa robocza „Skills over MCP” doprowadziła do przyjęcia propozycji SEP-2640 (status Final, 13.09.2026): powstało oficjalne rozszerzenie io.modelcontextprotocol/skills z metodami skills/list i skills/get oraz adresami skill://, zbudowane na istniejącym prymitywie zasobów. Serwer MCP może więc dostarczyć agentowi nie tylko narzędzia, ale i procedury. To nie jest „skille zamiast MCP” — to standaryzacja tego, jak procedury trafiają do agenta tym samym kanałem co dostęp. Adopcja przez klientów dopiero się zaczyna, więc sprawdź dokumentację swojego narzędzia, zanim na tym oprzesz wdrożenie.

MCP i A2A to nie konkurenci. Protokół Agent2Agent, przekazany przez Google pod Linux Foundation, opisuje komunikację między agentami przez granice organizacji. MCP opisuje podłączenie agenta do narzędzi i danych. Oficjalne stanowisko obu projektów mówi o komplementarności — i na tym etapie nic nie wskazuje, żeby miało się to zmienić.

Najmocniejsza krytyka MCP pochodzi od jego twórców. Materiał inżynieryjny Anthropic o wykonywaniu kodu zamiast bezpośrednich wywołań narzędzi jest w istocie krytyką „naiwnego MCP”: ładowanie wszystkich definicji do kontekstu nie skaluje się i widać to już przy kilkunastu serwerach. Odpowiedzią nie jest porzucenie protokołu, tylko lepsze pośrednictwo — filtrowanie narzędzi, ładowanie na żądanie, przetwarzanie danych poza kontekstem.

Nasza ocena, wyraźnie oddzielona od faktów. Spodziewamy się trzech rzeczy. Po pierwsze, konsolidacji wokół serwerów firmowych — zamiast dziesięciu serwerów na laptopie każdego pracownika, jedna brama MCP z centralną polityką i audytem; protokół już się pod to przygotował. Po drugie, dojrzewania warstwy bezpieczeństwa — skanowanie definicji narzędzi i przypinanie ich hashy stanie się higieną, tak jak dziś skanowanie zależności. Po trzecie, rozwarstwienia rynku serwerów: garść dopracowanych, oficjalnych integracji obok długiego ogona pakietów, których nikt nie audytuje. To ostatnie jest jednocześnie największym ryzykiem tego ekosystemu.

Czego natomiast nie oczekujemy: nowych transportów (maintainerzy mówią wprost, że w tym cyklu ich nie będzie) ani rezygnacji z niedeterministycznego charakteru MCP. To znaczy, że pytanie „czy podłączyć ten serwer” na długo pozostanie decyzją człowieka — i dlatego test czterech pytań z części 4 jest praktyczniejszy niż jakakolwiek lista rekomendowanych serwerów.


Co dalej

Najczęstsze pytania

Czym różni się MCP od skilla?
MCP daje agentowi dostęp do zewnętrznego systemu — to nowe „ręce”. Skill daje mu wiedzę, jak z tych rąk korzystać: jaką procedurę wykonać, w jakiej kolejności, w jakim formacie zwrócić wynik. Te dwie rzeczy stosuje się razem, nie zamiast siebie: serwer MCP do Jiry plus skill „jak opisujemy zgłoszenia”. Jeśli Twój problem brzmi „agent nie wie, jak coś zrobić” — to skill. Jeśli brzmi „agent nie ma jak tego zrobić” — to MCP.
Czy MCP działa tylko z Claude?
Nie. Anthropic wymyślił MCP i wypuścił go jako otwarty standard, a w grudniu 2025 przekazał go pod Agentic AI Foundation działającą przy Linux Foundation — współzałożycielami fundacji są Anthropic, Block i OpenAI. Dziś MCP obsługują m.in. aplikacje Claude i Claude Code, ChatGPT i Responses API OpenAI, Gemini CLI, VS Code z GitHub Copilotem, Cursor, JetBrains AI Assistant, Microsoft Copilot Studio oraz platformy AWS i Cloudflare.
Czy MCP jest bezpieczny?
Sam protokół definiuje mocne wymagania bezpieczeństwa (OAuth 2.1, walidacja audience tokenu, zakaz przekazywania cudzych tokenów dalej), ale ryzyko leży gdzie indziej: w serwerach, które podłączasz. Udokumentowano ataki przez zatrute opisy narzędzi, podmianę definicji po zatwierdzeniu, wstrzykiwanie instrukcji w danych zwracanych przez serwer oraz krytyczne CVE w popularnych komponentach. Traktuj każdy serwer MCP jak kod, który uruchamiasz na swoich uprawnieniach — bo nim jest.
Ile serwerów MCP można podłączyć naraz?
Technicznego limitu nie ma, ale jest limit praktyczny: definicje wszystkich narzędzi trafiają do okna kontekstowego modelu, zanim padnie pierwsze pytanie. Anthropic podaje scenariusz, w którym naiwne podejście zjadało 150 000 tokenów na samo wystawienie narzędzi. Dlatego trzymaj podłączone tylko te serwery, których faktycznie używasz w danym projekcie, i korzystaj z mechanizmów filtrowania narzędzi, jeśli Twój klient je ma.
Czy potrzebuję umieć programować, żeby korzystać z MCP?
Żeby korzystać — nie. Podłączenie gotowego serwera to najczęściej wklejenie adresu URL i zalogowanie się przez OAuth albo jedna komenda w terminalu. Żeby zbudować własny serwer — tak, ale próg jest niski: minimalny serwer w Pythonie to około dziesięciu linii, bo całą warstwę protokołu obsługuje oficjalne SDK.
Kiedy NIE używać MCP?
Gdy zadanie jest jednorazowe (wystarczy skopiować dane do czatu), gdy chodzi o wiedzę lub procedurę, a nie o dostęp (skill albo instrukcje projektu), gdy masz tysiące dokumentów do przeszukania (RAG), gdy coś ma się dziać zawsze i deterministycznie (skrypt, hook, krok w CI), gdy piszesz własnego agenta i potrzebujesz jednego wywołania REST (zwykłe narzędzie w kodzie jest prostsze) oraz gdy proces jest na tyle krytyczny, że nie chcesz mieć w nim modelu podejmującego decyzje.
Czym jest rewizja specyfikacji 2026-07-28 i czy muszę się nią przejmować?
To aktualna wersja standardu, opublikowana 28 lipca 2026. Usunęła sesje protokołu, handshake „initialize” i żądania inicjowane przez serwer — MCP stało się protokołem bezstanowym, znacznie łatwiejszym do hostowania zdalnie. Jeśli tylko podłączasz gotowe serwery, nie musisz się tym przejmować. Jeśli piszesz własny albo czytasz starsze poradniki, musisz: większość materiałów w sieci opisuje MCP w kształcie sprzed tej zmiany.
Czym jest oficjalny rejestr MCP?
To prowadzone przez projekt MCP repozytorium metadanych publicznie dostępnych serwerów, uruchomione we wrześniu 2025 i wciąż opisujące się jako wersja podglądowa. Nie hostuje kodu i nie prowadzi własnych audytów bezpieczeństwa — jest źródłem danych dla katalogów i marketplace’ów w konkretnych aplikacjach, a nie miejscem, z którego użytkownik końcowy instaluje serwery.

Źródła

  1. Specification (2026-07-28) — Model Context Protocol (dostęp: )
  2. Key Changes — MCP Specification 2026-07-28 — Model Context Protocol (dostęp: )
  3. Security Best Practices — MCP Specification — Model Context Protocol (dostęp: )
  4. Authorization — MCP Specification — Model Context Protocol (dostęp: )
  5. Introducing the Model Context Protocol — Anthropic (dostęp: )
  6. MCP joins the Agentic AI Foundation — Model Context Protocol (dostęp: )
  7. Code execution with MCP: Building more efficient agents — Anthropic Engineering (dostęp: )
  8. Connect Claude Code to tools via MCP — Anthropic (dostęp: )
  9. Python SDK — README i dokumentacja — Model Context Protocol (dostęp: )
  10. TypeScript SDK — README i dokumentacja — Model Context Protocol (dostęp: )
  11. MCP Security Notification: Tool Poisoning Attacks — Invariant Labs (dostęp: )
  12. Jumping the line: How MCP servers can attack you before you ever use them — Trail of Bits (dostęp: )
  13. The lethal trifecta for AI agents — Simon Willison (dostęp: )
  14. Exposing the Unseen: Mapping MCP Servers Across the Internet — Knostic (dostęp: )
  15. MCP Apps — Bringing UI Capabilities To MCP Clients — Model Context Protocol (dostęp: )
  16. Roadmap — Model Context Protocol (dostęp: )
  17. Skills over MCP Working Group (SEP-2640 — Final) — Model Context Protocol (dostęp: )
  18. Specification versioning — current protocol version — Model Context Protocol (dostęp: )
  19. mcp — historia wydań (PyPI) — PyPI (dostęp: )
  20. Upgrade to v2 — TypeScript SDK — Model Context Protocol (dostęp: )