Przejdź do głównej zawartości

Wewnętrzne serwery MCP — zbuduj tylko brakujący interfejs

Wewnętrzny serwer MCP to usługa Model Context Protocol, którą organizacja buduje, by agenci kodujący sięgali do wewnętrznego systemu, którego żadna utrzymywana integracja nie udostępnia bezpiecznie. Maksimum w pytaniu Q7 CTO Scorecard daje tylko, gdy zamyka zmierzoną, powtarzalną lukę dostępu wąskimi narzędziami (najpierw tylko do odczytu), ma właściciela, autoryzację least privilege, testy kontraktowe, monitoring i kryteria wycofania.

Ta strona jest dla CTO, który decyduje, co buduje zespół platformowy, i dla tech leada, który będzie właścicielem wyniku. Sytuacja: inżynierowie codziennie wklejają do sesji agenta ten sam arkusz własności serwisów, stan feature flag i linki do runbooków, a ktoś proponuje „serwer MCP do wszystkiego, co wewnętrzne”. Pół roku później są cztery serwery, jeden ma ogólne narzędzie SQL, dwa nie mają właściciela i nikt nie potrafi powiedzieć, czy którykolwiek przyspieszył jakiekolwiek zadanie.

  • Czteropoziomową tabelę punktacji Q7, dzięki której umiejscowisz organizację i nazwiesz dowody podnoszące wynik.
  • Tabelę decyzyjną, która dobiera najmniejszy interfejs do luki: istniejący serwer, CLI ze skillem, generowany plik albo własny serwer.
  • Szablony opisu luki i kontraktu narzędzia do przyjęcia bez zmian.
  • Zweryfikowane komendy podłączające jeden wewnętrzny serwer w Claude Code, Codeksie i Cursorze.
  • Automatyczne bramki, które dowodzą, że serwer działa w każdym kliencie i każdej erze protokołu, bez czytania każdego wywołania narzędzia.
  • Metryki i regułę wycofania, które utrzymują liczbę serwerów w ryzach, oraz typowe awarie z krokami naprawy.

Jak CTO Scorecard Q7 punktuje wewnętrzne serwery MCP?

Dział zatytułowany „Jak CTO Scorecard Q7 punktuje wewnętrzne serwery MCP?”

Scorecard pyta: „Czy wewnętrzne serwisy MCP bezpiecznie rozwiązują zmierzone, powtarzalne luki dostępu?”. Liczba serwerów nigdy nie daje punktów. Dają je dowody.

PunktyOdpowiedźDowód, który ją uzasadnia
0NieBrak albo serwery, których nikt nie umie wymienić.
1Istnieje prototyp (proof of concept), ale luka, właściciel lub kontrole nie są ustaloneRepozytorium i demo. Brak baseline’u, brak właściciela w katalogu serwisów, współdzielony token.
2Uzasadniony wąski serwis działa z podstawową odpowiedzialnością właściciela i monitoringiemOpis luki z baseline’em, wskazany z nazwy właściciel, dashboard z wywołaniami i błędami.
3Uzasadnione wewnętrzne serwisy MCP z właścicielami, minimalnymi uprawnieniami, dokumentacją, zestawami danych testowych (fixtures), monitoringiem i kryteriami wycofaniaWszystko z poziomu 2 oraz kontrakt dla każdego narzędzia, autoryzacja per użytkownik, przebieg testów kontraktowych w CI, zestaw danych testowych, kwartalny przegląd i spisana reguła wycofania.

Poziom 3 da się osiągnąć z jednym serwerem. Organizacja z jednym dobrze prowadzonym serwerem dostaje więcej punktów niż ta z sześcioma serwerami bez właściciela.

Kiedy wewnętrzny serwer MCP jest właściwym interfejsem?

Dział zatytułowany „Kiedy wewnętrzny serwer MCP jest właściwym interfejsem?”

Większość luk dostępu ma tańsze rozwiązanie niż nowa usługa. Serwer MCP dokłada uwierzytelniany endpoint, schemat ładowany przez każdego klienta do kontekstu, aktualizacje protokołu i dyżury. Przejdź tabelę od góry i zatrzymaj się na pierwszym pasującym wierszu.

Luka wygląda tak…Najmniejszy interfejsDlaczego wygrywa
System publiczny lub dostawcy zewnętrznego, który ma już utrzymywany serwer MCP (GitHub, Sentry, baza danych)Istniejący serwer w trybie tylko do odczytuUtrzymuje go ktoś inny. Zobacz podstawowe serwery MCP.
Wewnętrzny system z dobrym CLI lub REST API, używany przez jeden zespółCLI plus współdzielony skill opisujący, jak je wywołaćŻadnej nowej usługi. Agent i tak uruchamia komendy.
Wolno zmieniające się dane referencyjne (własność, decyzje architektoniczne, katalog API)Plik generowany w repozytorium, odświeżany przez CIZero powierzchni w runtime, zmiany widać w diffach.
Dane na żywo, potrzebne kilku zespołom, w więcej niż jednym kliencie agenta, z uprawnieniami per użytkownikWewnętrzny serwer MCPJeden kontrolowany interfejs, który rozumieją Claude Code, Codex i Cursor.

Buduj serwer, gdy spełnione są wszystkie cztery warunki z ostatniego wiersza: dane są na żywo, potrzeba obejmuje kilka zespołów, korzysta z niej więcej niż jeden klient, a dostęp zależy od tego, kto pyta. Jeśli spełniony jest tylko jeden, zwykle wystarczy skill albo generowany plik.

Kolejność ma znaczenie. Każdy krok daje dowód, na którym opiera się następny, a pominięcie dwóch pierwszych to najczęstsza droga do wyniku 1.

  1. Napisz opis luki i zmierz baseline. Przez dwa tygodnie zapisuj zadanie, kto je wykonuje, jak często, ile trwa i jak dziś zawodzi. Użyj szablonu opisu luki poniżej. Bez baseline’u nie udowodnisz, że serwer pomógł, a Q7 pyta o luki „zmierzone”.

  2. Najpierw sprawdź prostsze opcje. Przejdź tabelę decyzyjną z opisem luki w ręku. Zapisz, którą opcję odrzuciłeś i dlaczego, bo zapyta o to kwartalny przegląd.

  3. Napisz jeden kontrakt na każde narzędzie. Projektuj operacje na poziomie zadania, a nie surowy dostęp. find_service_owner(endpoint) zwracające zespół, repozytorium i datę ostatniej weryfikacji to ograniczona operacja biznesowa. query_internal_database(sql) daje każdemu podłączonemu agentowi otwartą powierzchnię uprawnień. Zacznij od narzędzi tylko do odczytu i ogranicz rozmiar każdego wyniku.

  4. Zaimplementuj najmniejszy serwer, który spełnia kontrakty. Opakuj istniejące wewnętrzne API, a nie bazę danych za nim, żeby nadal działała autoryzacja API. Budowa własnego serwera MCP opisuje kod SDK, transporty i pakowanie. Udostępnij serwer przez Streamable HTTP, żeby mieć jedno wdrożenie, a nie proces na każdym laptopie.

  5. Dodaj kontrole produkcyjne. OAuth per użytkownik zamiast współdzielonego tokenu serwisowego, autoryzacja per narzędzie, logi audytu z nazwą użytkownika i narzędzia, limity zapytań, timeouty i żadnego narzędzia zapisującego, dopóki narzędzia do odczytu nie udowodnią swojej wartości. Model bezpieczeństwa MCP (Q8) definiuje allowlistę, reguły akceptacji zapisów i adwersarialne dane testowe, które obowiązują ten serwer jak każdy inny.

  6. Podłącz serwer w każdym wspieranym kliencie i dodaj go do allowlisty. Użyj komend z następnej sekcji, a potem dopisz dokładny URL serwera do zarządzanej allowlisty. Zarządzana polityka opisuje, jak dystrybuować tę konfigurację.

  7. Awansuj na podstawie dowodów. Serwer wychodzi z pilotażu dopiero wtedy, gdy bramki kontraktowe przechodzą w CI, a metryki są lepsze od baseline’u z kroku 1. W przeciwnym razie zawęź go albo wycofaj.

Trzymaj oba pliki w repozytorium serwera, obok kodu. Opis luki to „zmierzone” z pytania Q7; kontrakt to coś, co recenzenci zatwierdzają zamiast czytać implementację.

mcp/catalog/gap-brief.yaml
gap: Agents cannot find the owning team and runbook for an internal endpoint
users: [payments, checkout, platform] # teams that hit the gap
frequency_per_week: 40 # counted from 2 weeks of logged sessions
current_path: Search the ownership sheet, then ask in #platform-help
current_lead_time_minutes_p50: 12 # measured, not estimated
failure_modes: [stale sheet, wrong team paged, runbook link missing]
alternatives_rejected:
existing_server: none exposes our service catalog
cli_plus_skill: catalog API needs per-user auth the CLI lacks
generated_file: ownership changes daily; a file is stale within hours
success_metric: p50 lead time under 2 minutes, wrong-owner rate under 2%
owner: platform-team (on-call rota "catalog")
review_date: 2026-12-15
retire_if: fewer than 10 distinct users in a quarter, or success metric missed twice
mcp/catalog/tools/find_service_owner.yaml
name: find_service_owner
purpose: Return the owning team, repository, and runbook for one internal endpoint
non_purpose: Listing all services, editing ownership, paging anyone
input: { endpoint: "string, path such as /v1/invoices, max 200 chars" }
output: { team: string, repository: string, runbook_url: string, last_verified: "ISO 8601" }
data_classification: internal
authorization: caller's own OAuth identity; catalog API enforces team visibility
side_effects: none # read-only; annotated readOnlyHint
limits: { timeout_ms: 5000, max_results: 1, rate_per_user_per_minute: 30 }
errors: [NOT_FOUND, FORBIDDEN, UPSTREAM_TIMEOUT] # agent reports these, never guesses
version: 1.2.0
owner: platform-team
deprecation: announce two releases ahead; old version served for 30 days

Liczby w opisie luki to miejsca na twoje własne pomiary. Linia retire_if to kryterium wycofania, o które pyta Q7. Zapisujesz je przed startem, żeby później nikt nie musiał o nie walczyć.

Jak podłączyć wewnętrzny serwer MCP w Claude Code, Codeksie i Cursorze?

Dział zatytułowany „Jak podłączyć wewnętrzny serwer MCP w Claude Code, Codeksie i Cursorze?”

Serwer jest ten sam, rejestracja różni się między klientami. Komendy sprawdzone w Claude Code 2.1.283 i Codeksie 0.157.1 dnia 2026-09-26. Każdy użytkownik uwierzytelnia się jako on sam, więc token nie trafia do żadnego pliku.

Uruchom w terminalu w katalogu głównym repozytorium. Zakres projektu zapisuje .mcp.json, który commitujesz, żeby każdy inżynier dostał ten sam wpis:

Okno terminala
claude mcp add --transport http --scope project catalog https://catalog.mcp.internal.example.com/mcp
claude mcp login catalog

Zapisany wpis to {"mcpServers": {"catalog": {"type": "http", "url": "https://catalog.mcp.internal.example.com/mcp"}}}. Narzędzia pojawiają się jako mcp__catalog__find_service_owner i tej nazwy używasz w regułach uprawnień oraz w --allowedTools. Każdy inżynier raz zatwierdza serwer projektu przy pierwszym użyciu; do tego czasu claude mcp list pokazuje go jako oczekujący na zatwierdzenie (Claude Code 2.1.283).

Jak udowodnić, że wewnętrzny serwer działa, bez czytania każdego wywołania?

Dział zatytułowany „Jak udowodnić, że wewnętrzny serwer działa, bez czytania każdego wywołania?”

Nikt nie przegląda pojedynczych wywołań narzędzi. Dowód niosą cztery automatyczne bramki i jedno kwartalne zatwierdzenie.

1. Bramki kontraktowe w CI, przy każdej zmianie serwera. MCP Inspector CLI (@modelcontextprotocol/inspector 2.8.0 na 2026-09-26) listuje narzędzia w każdej erze protokołu i sprawdza przenośność schematów. Uruchom go na wdrożeniu stagingowym:

Okno terminala
URL=https://catalog.staging.mcp.internal.example.com/mcp
npx @modelcontextprotocol/inspector@2.8.0 --cli "$URL" --protocol-era legacy --method tools/list --strict
npx @modelcontextprotocol/inspector@2.8.0 --cli "$URL" --protocol-era modern --method tools/list --strict
npx @modelcontextprotocol/inspector@2.8.0 --cli "$URL" --method tools/call \
--tool-name find_service_owner --tool-arg endpoint=/v1/invoices

Serwer, który nie oferuje 2026-07-28, oblewa wywołanie modern z niezerowym kodem wyjścia, a --strict kończy się kodem 6 przy problemie z przenośnością schematu o wadze error. Oba zatrzymują pipeline. Token dla stagingu podaj przez opcje OAuth Inspectora (--stored-auth-only w przebiegach nieinteraktywnych), nigdy jako dosłowny nagłówek.

2. Zestaw danych testowych. Zamień listę błędów z każdego kontraktu na testy: nieznany endpoint zwraca NOT_FOUND, użytkownik spoza zespołu dostaje FORBIDDEN, wolny upstream zwraca UPSTREAM_TIMEOUT w ramach limitu, a zbyt duże wejście jest odrzucane. Przypadki adwersarialne (wstrzyknięte instrukcje w zwracanych danych, powtórzone zapisy, korelacja logów audytu) pochodzą z zestawu danych testowych Q8.

3. Eval na złotych zadaniach. Trzymaj 10–20 prawdziwych pytań z opisu luki ze znanymi odpowiedziami i uruchamiaj je w trybie nieinteraktywnym (headless), z załadowanym tylko wewnętrznym serwerem. eval/catalog.mcp.json zawiera ten sam wpis catalog co .mcp.json, a --strict-mcp-config pomija wszystkie inne skonfigurowane serwery:

Okno terminala
claude -p "Who owns /v1/invoices and where is its runbook? Answer as JSON with team and runbook_url." \
--strict-mcp-config --mcp-config eval/catalog.mcp.json \
--allowedTools "mcp__catalog__find_service_owner" --output-format json

Porównaj każdą odpowiedź z oczekiwaną w skrypcie. W Codeksie odizoluj przebieg w ten sam sposób: --ignore-user-config pomija $CODEX_HOME/config.toml (i wszystkie skonfigurowane tam serwery), a nadpisania -c definiują catalog jako jedyny serwer MCP w tym przebiegu. Uruchamiaj go z katalogu bez projektowego .codex/config.toml, bo inaczej serwery z tego pliku dołączą do przebiegu (Codex 0.157.1):

Okno terminala
codex exec --sandbox read-only --ignore-user-config \
-c 'mcp_servers.catalog.url="https://catalog.mcp.internal.example.com/mcp"' \
-c 'mcp_servers.catalog.enabled_tools=["find_service_owner"]' \
"Who owns /v1/invoices and where is its runbook? Answer as JSON with team and runbook_url."

Ta strona nie opisuje dla Cursora ścieżki evalu w trybie nieinteraktywnym, więc zastępują go evale w Claude Code i Codeksie: sprawdzają ten sam serwer i te same kontrakty narzędzi. Spadek odsetka poprawnych odpowiedzi po wydaniu serwera blokuje to wydanie.

4. Sygnały z produkcji. Dashboard właściciela pokazuje wywołania na tydzień, liczbę różnych użytkowników, odsetek błędów, odmowy, latencję p95 i kompletność logów audytu, a alert włącza się, gdy którakolwiek wartość wyjdzie poza zakres.

Kwartalne zatwierdzenie. Właściciel porównuje metryki z success_metric z opisu luki, stosuje retire_if i zapisuje decyzję: zostawić, zawęzić albo wycofać. CTO lub lider platformy kontrasygnuje. Ten zapis jest dowodem na poziom 3 w Q7.

Działają tak samo w Claude Code, Codeksie i Cursorze. Uruchamiaj je z otwartym repozytorium serwera.

Co psuje się w wewnętrznych serwerach MCP i jak to naprawić?

Dział zatytułowany „Co psuje się w wewnętrznych serwerach MCP i jak to naprawić?”

Platforma bez potrzeby. Serwery powstały, żeby odhaczyć checklistę dojrzałości, i nikt ich nie używa, a nadal wymagają auth, aktualizacji protokołu i dyżurów. Naprawa: napisz wstecznie opis luki dla każdego serwera; wycofaj każdy, który nie pokaże baseline’u i obecnych użytkowników.

Narzędzie ogólne. Narzędzie run_query albo call_api sprawiło, że serwer nadaje się do wszystkiego i do niczego nie jest bezpieczny. Naprawa: odczytaj z logu audytu dziesięć najczęstszych wywołań, zamień każde w narzędzie na poziomie zadania, a potem usuń narzędzie ogólne i ogłoś datę.

Działa w Claude Code, nie działa w Codeksie. Serwer implementuje tylko erę 2026-07-28 albo tylko starszą, gdy klient się zaktualizuje. Naprawa: dodaj do CI obie kontrole --protocol-era i obsługuj obie ery, dopóki wszyscy wspierani klienci nie negocjują nowej.

Współdzielony token serwisowy. Każdy użytkownik dostaje uprawnienia tokenu, a log audytu pokazuje jedną tożsamość. Naprawa: przejdź na OAuth per użytkownik, potwierdź, że log wskazuje pojedynczych użytkowników, a potem unieważnij token. Opcje opisuje strona Tożsamość agentów, poświadczenia i sekrety.

Rozrost narzędzi zjada kontekst. Schemat każdego narzędzia trafia do kontekstu agenta, a serwer z 40 narzędziami wypiera samo zadanie. Naprawa: trzymaj krótką listę narzędzi, ograniczaj ją per klient przez enabled_tools lub reguły uprawnień i zajrzyj do ograniczania kosztu tokenów MCP.

Zmiana schematu po cichu psuje klientów. Pole o zmienionej nazwie zwraca undefined, a agent zgaduje odpowiedź. Naprawa: wersjonuj każdy kontrakt, trzymaj eval na złotych zadaniach w pipeline wydania i obsługuj starą wersję przez okno deprecjacji zapisane w kontrakcie.

Właściciel odszedł. Reorganizacja zlikwidowała zespół, a serwer działa dalej bez nikogo na dyżurze. Naprawa: uczyń pole właściciela obowiązkowym wpisem w katalogu serwisów, ustaw alert, gdy wskazuje rozwiązany zespół, i zastosuj retire_if na najbliższym przeglądzie.