MCP (Model Context Protocol) — kompletny poradnik: czym jest, jak go używać i jak zbudować własny serwer
- 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
- Część 1. Czym jest MCP i skąd się wziął
- Część 2. Jak to działa pod spodem
- Część 3. Jak używać MCP bez pisania kodu
- Część 4. Kiedy używać, kiedy nie i na co uważać
- Część 5. Zbuduj własny serwer MCP
- MCP w 2026 i co dalej
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
| Data | Co się wydarzyło |
|---|---|
| 25 listopada 2024 | Anthropic 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 2025 | Rewizja 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 2025 | Rewizja 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 2025 | Anthropic 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 2026 | Rewizja 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. Rewizja2026-07-28to 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
| Mechanizm | Co daje agentowi | Kiedy sięgasz | Kiedy to zły wybór |
|---|---|---|---|
| Prompt | jednorazową instrukcję | zadanie jednorazowe, eksperyment | gdy robisz to samo co tydzień |
| Instrukcje projektu | stałe fakty o kontekście pracy | „ten projekt używa pnpm”, „piszemy po polsku” | gdy fakt dotyczy tylko jednego typu zadania |
| Skill | procedurę ładowaną na żądanie | powtarzalny workflow, format wyjścia | gdy potrzebujesz dostępu do systemu |
| MCP | dostęp do systemu zewnętrznego | agent musi coś odczytać z albo zapisać do Gmaila, Jiry, bazy | gdy chodzi o wiedzę, nie o dostęp |
| RAG | wyszukiwanie po dużym zbiorze dokumentów | tysiące stron dokumentacji, baza wiedzy | gdy dokumentów jest kilkanaście |
| Function calling | wywołanie funkcji w Twoim kodzie | piszesz własnego agenta, masz jedno API | gdy chcesz, by z narzędzia korzystali też inni |
| Hook / skrypt | wymuszenie deterministyczne | coś musi się wydarzyć zawsze | gdy 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:
| Prymityw | Kto steruje | Co to jest | Przykład |
|---|---|---|---|
| Narzędzia (tools) | model | akcje, które model może wywołać sam, na podstawie opisu i kontekstu rozmowy | utworz_zgloszenie, wyszukaj_klienta, wyslij_maila |
| Zasoby (resources) | aplikacja | dane identyfikowane adresem URI, które host wczytuje do kontekstu | schemat bazy danych, plik konfiguracyjny, profil użytkownika |
| Prompty (prompts) | użytkownik | gotowe polecenia, które użytkownik wybiera świadomie | komenda „/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ć:
- Serwer musi walidować nagłówek
Origin, żeby uniemożliwić atak typu DNS rebinding. Przy nieprawidłowymOriginodpowiada kodem 403. - Serwer działający lokalnie powinien nasłuchiwać wyłącznie na
127.0.0.1, nigdy na0.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:
- Wystawić metadane chronionego zasobu pod
/.well-known/oauth-protected-resource, wskazujące serwer autoryzacyjny. - Odpowiadać kodem 401 z nagłówkiem
WWW-Authenticate, w którym podaje adres tych metadanych i wymagane uprawnienia. - 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.
- 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ędzie | Jak podłączasz | Ograniczenia |
|---|---|---|
| Aplikacja Claude (web, desktop, mobile, Cowork) | katalog konektorów w ustawieniach albo własny adres URL serwera zdalnego | tylko serwery zdalne; wspólny katalog dla wszystkich powierzchni Claude |
| Claude Code | komenda claude mcp add lub plik .mcp.json w repozytorium | serwery lokalne i zdalne; zakresy: lokalny, projektowy, użytkownika |
| ChatGPT | konektory oraz „developer mode” z pełnym MCP | developer 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 API | tylko serwery zdalne; domyślnie każde wywołanie wymaga zatwierdzenia |
| API Anthropic (Messages) | pole mcp_servers w wywołaniu | tylko serwery zdalne, nie obsługuje stdio |
| VS Code + GitHub Copilot | plik .vscode/mcp.json albo konfiguracja użytkownika | klucz 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 CLI | settings.json, klucz mcpServers, komenda gemini mcp add | dla Streamable HTTP używa pola httpUrl, nie url |
| JetBrains AI Assistant | konfiguracja w ustawieniach IDE | IDE 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 beztype, 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
typew 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.
| Kategoria | Przykłady | Co realnie zyskujesz | Czego się spodziewać |
|---|---|---|---|
| Zarządzanie pracą | Jira, Asana, Notion, Linear | agent czyta zgłoszenie i od razu pracuje nad zadaniem | duże projekty zwracają dużo danych — trzeba filtrować |
| Repozytoria i CI | GitHub, Azure DevOps | przegląd PR-ów, tworzenie zgłoszeń, czytanie logów buildów | najpoważniejszy wektor prompt injection (patrz część 4) |
| Monitoring | Sentry, systemy obserwowalności | „pokaż mi najczęstszy błąd z ostatniej doby i znajdź go w kodzie” | najczystszy przypadek użycia MCP |
| Bazy danych | PostgreSQL i podobne | odpowiedzi na pytania o dane bez pisania SQL-a ręcznie | domyślnie tylko do odczytu, zawsze |
| Płatności i CRM | Stripe, HubSpot, Salesforce | sprawdzenie statusu klienta i historii płatności bez przełączania kart | dane wrażliwe — najostrzejszy reżim uprawnień |
| Poczta i kalendarz | Gmail, Outlook, Kalendarz Google | umawianie, wyszukiwanie ustaleń w mailach | klasyczne miejsce na wyciek danych |
| Dyski i dokumenty | Google Drive, SharePoint, Dropbox | praca na dokumentach bez pobierania ich ręcznie | przy dużych zbiorach lepszy RAG |
| Komunikatory | Slack, Teams, Discord | podsumowania wątków, wyszukiwanie decyzji | dużo szumu w danych wejściowych |
| Design | Figma | generowanie kodu z projektu | jakość zależy od dyscypliny w pliku projektowym |
| Infrastruktura chmurowa | AWS, Cloudflare, Google Cloud | diagnostyka, przegląd konfiguracji | uprawnienia do zapisu tylko przez osobne konto serwisowe |
| Automatyzacja przeglądarki i systemu plików | Playwright, serwery plikowe, Git | testy end-to-end, praca na lokalnym repozytorium | najszersze 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.
- 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.
- Czy zrobisz to więcej niż raz? Jednorazowe pobranie danych szybciej załatwisz kopiuj-wklej niż konfiguracją serwera.
- 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.
- 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
| Sytuacja | Zamiast MCP użyj |
|---|---|
| Potrzebujesz raz pobrać dane | kopiuj-wklej albo załącznik |
| Agent nie wie, jak coś zrobić | skilla |
| Agent nie zna stałego faktu o projekcie | instrukcji projektu |
| Masz tysiące dokumentów do przeszukania | RAG |
| Coś musi się zadziać zawsze i identycznie | skryptu, hooka albo kroku w CI |
| Piszesz własnego agenta i masz jedno API do zawołania | zwykłego narzędzia w kodzie |
| Proces jest krytyczny i nie znosi zmienności | klasycznej integracji, bez modelu w środku |
| Chcesz dać agentowi dostęp do produkcyjnej bazy z prawem zapisu | nie 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.jsonjest 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
| Objaw | Przyczyna | Co zrobić |
|---|---|---|
| Model ignoruje narzędzie, choć serwer działa | opis napisany dla człowieka, nie dla modelu | napisz, co narzędzie robi i kiedy go użyć, słowami, których używa użytkownik |
| Odpowiedzi są wolne i drogie | zbyt wiele podłączonych serwerów naraz | odłącz nieużywane, ogranicz zakres do projektu |
| Model gubi się przy wyborze narzędzia | dwa serwery z podobnymi narzędziami | trzymaj jeden serwer na obszar, prefiksuj nazwy |
| Model dostaje ścianę tekstu i traci wątek | narzędzie zwraca surowy, wielki JSON | zwracaj to, czego model potrzebuje; dodaj limit i paginację |
| Agent wykonuje dziesięć wywołań zamiast jednego | narzędzia zbyt drobnoziarniste | projektuj narzędzia wokół zadań użytkownika, nie wokół endpointów API |
| Model nie potrafi się poprawić po błędzie | narzędzie rzuca surowy wyjątek techniczny | zwracaj czytelny komunikat: co poszło źle i jak to naprawić |
| Klucze API wyciekają | sekrety w pliku konfiguracyjnym MCP | używaj magazynu poświadczeń; agent potrafi odczytać ten plik i wysłać go dalej |
| Wszystko działało, po aktualizacji przestało | brak przypiętych wersji | przypnij wersje serwerów i weryfikuj zmiany w definicjach narzędzi |
| Serwer stdio nie odpowiada | logi wypisywane na standardowe wyjście | loguj wyłącznie na standardowe wyjście błędów |
| Ktoś w firmie podłączył serwer, o którym nikt nie wie | brak polityki i allowlisty | wersjonuj konfigurację MCP razem z kodem |
| „Wdrożyliśmy MCP” bez konkretnego przypadku użycia | mylenie standardu z rozwiązaniem | zacznij od jednego zadania, które ktoś dziś robi ręcznie |
| Mylenie MCP ze skillem | nierozróżnianie dostępu od wiedzy | patrz 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
mcp2.2.0 z 7.09.2026, TypeScript@modelcontextprotocol/server2.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 klasaFastMCPzmcp.server.fastmcpzostała zastąpiona przezMCPServerzmcp.server. W TypeScripcie pakiet@modelcontextprotocol/sdkrozbito na@modelcontextprotocol/serveri@modelcontextprotocol/client, aserver.tool()zastąpiłoserver.registerTool(). Jeśli masz w projekciepip install mcpbez 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:
- 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.
- Opisuj każdy argument. Opis pola trafia do schematu i to jedyna dokumentacja parametru, jaką dostaje model.
- 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
| Decyzja | Wybierz | Kiedy |
|---|---|---|
| Transport | stdio | serwer lokalny, dostęp do plików, jeden użytkownik |
| Streamable HTTP | serwer firmowy, wielu użytkowników, OAuth | |
| Prymityw | narzędzie | model ma to wywołać sam |
| zasób | aplikacja ma to wczytać do kontekstu | |
| prompt | użytkownik ma to wybrać świadomie | |
| Granulacja narzędzi | wokół zadań użytkownika | zawsze; nie mapuj jeden do jednego na endpointy API |
| Uprawnienia | tylko odczyt domyślnie | zawsze, dopóki nie ma twardego uzasadnienia |
| Błąd | isError z czytelnym komunikatem | błąd wykonania — model ma się poprawić |
| błąd JSON-RPC | błąd protokołu — nieznane narzędzie, złe żądanie | |
| Wynik | krótki tekst dla modelu | zawsze |
structuredContent | gdy dane idą do aplikacji | |
| Logowanie przy stdio | standardowe wyjście błędów | zawsze, 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
- MCP w praktyce — proste przykłady i automatyzacje — dziewięć przykładów dla różnych ról, porównanie z Zapierem, Make i n8n oraz trzy wzorce łączenia agenta z automatyzacją.
- Skille (SKILL.md) — kompletny poradnik — druga połowa tej układanki: jak dać agentowi procedurę, skoro MCP dało mu dostęp.
- Jak zbudować agenta AI — od czego zacząć, jeśli chcesz mieć własnego agenta korzystającego z serwerów MCP.
- Bezpieczeństwo agentów AI — szersze ujęcie ryzyk, których część 4 dotyka tylko od strony MCP.
- RAG w praktyce — właściwy wybór, gdy problemem jest przeszukanie tysięcy dokumentów, a nie dostęp do systemu.
- Frameworki agentów AI — warstwa, z którą MCP najczęściej się myli.
- Słownik: MCP i serwer MCP — zwięzłe definicje do szybkiego przypomnienia.
Najczęstsze pytania
Czym różni się MCP od skilla?
Czy MCP działa tylko z Claude?
Czy MCP jest bezpieczny?
Ile serwerów MCP można podłączyć naraz?
Czy potrzebuję umieć programować, żeby korzystać z MCP?
Kiedy NIE używać MCP?
Czym jest rewizja specyfikacji 2026-07-28 i czy muszę się nią przejmować?
Czym jest oficjalny rejestr MCP?
Źródła
- Specification (2026-07-28) — Model Context Protocol (dostęp: )
- Key Changes — MCP Specification 2026-07-28 — Model Context Protocol (dostęp: )
- Security Best Practices — MCP Specification — Model Context Protocol (dostęp: )
- Authorization — MCP Specification — Model Context Protocol (dostęp: )
- Introducing the Model Context Protocol — Anthropic (dostęp: )
- MCP joins the Agentic AI Foundation — Model Context Protocol (dostęp: )
- Code execution with MCP: Building more efficient agents — Anthropic Engineering (dostęp: )
- Connect Claude Code to tools via MCP — Anthropic (dostęp: )
- Python SDK — README i dokumentacja — Model Context Protocol (dostęp: )
- TypeScript SDK — README i dokumentacja — Model Context Protocol (dostęp: )
- MCP Security Notification: Tool Poisoning Attacks — Invariant Labs (dostęp: )
- Jumping the line: How MCP servers can attack you before you ever use them — Trail of Bits (dostęp: )
- The lethal trifecta for AI agents — Simon Willison (dostęp: )
- Exposing the Unseen: Mapping MCP Servers Across the Internet — Knostic (dostęp: )
- MCP Apps — Bringing UI Capabilities To MCP Clients — Model Context Protocol (dostęp: )
- Roadmap — Model Context Protocol (dostęp: )
- Skills over MCP Working Group (SEP-2640 — Final) — Model Context Protocol (dostęp: )
- Specification versioning — current protocol version — Model Context Protocol (dostęp: )
- mcp — historia wydań (PyPI) — PyPI (dostęp: )
- Upgrade to v2 — TypeScript SDK — Model Context Protocol (dostęp: )