Odpalasz CI na backendzie. Lintujesz frontend. Twoje kontenery Docker mają healthchecki. Każdy element stosu ma jakąś strategię testowania — z wyjątkiem połączeń MCP, od których twój agent zależy przy każdym wywołaniu.
19 kwietnia zespół MCP opublikował swoją roadmapę na 2026. Cztery priorytety: autoryzacja, rejestr, bogate prymitywy UX i zdolności agentowe. Testowanie, health checki, walidacja kontraktów — nie ma na liście. Nie wspomniane. Nie planowane. 😾
Więc jesteś zdany na siebie. Oto jak testować serwery MCP dziś, narzędziami, które faktycznie istnieją.
Z czym masz do czynienia
Ekosystem MCP ma mniej więcej 17 000 zarejestrowanych serwerów. Audyty społecznościowe pokazują, że mniej więcej połowa odpowiada stabilnie w dowolnym momencie. Twój agent łączy się z trzema serwerami? Statystycznie, jeden z nich właśnie nawala.
Testomat.io opublikował najobszerniejszy przegląd narzędzi do testowania MCP 8 kwietnia. Ich wniosek jest brutalnie prosty: nic nie mówi natywnie po MCP jeśli chodzi o testowanie. Wszystko to taśma klejąca nałożona na generyczne frameworki HTTP. Żaden test runner nie rozumie transportu MCP. Żadna biblioteka asercji nie wie, jak wygląda poprawna odpowiedź narzędzia. Budujesz cały stos testowy od zera dla każdego serwera, od którego zależysz.
Oto pełna inwentaryzacja tego, co istnieje — i jak to uruchomić.
MCP Inspector: manualny punkt startowy
MCP Inspector to oficjalne narzędzie do debugowania — pomyśl o Postmanie dla MCP. Łączysz się z serwerem, ręcznie wywołujesz narzędzia, przeglądasz odpowiedzi.
Co daje:
- Interaktywne odkrywanie i wywoływanie narzędzi
- Surowy wgląd w odpowiedzi JSON
- Diagnostykę połączeń dla transportów stdio i HTTP+SSE
Czego nie daje:
- Integracji z CI
- Wykrywania regresji
- Automatycznych zestawów testów
- Walidacji odpowiedzi względem jakiegokolwiek schematu
To śrubokręt. Przydatny do dłubania przy developmencie, bezwartościowy przy zapobieganiu regresjom na produkcji. Potrzebujesz test harnessa. 😹
Testy opakowujące (podejście na taśmę klejącą)
Większość zespołów testujących MCP dziś pisze testy opakowujące — zwykłe zestawy pytest lub Jest, które wywołują narzędzia bezpośrednio przez MCP client SDK i sprawdzają asercjami to, co wraca.
# pytest — testowanie narzędzia serwera MCP
import json
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def test_search_tool_returns_results():
server = StdioServerParameters(
command="npx",
args=["-y", "@example/mcp-search-server"]
)
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(
"search",
arguments={"query": "test query", "limit": 5}
)
assert result.content is not None
assert len(result.content) > 0
assert result.content[0].type == "text"
data = json.loads(result.content[0].text)
assert "results" in data
assert len(data["results"]) <= 5
To działa, dopóki upstream nie zmieni formatu odpowiedzi. Co dzieje się po cichu, bez wersjonowania, bez changelogów — specyfikacja MCP nie ma konwencji semver, nie ma odpowiednika lockfile'a, nie ma mechanizmu ogłaszania breaking changes. Twoja asercja sprawdza data["results"] — serwer zmienia nazwę na data["items"] we wtorek o 2 w nocy. W najlepszym razie: twój test robi się czerwony. W najgorszym: pole dalej istnieje, ale struktura wewnątrz się zmienia, test świeci na zielono, twój agent halucynuje na zdeformowanych danych, a ty płacisz za każdy zhalucynowany token.
Testowanie kontraktów bez kontraktów
Fundamentalny problem: serwery MCP nie publikują schematów odpowiedzi. Specyfikacja opisuje co narzędzie powinno robić w języku naturalnym. Nie oferuje żadnego maszynowo-czytelnego kontraktu do walidacji.
Obejście: wygeneruj własny.
# Krok 1: Nagrywaj prawdziwe odpowiedzi w czasie
from genson import SchemaBuilder
builder = SchemaBuilder()
for response in recorded_responses: # zbieraj ze staging/dev
builder.add_object(json.loads(response))
inferred_schema = builder.to_schema()
# Zapisz to w repo jako "kontrakt"
# Krok 2: Waliduj w CI
from jsonschema import validate, ValidationError
def test_tool_response_matches_contract():
response = call_mcp_tool("search", {"query": "test"})
try:
validate(instance=response, schema=inferred_schema)
except ValidationError as e:
pytest.fail(f"Contract violation: {e.message}")
Proces: nagrywaj prawdziwe odpowiedzi z serwera przez tydzień. Wygeneruj JSON Schema z tych odpowiedzi za pomocą generatora schematów. Zacommituj ten schemat do repo. Waliduj przyszłe odpowiedzi względem niego w CI.
To inżynieria wsteczna testowania kontraktów. Nieelegancka. Ale łapie ciche zmiany po stronie upstream, które w przeciwnym razie trafiłyby na produkcję niezauważone. Kiedy schemat pęka, twój pipeline pęka — głośno, w CI, a nie po cichu w outputcie twojego agenta. 😸
Monitoring zdrowia: zbuduj albo się módl
Twój orkiestrator pinguje kontenery Docker. Twój load balancer sprawdza /health. Serwery MCP nie oferują endpointu zdrowia — specyfikacja nie definiuje żadnego. Serwer albo odpowiada, albo nie, a dowiadujesz się, kiedy wywołanie narzędzia twojego agenta wisi.
Zbuduj własny health check:
import asyncio
from datetime import datetime
async def check_mcp_health(server_params, timeout=10):
try:
async with asyncio.timeout(timeout):
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
return {
"status": "healthy",
"tools_available": len(tools.tools),
"checked_at": datetime.utcnow().isoformat()
}
except (asyncio.TimeoutError, Exception) as e:
return {
"status": "unhealthy",
"error": str(e),
"checked_at": datetime.utcnow().isoformat()
}
Odpalaj to na cronie. Alertuj po kolejnych failach. Sprawdzaj nie tylko łączność, ale listę narzędzi — serwery dodają i usuwają toole bez uprzedzenia, a twój agent oczekujący search_v2 po tym, jak serwer po cichu go usunął, produkuje rodzaj awarii, który wygląda jak bug agenta, ale nim nie jest.
Wstrzykiwanie awarii: część, którą wszyscy pomijają
Twój agent wywołuje narzędzie. Narzędzie timeoutuje. Co się dzieje dalej?
Jeśli tego nie testowałeś, odpowiedź brzmi: model improwizuje. Może retryować w nieskończoność. Może zhalucynować oczekiwaną odpowiedź. Może przeprosić użytkownika i nic nie zrobić. Nie dowiesz się aż do produkcji, a produkcja kasuje za token za tę lekcję. 🙀
Opakuj swojego klienta MCP, żeby symulować awarie:
import random
class ChaosProxy:
"""Opakowuje prawdziwą sesję MCP do wstrzykiwania awarii w testach."""
def __init__(self, real_session, failure_rate=0.1, corruption_rate=0.05):
self.session = real_session
self.failure_rate = failure_rate
self.corruption_rate = corruption_rate
async def call_tool(self, name, arguments):
# Symulacja timeoutu
if random.random() < self.failure_rate:
raise TimeoutError(f"Simulated MCP timeout on {name}")
result = await self.session.call_tool(name, arguments)
# Symulacja uszkodzonej odpowiedzi
if random.random() < self.corruption_rate:
return self._corrupt_response(result)
return result
def _corrupt_response(self, result):
# Zwraca poprawną kopertę MCP ze śmieciową zawartością
# Testuje, czy twój agent radzi sobie z uszkodzonymi danymi
...
Puść swojego agenta przez tego proxy z 10% failure rate. Obserwuj, jak radzi sobie z timeoutami, śmieciowymi danymi i brakującymi narzędziami. Napraw to, co się psuje. Zwiększ procent. Powtarzaj, aż twój agent degraduje się gracefully zamiast pewnie halucynować.
Kompletny stos testowy
Oto jak wygląda przetestowany deployment MCP dziś — wszystko ręcznie sklejone, nic nie jest zestandaryzowane:
| Warstwa | Narzędzie | Co łapie |
|---|---|---|
| Ręczna eksploracja | MCP Inspector | "Czy to narzędzie istnieje i odpowiada?" |
| Testy jednostkowe | wrappery pytest/Jest | Kształt odpowiedzi, podstawowe zachowanie |
| Testy kontraktowe | Wygenerowany JSON Schema | Ciche zmiany formatu upstream |
| Monitoring zdrowia | Własny cron + alerting | Awarie serwerów, dryft listy narzędzi |
| Wstrzykiwanie awarii | Chaos proxy wrapper | Zachowanie agenta przy degradacji |
| Testy integracyjne | End-to-end przebiegi agenta | Regresje pełnego pipeline'u |
Ilość zestandaryzowanego toolingu, który specyfikacja MCP dostarcza na cokolwiek z tego: zero. Każdą warstwę, którą budujesz, sam też utrzymujesz, debugujesz i przebudowujesz, kiedy zmiany transportu rozbijają twoją infrastrukturę testową. 😾
Pułapki, które cię ugryzą
Zanieczyszczenie stanu. Narzędzia MCP mogą mieć efekty uboczne — zapisywać dane, kasować rekordy, obciążać konto. Specyfikacja nie definiuje trybu mock. Albo budujesz fałszywy serwer do testów, albo testujesz na produkcji (niebezpieczne), albo utrzymujesz środowisko staging na każdą zależność MCP (drogie). Większość zespołów testuje na produkcji i ma nadzieję. Nadzieja nie jest strategią testowania.
Niezgodność transportu. Twoje testy jadą po stdio. Produkcja po HTTP+SSE. Zachowują się inaczej pod obciążeniem, timeoutują inaczej, failują inaczej. Testuj oba transporty albo zaakceptuj, że twoje środowisko testowe nie odpowiada produkcji.
Wygaśnięcie auth. Tokeny OAuth wygasają. Twoje CI odpala się o 3 w nocy. Token wygasł o 2. Twój test failuje nie dlatego, że serwer padł, ale dlatego, że auth padł. Obsłuż odświeżanie tokenów w test setup albo będziesz gonił za fantomowymi failami godzinami.
Dryft listy narzędzi. Serwer dodaje narzędzie, usuwa narzędzie, zmienia nazwę parametru — zero powiadomień, zero version bump. Testuj odkrywanie narzędzi jako część health checków. Diffuj listę narzędzi względem known-good snapshotu. Alertuj na zmiany.
Teraz jesteś niebezpieczny
Umiesz testować serwery MCP. Nie dlatego, że protokół ci pomaga — roadmapa z 19 kwietnia potwierdza, że nie będzie tego priorytetyzował w najbliższym czasie — ale dlatego, że walidacja JSON Schema, chaos engineering i monitoring zdrowia to problemy dawno rozwiązane. Możesz je przykręcić do nietestowanej powierzchni MCP zwykłym Pythonem i cronem.
Setup jest brzydki. Utrzymanie jest manualne. Cały stos trzeba będzie przebudować, kiedy specyfikacja w końcu doda prymitywy testowe — jeśli kiedykolwiek to zrobi.
Ale twój agent ma teraz przetestowane zależności zamiast modlitw. To jest różnica między "działało na demo" a "działa na produkcji". Jedno z tych płaci twoją pensję. Drugie daje ci wiadomość na Slacku o 2 w nocy od kogoś, kto zaufał twojemu agentowi z czymś ważnym. 😼
→ Roadmapa MCP 2026 (19 kwietnia 2026) → Testomat.io — Narzędzia do testowania serwerów MCP




