Przejdź do głównej zawartości

Problemy z połączeniem serwera MCP

Serwer MCP, który nie łączy się w Claude Code, Codeksie lub Cursorze, prawie zawsze ma jedną z pięciu przyczyn: błędny wpis serwera, launcher niewidoczny w PATH klienta, brakujące lub wygasłe poświadczenia, przekroczony czas startu albo problem sieciowy lub protokołu na serwerze zdalnym. Sprawdź je w tej kolejności, a każdą poprawkę potwierdź wywołaniem tools/list.

Dodałeś serwer Postgres, zrestartowałeś agenta, a lista narzędzi jest pusta. claude mcp list pokazuje Failed to connect, Cursor świeci na czerwono, a kolega z identyczną konfiguracją dostaje Connection closed. Ta strona jest dla programisty, który patrzy na ten błąd, i dla tech leada, który odpowiada za wspólny plik .mcp.json zespołu. Opisuje kolejność diagnozy, pułapki wiersza poleceń, które zapisują zepsuty wpis bez żadnego błędu, oraz test dymny, który udowadnia, że każdy serwer odpowiada, zanim agent zacznie na nim polegać.

Sprawdzone 2026-09-26 na Claude Code 2.1.283, codex-cli 0.157.1 i CLI MCP Inspectora 2.8.0; każda pułapka Claude Code opisana niżej odtwarza się także na 2.1.286. Szczegóły dotyczące Cursora pochodzą z dokumentacji dostawców; tam, gdzie nie dało się ich przetestować, zaznaczamy to wprost.

  • Tabelę objawów, która łączy widoczny błąd z przyczyną i pierwszym poleceniem do uruchomienia.
  • Siedem pułapek CLI, które tworzą wpis serwera wyglądający poprawnie i nigdy się nie łączący.
  • Poprawki dla spawn ENOENT, timeoutów przy starcie, wygasłych tokenów OAuth i ignorowanych nagłówków.
  • Test dymny oparty na tools/list, który uruchomisz lokalnie lub w CI, więc „działa” staje się sprawdzeniem, a nie wrażeniem.
  • Trzy prompty do wklejenia, dzięki którym agent sam znajdzie prawdziwy błąd.

Jeśli nie masz jeszcze dodanego serwera, zacznij od strony konfiguracji dla swojego narzędzia: MCP w Claude Code, MCP w Codeksie albo MCP w Cursorze.

Najpierw dopasuj objaw. Każdy wiersz podaje najczęstszą przyczynę i polecenie, które ją potwierdza.

ObjawNajczęstsza przyczynaPierwsze sprawdzenie
spawn npx ENOENT, Connection closed zaraz po starcieKlient nie widzi npx, node ani uvx w swoim PATHUruchom dokładne command z wpisu w terminalu; which npx
Zdalny URL zapisany jako serwer stdio, Failed to connectclaude mcp add bez --transport httpclaude mcp get <nazwa> pokazuje Type: stdio i URL jako polecenie
⏸ Pending approval w claude mcp listSerwer projektowy z .mcp.json, którego nikt jeszcze nie zatwierdziłUruchom claude w repozytorium i zatwierdź go
Needs authentication, 401 albo „połączony, ale bez narzędzi” na serwerze zdalnymOAuth nie został dokończony albo token wygasł/mcp w Claude Code, codex mcp login <nazwa>
401 w Codeksie, choć config.toml zawiera tokenCodex zignorował nieznany klucz headerscodex mcp get <nazwa> --json pokazuje "http_headers": null
Działa przy drugiej próbie, pada przy pierwszym wywołaniu dniaPierwsze pobieranie pakietu przekracza limit czasu startuRozgrzej cache w terminalu; podnieś limit
Połączony, zero narzędziSerwer wystartował, ale nie zarejestrował żadnych narzędzi, zwykle przez brak wymaganej zmiennej albo zakresu tokena (wiele serwerów rejestruje narzędzia dopiero po konfiguracji)Przeczytaj jego stderr, uruchamiając polecenie ręcznie
U ciebie działa, u kolegi nieLokalny PATH, globalna instalacja albo zmienna, którą masz tylko tyPorównaj wynik claude mcp get lub codex mcp get --json na obu maszynach

Każdy krok wyklucza całą klasę przyczyn, więc wykonuj je po kolei i zatrzymaj się na pierwszym, który zawiedzie.

  1. Odczytaj to, co klient faktycznie zapisał. Wypisz wpis, którego klient używa, a nie ten, który wydaje ci się, że napisałeś: claude mcp get <nazwa>, codex mcp get <nazwa> --json albo blok mcpServers w .cursor/mcp.json. Większość zepsutych serwerów jest zepsuta właśnie tutaj.
  2. Uruchom polecenie startowe ręcznie. Skopiuj command i args do terminala. Jeśli serwer wypisze błąd albo się zakończy, klient zawiedzie tak samo. Zdrowy serwer stdio nic nie wypisuje i czeka na wejście; zatrzymaj go przez Ctrl+C.
  3. Sprawdź PATH klienta. Aplikacja desktopowa ani IDE nie wczytuje twojego .zshrc, więc launcher zainstalowany przez nvm, asdf, mise czy Homebrew może być dla niej niewidoczny. Porównaj which npx w terminalu z tym, co widzi klient.
  4. Sprawdź poświadczenia. Upewnij się, że każda zmienna, której potrzebuje serwer, jest ustawiona w env wpisu, a OAuth serwera zdalnego jest dokończony i nie wygasł.
  5. Sprawdź sieć i protokół. Dla serwerów zdalnych przetestuj URL, proxy i wersję protokołu, którą negocjuje klient.

Jak sprawdzić status serwera MCP w Claude Code, Codeksie i Cursorze

Dział zatytułowany „Jak sprawdzić status serwera MCP w Claude Code, Codeksie i Cursorze”

Polecenia statusu różnią się między narzędziami. Używaj ich przed każdą poprawką i po niej.

Okno terminala
claude mcp list # każdy serwer z kontrolą stanu: Connected, Failed to connect, Pending approval
claude mcp get postgres # zakres, typ, polecenie lub URL, env i status jednego serwera
claude --debug "mcp" # sesja z wyjściem debugowania MCP
claude --debug-file /tmp/mcp.log # to samo, zapisane do pliku, który dołączysz do zgłoszenia

W sesji /mcp pokazuje stan każdego serwera i pozwala się uwierzytelnić lub połączyć ponownie. Serwery projektowe z .mcp.json pozostają w stanie ⏸ Pending approval, dopóki ktoś nie zatwierdzi ich w sesji interaktywnej. Aby Claude Code zapytał ponownie po odrzuceniu, uruchom claude mcp reset-project-choices.

Pułapki CLI, które zapisują zepsuty wpis serwera MCP

Dział zatytułowany „Pułapki CLI, które zapisują zepsuty wpis serwera MCP”

Te polecenia kończą się sukcesem albo błędem wskazującym w złe miejsce. Każde uruchomiliśmy na podanych wersjach.

PułapkaCo się dziejePoprawna forma
claude mcp add sentry https://mcp.sentry.dev/mcp bez --transportClaude Code 2.1.283 wypisuje ostrzeżenie, ale i tak zapisuje serwer stdio, którego poleceniem jest URL. Pada przy łączeniuclaude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp add --url …error: unknown option '--url' (2.1.283). --url to flaga CodeksaPodaj URL jako argument pozycyjny po nazwie
-e KLUCZ=wartość tuż przed nazwą albo między nazwą a poleceniem bez ---e przyjmuje wiele wartości i połyka kolejny argument, przed nazwą zjada nazwę i kończy się błędem Invalid environment variable format: <nazwa>; między nazwą a poleceniem zjada polecenie i kończy się błędem missing required argument 'commandOrUrl'. Po -- -e po cichu staje się argumentem serwera (2.1.283)claude mcp add my-server -e API_KEY=… -- npx my-mcp-server: nazwa, potem -e, potem --
headers = { … } pod [mcp_servers.x] w CodeksieParsuje się bez błędu i zostaje odrzucone (0.157.1). codex mcp get x --json pokazuje "http_headers": nullhttp_headers, env_http_headers albo bearer_token_env_var
codex mcp add x --url … --env K=V--env działa tylko dla stdio (0.157.1) i polecenie kończy się błędem--bearer-token-env-var GITHUB_PAT_TOKEN albo http_headers w TOML
.claude/mcp.jsonClaude Code nigdy go nie czytaZakres projektu to .mcp.json w katalogu głównym repozytorium
codex mcp-serverNie istnieje jako podpolecenie w codex-cli 0.157.1; Codex nie działa już jako serwer MCPDo sterowania programowego użyj codex exec albo Codex SDK; Claude Code nadal oferuje claude mcp serve

Ósmą pułapką są nazwy pakietów. npx -y postgres-mcp instaluje niezwiązany pakiet z npm: Postgres MCP Pro to pakiet PyPI postgres-mcp, więc uruchamia się go przez uvx. Zanim obwinisz połączenie, sprawdź nazwę przez npm view <pakiet> version albo na PyPI. Przewodnik po bezpieczeństwie MCP wyjaśnia, dlaczego podobnie nazwany pakiet to ryzyko w łańcuchu dostaw, a nie tylko zepsuta konfiguracja.

Jak naprawić spawn ENOENT i Connection closed na serwerach stdio

Dział zatytułowany „Jak naprawić spawn ENOENT i Connection closed na serwerach stdio”

Te błędy oznaczają, że proces w ogóle nie wystartował. Winny jest prawie zawsze launcher, a nie serwer.

Okno terminala
which npx node uvx # np. /Users/you/.nvm/versions/node/v22.14.0/bin/npx

Jeśli ścieżka leży w katalogu menedżera wersji, klient desktopowy jej nie widzi. Wpisz do konfiguracji ścieżkę bezwzględną zamiast samej nazwy:

{
"mcpServers": {
"postgres": {
"command": "/Users/you/.local/bin/uvx",
"args": ["postgres-mcp", "--access-mode=restricted"],
"env": { "DATABASE_URI": "${DATABASE_URI}" }
}
}
}

Rozwijanie ${DATABASE_URI} to składnia .mcp.json w Claude Code (obsługuje też ${VAR:-default}). Cursor używa własnej składni interpolacji; aktualną formę sprawdź w dokumentacji MCP Cursora. Serwery w Pythonie wymagają zainstalowanego uv; uvx jest jego częścią.

Częściowo pobrany (przerwany) pakiet w cache npx daje ten sam błąd przy każdej kolejnej próbie. Wyczyść tylko cache npx, a potem raz uruchom polecenie ręcznie, żeby następny start był „ciepły”:

Okno terminala
rm -rf "$(npm config get cache)/_npx"

Serwer, który działa za drugim razem, za pierwszym zwykle się pobiera. Klient poddaje się, zanim npx lub uvx skończy. Uruchom polecenie startowe raz w terminalu, żeby rozgrzać cache, przypnij wersję w args, żeby cache pozostał ważny, a limit startu podnoś tylko wtedy, gdy serwer naprawdę jest wolny:

Okno terminala
MCP_TIMEOUT=30000 claude # limit czasu startu serwera w milisekundach

MCP_TOOL_TIMEOUT ustawia limit dla pojedynczego wywołania narzędzia.

Prośba do agenta, żeby „poczekał dłużej”, niczego nie zmienia: limit egzekwuje klient. Strojenie timeoutów dla serwerów, które pozostają wolne, opisuje strona dobre praktyki MCP.

Jak naprawić błędy uwierzytelniania na zdalnych serwerach MCP

Dział zatytułowany „Jak naprawić błędy uwierzytelniania na zdalnych serwerach MCP”

Zdalny serwer, który zwraca 401 albo łączy się bez narzędzi, ma problem z poświadczeniami. Większość serwerów hostowanych przez dostawców (GitHub, Sentry, Linear, Figma, Atlassian) używa OAuth, więc poprawka polega na dokończeniu lub powtórzeniu logowania w przeglądarce, a nie na wklejaniu tokena.

Okno terminala
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp login sentry # albo /mcp w sesji
claude mcp logout sentry # usuń nieaktualny token, potem zaloguj się ponownie

Dla serwera, który przyjmuje statyczny token, podaj nagłówek w apostrofach: claude mcp add --transport http github https://api.githubcopilot.com/mcp/ -H 'Authorization: Bearer ${GITHUB_PAT}'. Apostrofy chronią ${GITHUB_PAT} przed rozwinięciem, więc konfiguracja przechowuje odwołanie, Claude Code rozwija je przy łączeniu, a token nie trafia ani do pliku konfiguracji, ani (z -s project) do gita. Cudzysłów zapisałby w konfiguracji sam token.

Dwie pułapki specyficzne dla serwerów: nagłówek tokena Sentry to Authorization: Sentry-Bearer <token>, a nie Bearer, a endpoint Atlassiana to https://mcp.atlassian.com/v2/mcp (stary /v1/sse przestał działać po 30 czerwca 2026). 403 przy każdym wywołaniu z poprawnym tokenem zwykle oznacza zbyt wąski zakres tokena; przewodnik po bezpieczeństwie MCP wymienia zakresy zgodne z zasadą najmniejszych uprawnień.

Jak podłączyć klienta obsługującego tylko stdio do zdalnego serwera przez mcp-remote

Dział zatytułowany „Jak podłączyć klienta obsługującego tylko stdio do zdalnego serwera przez mcp-remote”

Claude Code, Codex i Cursor rozmawiają z serwerami zdalnymi po HTTP, więc nie potrzebują mostka. Niektóre starsze lub wbudowane klienty MCP potrafią tylko uruchamiać lokalne procesy stdio. Dla nich mcp-remote działa jako lokalny serwer stdio i przekazuje ruch do zdalnego URL-a, łącznie z logowaniem OAuth:

{
"mcpServers": {
"atlassian": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v2/mcp"]
}
}
}

Składnia to mcp-remote <https://server-url> [callback-port] [--debug]; dodaj --debug, gdy podejrzewasz sam mostek. Nie owijaj serwera zdalnego w mcp-remote w Claude Code ani w Codeksie, żeby go „naprawić”: ukryjesz prawdziwy błąd HTTP za drugim procesem.

Stan na 2026-09-26: mcp-remote ma wersję 0.14.3 w npm i ★1.6k na GitHubie, a README Atlassiana i Tavily nadal opisują go dla klientów obsługujących tylko stdio (rejestr npm, GitHub).

Problemy z siecią, proxy i protokołem na zdalnych serwerach MCP

Dział zatytułowany „Problemy z siecią, proxy i protokołem na zdalnych serwerach MCP”

Serwery zdalne dodają trzy punkty awarii, których serwery stdio nie mają.

  • Proxy. Serwer stdio dziedziczy środowisko ze swojego wpisu, a nie z twojej powłoki. Wpisz HTTPS_PROXY i NO_PROXY do bloku env wpisu. Za proxy, które przechwytuje TLS, serwery oparte na Node potrzebują też NODE_EXTRA_CA_CERTS wskazującego firmowy pakiet certyfikatów CA.
  • Lokalne serwery HTTP. Dla serwera uruchomionego na twojej maszynie najpierw potwierdź, że coś nasłuchuje, zanim obwinisz klienta: curl -i http://127.0.0.1:3845/mcp zwraca status HTTP, gdy proces działa, i Connection refused, gdy nie działa. lsof -i :3845 pokazuje, który proces trzyma port.
  • Wersja protokołu. MCP 2026-07-28 usunął handshake initialize i Mcp-Session-Id. Claude Code domyślnie negocjuje 2026-07-28 z bezpośrednimi serwerami HTTP (we wszystkich instalacjach od v2.1.274); codex-cli 0.157.1 tego nie robi (mcp_2026_07_28 jest w fazie rozwoju i wyłączone). Serwer, który działa w Codeksie, a pada tylko w Claude Code, może odrzucać nowszy protokół: sprawdź MCP_PROTOCOL_NEGOTIATION=legacy claude i, jeśli to pomoże, zgłoś problem opiekunowi serwera. Zmiany po stronie serwera opisuje przewodnik migracji do MCP 2026-07-28.

Jak udowodnić, że serwer MCP działa, zanim agent zacznie na nim polegać

Dział zatytułowany „Jak udowodnić, że serwer MCP działa, zanim agent zacznie na nim polegać”

„Kropka jest zielona” to nie test. Serwer może się połączyć i nie udostępnić żadnego narzędzia albo udostępnić niewłaściwe. Sprawdź każdy serwer deterministycznym wywołaniem tools/list z CLI MCP Inspectora, które czyta ten sam JSON mcpServers, co klienty:

Okno terminala
# Inspector nie rozwija ${VAR}: najpierw zapisz rozwiniętą kopię poza repozytorium
f="$(mktemp "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/mcp.XXXXXX")" # tylko dla właściciela, nieprzewidywalna nazwa
node -e 'const fs=require("fs");const sub=v=>typeof v==="string"?v.replace(/\$\{(\w+)(?::-([^}]*))?\}/g,(m,k,d)=>process.env[k]??d??m):Array.isArray(v)?v.map(sub):v&&typeof v==="object"?Object.fromEntries(Object.entries(v).map(([k,x])=>[k,sub(x)])):v;fs.writeFileSync(process.argv[1],JSON.stringify(sub(JSON.parse(fs.readFileSync(".mcp.json","utf8")))))' "$f"
npx -y @modelcontextprotocol/inspector --cli --config "$f" --server postgres --method tools/list
rm "$f" # usuń rozwiniętą kopię po zakończeniu

Inspector przekazuje symbole zastępcze ${VAR} z --config dosłownie (sprawdzone na 2.8.0): serwer uruchomiony z commitowanego .mcp.json dostaje jako poświadczenie napis ${DATABASE_URI} i pada albo łączy się z niewłaściwym celem. Dlatego skrypt podstawia wartości w sparsowanym JSON-ie, więc cudzysłów ani ukośnik wsteczny w sekrecie nie zepsują pliku, a wynik zapisuje do pliku z mktemp z uprawnieniami tylko dla właściciela, poza repozytorium. Usuń go po zakończeniu (rm "$f") i nigdy nie commituj. Stan na 2026-09-26: Inspector ma wersję 2.8.0 w npm i ★11.0k na GitHubie (rejestr npm, GitHub). Wywołanie tools/list wypisuje narzędzia serwera jako JSON albo błąd, np. Connection timed out after 30000 ms. Do szybkiego sprawdzenia możesz zamiast --config podać samo polecenie (… --cli context7-mcp --method tools/list), ale wybieraj --config: dodatkowe flagi w argumentach serwera mogą zostać odczytane jako flagi Inspectora.

W zespole zamień to w bramkę, za którą odpowiada tech lead:

  1. Commituj .mcp.json wyłącznie z symbolami zastępczymi ${VAR}, nigdy z tokenem.
  2. Dodaj skrypt testu dymnego, który zapisuje rozwiniętą kopię poza gitem, wykonuje wywołanie tools/list dla każdego serwera z niej, usuwa kopię i kończy się błędem, gdy serwer zawiedzie albo zwróci zero narzędzi.
  3. Uruchamiaj go w CI przy pushu na domyślną gałąź, który zmienia .mcp.json, tylko z sekretami potrzebnymi temu zadaniu, oraz lokalnie po onboardingu. Nigdy nie dawaj tych sekretów zadaniu uruchamianemu przez pull request: pull request może przepisać .mcp.json i sam skrypt, a każdy wpis serwera to polecenie, które zadanie wykona.
  4. Tak samo sprawdzaj koszt kontekstu: porównaj /context w Claude Code przed dodaniem serwera i po nim, bo serwer, który się łączy, nadal może wypychać zadanie z kontekstu. Zobacz ograniczanie kosztu tokenów MCP.

W terminalu działa, w kliencie nie. Klient ma inny PATH albo nieaktualny proces. Wpisz bezwzględną ścieżkę launchera, wyczyść cache npx i całkowicie zamknij klienta.

Claude Code pokazuje serwer, ale nigdy się z nim nie łączy. To serwer projektowy czekający na zatwierdzenie. Uruchom claude w repozytorium i zatwierdź go; jeśli ktoś wcześniej go odrzucił, uruchom claude mcp reset-project-choices.

Serwer się łączy i ładuje zero narzędzi. Wystartował, ale nie zarejestrował żadnych narzędzi, zwykle przez brak wymaganej zmiennej albo zakresu tokena: wiele serwerów rejestruje narzędzia dopiero po konfiguracji. Uruchom polecenie ręcznie z tym samym env i przeczytaj stderr.

Zdalny serwer wczoraj działał, a dziś zwraca 401. Token OAuth wygasł albo został unieważniony. Uruchom claude mcp logout <nazwa>, a potem claude mcp login <nazwa>, albo codex mcp logout <nazwa> i codex mcp login <nazwa>, albo połącz się ponownie z ustawień MCP w Cursorze.

U ciebie działa, u kolegi nie. Masz globalną instalację, zmienną albo wpis w PATH, których on nie ma. Przypinaj wersje w args, wypisz każdą wymaganą zmienną w README repozytorium i włącz test dymny do onboardingu.

Gromadzą się stare procesy serwerów. Szukaj ich po nazwie konkretnego serwera i zatrzymuj tylko je, np. pgrep -fl postgres-mcp, a potem kill <pid>. Unikaj pkill -f mcp: zabija także serwery innych klientów i każdy proces z „mcp” w argumentach.