Tworzenie własnego serwera MCP
Własny serwer MCP to mały program, który udostępnia wewnętrzne API, bazę danych albo CLI jako narzędzia, które mogą wywoływać Claude Code, Codex i Cursor. We wrześniu 2026 budujesz go na SDK v2 dla TypeScriptu (@modelcontextprotocol/server) albo na pakiecie PyPI mcp 2.x i uruchamiasz punktem wejścia, który obsługuje zarówno specyfikację MCP 2026-07-28, jak i starszych klientów.
Ta strona jest dla programisty, który odpowiada za wewnętrzny system, i dla tech leada, który decyduje, czy serwer trafi do zespołu. Flagi funkcji siedzą za wewnętrznym API, historia wdrożeń leży w usłudze, o której nikt spoza firmy nie słyszał, a agent nie sięga ani do jednego, ani do drugiego. Wklejasz więc JSON do czatu i to ty jesteś integracją. Własny serwer usuwa ten krok. Trudny nie jest protokół, bo ten obsługuje SDK. Trudny jest kontrakt narzędzia, którego model używa poprawnie, i dowód, że tak jest.
Co daje ci własny serwer MCP
Dział zatytułowany „Co daje ci własny serwer MCP”- Działający serwer na
@modelcontextprotocol/server2.1.0, uruchamiany przezserveStdio, który odpowiada zarówno klientowi negocjującemu spec 2026-07-28 (Claude Code robi to domyślnie z serwerami HTTP), jak i klientowi, który nadal używa starszego protokołu (Codex 0.157.1). - Skill
mcp-builderzainstalowany w twoim agencie i prompt, który każe mu generować szkielet na SDK v2 zamiast na przykładach v1, z którymi przychodzi. - Plik testów i dwa polecenia MCP Inspectora, które dowodzą kontraktu narzędzi w obu erach protokołu, więc nikt nie musi recenzować serwera linijka po linijce.
- Rejestrację w Claude Code, Codeksie i Cursorze oraz pomiar kosztu kontekstu przed i po.
- Trzy sposoby wydania (prywatny npm, Streamable HTTP dla zespołu, publiczny MCP Registry przez
mcp-publisher) i listę kontrolną do zatwierdzenia.
Sprawdzone 2026-09-26 na @modelcontextprotocol/server 2.1.0, @modelcontextprotocol/node 2.1.0, @modelcontextprotocol/express 2.0.1, PyPI mcp 2.2.0, @modelcontextprotocol/inspector 2.8.0, Claude Code 2.1.283 i codex-cli 0.157.1. Każdy blok kodu na tej stronie został skompilowany i uruchomiony na tych wersjach. W środowisku testowym nie było binarki Cursora, więc kroki dla Cursora nie są zweryfikowane.
Serwer MCP, skill czy CLI?
Dział zatytułowany „Serwer MCP, skill czy CLI?”Buduj serwer tylko wtedy, gdy agent potrzebuje dostępu na żywo do czegoś, do czego inaczej nie sięgnie. Wiele próśb „potrzebujemy serwera MCP” to w rzeczywistości brakująca instrukcja albo brakujący skrypt.
| Agent potrzebuje… | Zbuduj | Dlaczego |
|---|---|---|
| Danych lub akcji na żywo za uwierzytelnieniem: flagi funkcji, historia wdrożeń, system incydentów | Serwer MCP | Typowane wejścia, jedno poświadczenie trzymane przez serwer, działa w każdym agencie |
| Procedury: jak pisać migrację, wasza lista kontrolna wydania | Skill (tworzenie własnych skilli) | Kosztuje kontekst tylko wtedy, gdy się uruchamia; nie ma procesu do utrzymania |
Polecenia, które już istnieje: kubectl, gh, cele make | Nic nowego albo skill opisujący polecenie | Agent już uruchamia polecenia powłoki; serwer dodaje drugą drogę do tego samego |
| Czegoś, co robi gotowy serwer: GitHub, Postgres, Sentry | Zainstaluj ten serwer (najlepsze serwery MCP) | Nie chcesz utrzymywać cudzego wrappera API |
Tech leadzi, którzy podejmują tę decyzję za cały zespół, powinni przeczytać wewnętrzne serwery MCP: buduj tylko brakujący interfejs, gdzie są opisane odpowiedzialność za serwer i kryteria jego wycofania.
Zainstaluj skill mcp-builder i pozwól agentowi wygenerować szkielet
Dział zatytułowany „Zainstaluj skill mcp-builder i pozwól agentowi wygenerować szkielet”Skill mcp-builder od Anthropic prowadzi agenta przez research, implementację, testy w MCP Inspectorze i zestaw pytań ewaluacyjnych. Działa we wszystkich trzech agentach przez CLI skills (1.7.0).
npx skills add anthropics/skills --skill mcp-builder -a claude-codeMożesz też zainstalować go jako część pluginu: /plugin marketplace add anthropics/skills, a potem /plugin install example-skills@anthropic-agent-skills. Ten plugin instaluje jeszcze 11 innych przykładowych skilli, więc wybierz instalację pojedynczego skilla.
npx skills add anthropics/skills --skill mcp-builder -a codexnpx skills add anthropics/skills --skill mcp-builder -a cursorZbuduj serwer na SDK v2
Dział zatytułowany „Zbuduj serwer na SDK v2”Porównaj to, co wygenerował agent, z tym wzorcem. To najmniejszy serwer, który poprawnie wykonuje zadanie, z odczytem flag w osobnym module, żeby łatwo podmienić go na prawdziwe wywołanie API.
-
Utwórz projekt i zainstaluj SDK.
Okno terminala mkdir feature-flags-mcp && cd feature-flags-mcpnpm init -y && npm pkg set type=modulenpm install @modelcontextprotocol/server zodnpm install -D typescript @types/node vitest @modelcontextprotocol/clientv2 wymaga Node.js 20 lub nowszego i Zoda 4.2 lub nowszego. Z Zodem 4.0 albo 4.1 SDK przełącza się na własny konwerter i gubi twoje opisy z
.describe()w schemacie, który widzi model. -
Napisz fabrykę serwera w
src/build-server.ts.src/build-server.ts import { McpServer } from '@modelcontextprotocol/server';import { z } from 'zod';import { getFeatureFlags } from './flags.js';export function buildServer() {const server = new McpServer({ name: 'feature-flags', version: '1.0.0' });server.registerTool('get_feature_flags',{description:'Return the feature flags that are ON in one environment. Use before changing code behind a flag.',inputSchema: z.object({environment: z.enum(['dev', 'staging', 'production']).describe('Deployment environment'),}),annotations: { readOnlyHint: true },},async ({ environment }) => {try {const flags = await getFeatureFlags(environment);return { content: [{ type: 'text', text: JSON.stringify(flags, null, 2) }] };} catch (error) {const message = error instanceof Error ? error.message : String(error);return { isError: true, content: [{ type: 'text', text: `Flag lookup failed: ${message}` }] };}},);return server;}src/flags.tseksportujegetFeatureFlags(environment), które wywołuje wasze API flag. Osobny moduł pozwala testom go podmienić. -
Uruchom serwer w
src/server.ts.src/server.ts #!/usr/bin/env nodeimport { serveStdio } from '@modelcontextprotocol/server/stdio';import { buildServer } from './build-server.js';serveStdio(buildServer);serveStdioprzypina jedną instancję serwera do każdego połączenia. Odpowiada na otwarcie w erze 2026-07-28 i, domyślnie, nainitializez ery 2025, więc ta sama binarka działa z klientem w każdej z dwóch er protokołu. -
Dodaj
tsconfig.jsoni zbuduj projekt.tsconfig.json {"compilerOptions": {"target": "ES2022","module": "NodeNext","moduleResolution": "NodeNext","outDir": "dist","rootDir": "src","strict": true,"types": ["node"]},"include": ["src"]}Okno terminala npx tscBuild tworzy
dist/server.js, na który wskazuje każda konfiguracja klienta poniżej.
Trzy szczegóły decydują o tym, czy model dobrze używa narzędzia. Opis to jedyne, co model czyta przy wyborze narzędzia, więc napisz, co zwraca i kiedy go wywołać. z.enum zamienia zgadywanie („prod”?) w błąd walidacji, który model potrafi poprawić. A isError: true pozwala modelowi zobaczyć porażkę i zareagować, zamiast dostać pustą treść i wymyślić odpowiedź.
Udowodnij, że serwer działa, bez czytania każdej linii
Dział zatytułowany „Udowodnij, że serwer działa, bez czytania każdej linii”Pytanie przy przeglądzie serwera MCP nie brzmi „czy ten kod jest ładny?”, tylko „czy model dostaje właściwe narzędzia i czy każde narzędzie bezpiecznie zawodzi?”. Odpowiadają na nie trzy sprawdzenia, które trwają sekundy.
1. Sprawdź kontrakt w obu erach protokołu. CLI MCP Inspectora łączy się starszym protokołem, jeśli nie powiesz inaczej, więc uruchom je dwa razy. Polecenie serwera podaj najpierw: --tool-arg przyjmuje wiele wartości i połyka wszystko, co stoi za nim.
npx @modelcontextprotocol/inspector --cli node dist/server.js --protocol-era modern --method tools/list --strictnpx @modelcontextprotocol/inspector --cli node dist/server.js --protocol-era legacy \ --method tools/call --tool-name get_feature_flags --tool-arg environment=staging--strict zgłasza problemy z przenośnością schematów narzędzi i kończy się kodem 6, jeśli któryś jest błędem, więc nadaje się na bramkę w CI. npx @modelcontextprotocol/inspector bez --cli otwiera interfejs w przeglądarce.
2. Przetestuj kontrakt narzędzi w procesie. createMcpHandler obsługuje 2026-07-28 przez funkcję fetch, więc test może sterować prawdziwym serwerem bez gniazda i bez procesu potomnego:
import { describe, expect, it } from 'vitest';import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';import { createMcpHandler } from '@modelcontextprotocol/server';import { buildServer } from '../src/build-server.js';
async function connect() { const handler = createMcpHandler(buildServer); const transport = new StreamableHTTPClientTransport(new URL('http://test.local/mcp'), { fetch: (url, init) => handler.fetch(new Request(url, init)), }); const client = new Client({ name: 'test', version: '0.0.0' }, { versionNegotiation: { mode: { pin: '2026-07-28' } } }); await client.connect(transport); return client;}
describe('feature-flags MCP server', () => { it('exposes exactly the tools the agent should see', async () => { const { tools } = await (await connect()).listTools(); expect(tools.map((t) => t.name)).toEqual(['get_feature_flags']); });
it('rejects an unknown environment as a tool error, not a crash', async () => { const result = await (await connect()).callTool({ name: 'get_feature_flags', arguments: { environment: 'qa' } }); expect(result.isError).toBe(true); });});Pierwszy test robi się czerwony, gdy ktoś niechcący doda narzędzie zapisujące. Drugi, gdy zepsuje się walidacja albo obsługa błędów. Dodaj po jednym teście ścieżki szczęśliwej na każde narzędzie, z podmienionym getFeatureFlags.
3. Oceń, czy model z niego korzysta. Testy dowodzą kontraktu, ale nie dowodzą, że model wybiera właściwe narzędzie. mcp-builder ma fazę ewaluacji, w której powstaje 10 realistycznych pytań wymagających twoich narzędzi. Uruchamiaj je w świeżej sesji po każdej zmianie opisu lub schematu i trzymaj plik z pytaniami w repozytorium.
Podłącz serwer do Claude Code, Codeksa i Cursora
Dział zatytułowany „Podłącz serwer do Claude Code, Codeksa i Cursora”Używaj ścieżki bezwzględnej: klienci uruchamiają serwer z własnego katalogu roboczego, a nie z twojego projektu. Sekrety przekazuj jako zmienne środowiskowe z powłoki albo menedżera sekretów, nigdy jako wartości wpisane w commitowany plik.
claude mcp add feature-flags -e FLAGS_API_URL="$FLAGS_API_URL" -e FLAGS_API_TOKEN="$FLAGS_API_TOKEN" \ -- node /abs/path/feature-flags-mcp/dist/server.jsclaude mcp get feature-flagsclaude mcp get sprawdza stan serwera i wypisuje Connected, gdy proces startuje i odpowiada. Domyślny zakres to local (tylko ty, tylko ten projekt). Użyj -s project, żeby zapisać .mcp.json dla zespołu; współpracownicy zatwierdzają go wtedy raz. .mcp.json trafia do repozytorium, więc w tym przypadku nie przekazuj tokenu przez -e, tylko ustaw go w środowisku każdego inżyniera. Przy wolnym systemie źródłowym zwiększ MCP_TOOL_TIMEOUT (w milisekundach) w środowisku, z którego uruchamiasz Claude Code.
codex mcp add feature-flags --env FLAGS_API_URL="$FLAGS_API_URL" --env FLAGS_API_TOKEN="$FLAGS_API_TOKEN" \ -- node /abs/path/feature-flags-mcp/dist/server.jscodex mcp get feature-flagsTo zapisuje [mcp_servers.feature-flags] w ~/.codex/config.toml. Limity czasu to klucze startup_timeout_sec i tool_timeout_sec w tej tabeli. Codex 0.157.1 łączy się protokołem z ery 2025 (mcp_2026_07_28 ma w codex features list status under development i jest wyłączone), a serveStdio odpowiada również na niego.
Dodaj serwer do .cursor/mcp.json w projekcie (albo do globalnego pliku w katalogu domowym):
{ "mcpServers": { "feature-flags": { "command": "node", "args": ["/abs/path/feature-flags-mcp/dist/server.js"], "env": { "FLAGS_API_URL": "https://flags.internal.example.com" } } }}Nie wpisuj tokenu do tego pliku; ustaw FLAGS_API_TOKEN w środowisku, z którego startuje Cursor. Ustawienia MCP w Cursorze pokazują, czy serwer się połączył. Obsługi specyfikacji 2026-07-28 w Cursorze nie zweryfikowano 2026-09-26; serwer odpowiada w obu protokołach.
Sprawdź koszt kontekstu. Każdy schemat narzędzia siedzi w kontekście agenta. W Claude Code uruchom /context przed dodaniem serwera i po nim i porównaj wiersz narzędzi MCP. Claude Code i Codex domyślnie odraczają schematy narzędzi przez wyszukiwanie narzędzi (tool search), więc jeden mały serwer kosztuje niewiele, ale koszt rośnie z każdym narzędziem. Dziesięć wąskich narzędzi to gorszy wybór niż trzy dobrze opisane. Zobacz ograniczanie kosztu tokenów MCP.
Bezpiecznie opakuj wewnętrzne API albo CLI
Dział zatytułowany „Bezpiecznie opakuj wewnętrzne API albo CLI”Narzędzie to granica wejścia: argumenty wybiera model, a może je wybrać także prompt injection ukryty w czymś, co agent przeczytał wcześniej. Dwa wzorce pokrywają większość wewnętrznych serwerów.
import { execFile } from 'node:child_process';import { promisify } from 'node:util';import type { McpServer } from '@modelcontextprotocol/server';import { z } from 'zod';
const execFileAsync = promisify(execFile);
export function registerOpsTools(server: McpServer) { server.registerTool( 'list_deployments', { description: 'List the most recent deployments of one service, newest first.', inputSchema: z.object({ service: z.string().regex(/^[a-z0-9-]{1,64}$/), limit: z.number().int().min(1).max(50).default(10), }), annotations: { readOnlyHint: true }, }, async ({ service, limit }) => { const url = new URL('/deployments', process.env.DEPLOY_API_URL); url.searchParams.set('service', service); url.searchParams.set('limit', String(limit)); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.DEPLOY_API_TOKEN}` } }); if (!res.ok) { return { isError: true, content: [{ type: 'text', text: `Deploy API returned HTTP ${res.status} for ${service}` }] }; } return { content: [{ type: 'text', text: JSON.stringify(await res.json(), null, 2) }] }; }, );
server.registerTool( 'kubectl_get', { description: 'Read Kubernetes resources as JSON. Read-only: never creates, edits or deletes.', inputSchema: z.object({ resource: z.enum(['pods', 'services', 'deployments', 'ingresses']), namespace: z.string().regex(/^[a-z0-9-]{1,63}$/).default('default'), }), annotations: { readOnlyHint: true }, }, async ({ resource, namespace }) => { try { const { stdout } = await execFileAsync('kubectl', ['get', resource, '-n', namespace, '-o', 'json'], { timeout: 15_000, maxBuffer: 5 * 1024 * 1024, }); return { content: [{ type: 'text', text: stdout }] }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: 'text', text: `kubectl failed: ${message}` }] }; } }, );}Bezpieczne czyni je kształt, a nie komentarze. URL i searchParams kodują wejście, zamiast doklejać je do ścieżki. execFile z tablicą argumentów nie uruchamia powłoki, a z.enum i wyrażenie regularne są listą dozwolonych wartości. Serwer trzyma jeden token konta usługowego o wąskim zakresie; agent nigdy go nie widzi. Wywołaj registerOpsTools(server) w buildServer(), żeby testy objęły również te narzędzia.
Zacznij od narzędzi tylko do odczytu. Narzędzie zapisujące dodawaj dopiero wtedy, gdy zatwierdzi je recenzent, daj mu własne wąskie wejście i nie ustawiaj readOnlyHint, żeby klienci pytali o zgodę. Modelowanie zagrożeń opisuje strona bezpieczeństwo MCP.
Narzędzia, zasoby czy prompty?
Dział zatytułowany „Narzędzia, zasoby czy prompty?”Serwery MCP udostępniają trzy prymitywy. Większości wewnętrznych serwerów wystarczą narzędzia.
| Prymityw | Rejestrowany przez | Do czego | Zachowanie klientów |
|---|---|---|---|
| Narzędzie (tool) | registerTool | Wszystko, co model sam postanawia wywołać: odczyty, wyszukiwania, akcje | Obsługiwane przez wszystkich trzech agentów |
| Zasób (resource) | registerResource (v2 wymaga argumentu z metadanymi; przekaż {}, jeśli ich nie masz) | Dokumenty, które dołącza użytkownik: runbooki, schematy | Klienci różnią się tym, jak zasoby trafiają do modelu; sprawdź każdego agenta, zanim zaczniesz na tym polegać |
| Prompt | registerPrompt | Powtarzalny przepływ, który użytkownik uruchamia z nazwy, np. szablon postmortemu | Klienci różnią się tym, jak pokazują prompty; często lepiej sprawdzi się skill |
W razie wątpliwości zrób z tego narzędzie. Model może wywołać narzędzie sam; zasób albo prompt zwykle musi wybrać człowiek.
Udostępnij serwer zespołowi przez HTTP
Dział zatytułowany „Udostępnij serwer zespołowi przez HTTP”Serwer stdio działa na maszynie każdego inżyniera, z poświadczeniami każdego inżyniera. Gdy kilka osób albo zadanie CI ma współdzielić jeden serwer z jednym kontem usługowym, wystaw Streamable HTTP. createMcpHandler obsługuje 2026-07-28 i, domyślnie, bezstanowe żądania z ery 2025 z tego samego endpointu.
import { createMcpExpressApp } from '@modelcontextprotocol/express';import { toNodeHandler } from '@modelcontextprotocol/node';import { createMcpHandler } from '@modelcontextprotocol/server';import { buildServer } from './build-server.js';
const handler = createMcpHandler(buildServer);const app = createMcpExpressApp({ host: '0.0.0.0', allowedHosts: ['flags-mcp.internal.example.com'] });
app.all('/mcp', toNodeHandler(handler));app.listen(3000, '0.0.0.0');Do tego zainstaluj adaptery oraz @types/express jako zależność deweloperską, żeby tsc skompilował src/http.ts: npm install @modelcontextprotocol/express @modelcontextprotocol/node express && npm install -D @types/express. allowedHosts odrzuca każdy inny nagłówek Host kodem HTTP 403, co blokuje DNS rebinding. To nie jest uwierzytelnianie: zanim ktokolwiek spoza twojego laptopa dostanie się do endpointu, postaw go za proxy świadomym tożsamości albo bramką, albo dodaj weryfikację tokenu bearer. Serwer tworzy świeżą instancję na każde żądanie, więc nie ma stanu sesji, który zginie, gdy load balancer przeniesie żądanie.
Zamiast polecenia zarejestruj URL: claude mcp add --transport http feature-flags https://flags-mcp.internal.example.com/mcp albo codex mcp add feature-flags --url https://flags-mcp.internal.example.com/mcp --bearer-token-env-var FLAGS_MCP_TOKEN.
Serwer, który już działa na SDK v1 albo trzyma stan sesji, wymaga migracji, a nie przepisania od zera: zobacz MCP 2026-07-28: co się zmieniło i jak zmigrować serwer.
Wydaj serwer: prywatny npm, wspólny serwer HTTP albo publiczny MCP Registry
Dział zatytułowany „Wydaj serwer: prywatny npm, wspólny serwer HTTP albo publiczny MCP Registry”| Odbiorcy | Wydaj jako | Klienci uruchamiają |
|---|---|---|
| Twoja firma | Pakiet w prywatnym rejestrze npm, z wpisem bin | npx -y @acme/feature-flags-mcp |
| Twoja firma, jedno wspólne poświadczenie | Serwer HTTP z poprzedniej sekcji w kontenerze za waszą bramką | URL |
| Wszyscy | Publiczny pakiet npm plus wpis w oficjalnym MCP Registry | npx -y z twoim pakietem, znalezionym przez klientów obsługujących rejestr |
Oficjalny MCP Registry przechowuje tylko metadane, więc pakiet musi najpierw być publiczny. Rejestr to nadal wersja preview (API zamrożone na v0.1 od 2025-10-24; możliwe są zmiany niekompatybilne i resety danych). 2026-09-26 zawierał 36 176 serwerów w version=latest (API rejestru, pełna paginacja). Nigdy nie publikuj tam wewnętrznego serwera; do kuratorowania wewnętrznych serwerów prowadź prywatny katalog, jak opisuje rejestry, allowlisty i bramki MCP.
-
Dodaj
mcpNamedopackage.json. Przy uwierzytelnianiu przez GitHub musi zaczynać się odio.github.<twój-użytkownik-lub-organizacja>/.package.json (fragment) {"name": "@acme/feature-flags-mcp","version": "1.0.0","mcpName": "io.github.acme/feature-flags","type": "module","bin": { "feature-flags-mcp": "dist/server.js" },"files": ["dist"]} -
Opublikuj pakiet:
npm publish --access public. -
Zainstaluj publisher i utwórz
server.json.Okno terminala brew install mcp-publishermcp-publisher initUstaw
namena tę samą wartość comcpName, a oba polaversionna wersję opublikowaną w npm. -
Zwaliduj, zaloguj się i opublikuj.
Okno terminala mcp-publisher validatemcp-publisher login githubmcp-publisher publish
Gdy chcesz odwrotnie: Claude Code jako serwer MCP
Dział zatytułowany „Gdy chcesz odwrotnie: Claude Code jako serwer MCP”claude mcp serve uruchamia samo Claude Code jako serwer MCP na stdio, dzięki czemu inny klient MCP może korzystać z jego narzędzi. To nie jest sposób na zbudowanie własnego serwera, a Codex 0.157.1 nie ma odpowiednika. Sięgnij po to, gdy narzędzie, którego już używasz, obsługuje MCP i ma korzystać z narzędzi plikowych i powłoki Claude Code; działa ono z uprawnieniami, na które pozwala dana konfiguracja Claude Code.
Co psuje się we własnym serwerze MCP?
Dział zatytułowany „Co psuje się we własnym serwerze MCP?”Klient pokazuje serwer jako niedziałający albo połączony bez narzędzi. Coś pisze na stdout. Przy stdio stdout jest kanałem protokołu. Klienci na SDK v2 pomijają linie, które nie są JSON-em, ale nie kontrolujesz, który klient się połączy, więc przenieś wszystkie logi na stderr (console.error) i sprawdź zależności, które wypisują bannery. Potem uruchom polecenie Inspectora z tools/list z tej strony.
Codex widzi narzędzia, a Claude Code nie (albo odwrotnie). Serwer odpowiada tylko w jednej erze protokołu. Serwer v2 uruchomiony przez server.connect(new StdioServerTransport()) obsługuje tylko protokół z ery 2025. Przełącz się na serveStdio(buildServer) albo createMcpHandler(buildServer) i ponownie uruchom Inspectora w obu erach.
Każde wywołanie nie przechodzi walidacji albo brakuje opisów pól. Masz Zoda 3 albo Zoda 4.0–4.1, albo przekazałeś surowy kształt ({ env: z.string() }) zbudowany inną kopią Zoda. Zainstaluj zod@^4.2.0 i opakowuj schematy w z.object().
„Cannot find module” przy starcie. Klient uruchamia serwer z innego katalogu albo w package.json brakuje "type": "module". Użyj ścieżki bezwzględnej do dist/server.js i przebuduj projekt.
Narzędzie wisi, a potem agent się poddaje. System źródłowy jest wolny. Ustaw limit czasu na każdym fetch i execFile, żeby narzędzie zwracało isError zamiast wisieć, a potem zwiększ limit klienta, jeśli praca naprawdę trwa długo: MCP_TOOL_TIMEOUT w Claude Code, tool_timeout_sec w Codeksie.
Model wywołuje złe narzędzie albo zmyśla argumenty. Opis jest mglisty albo dwa narzędzia się pokrywają. Przepisz opis tak, żeby mówił, co zwraca i kiedy go użyć, połącz pokrywające się narzędzia i ponownie uruchom pytania ewaluacyjne.
mcp-publisher publish odrzuca serwer. name w server.json nie zgadza się z mcpName, przestrzeń nazw nie pasuje do konta, na które się zalogowałeś, albo wersja nie jest jeszcze opublikowana w npm. Popraw niezgodność i ponownie uruchom mcp-publisher validate.
Zatwierdź własny serwer MCP
Dział zatytułowany „Zatwierdź własny serwer MCP”Tech lead zatwierdza serwer na podstawie dowodów, a nie lektury handlerów:
-
npm run verifyprzechodzi w CI: sprawdzenie typów, testy i przebieg Inspectora z--strictw obu erach protokołu. - Test przypina dokładną listę narzędzi, a każde narzędzie bez
readOnlyHintjest na zatwierdzonej liście narzędzi zapisujących. - Serwer używa jednego poświadczenia konta usługowego o wąskim zakresie, pobieranego ze środowiska; żaden sekret nie leży w commitowanym pliku.
- Każde wywołanie systemu źródłowego ma limit czasu, a każda porażka zwraca
isError. - Pytania ewaluacyjne przechodzą w świeżej sesji głównego agenta zespołu.
- Serwer ma nazwanego właściciela i warunek wycofania.
Stan na 2026-09-26: modelcontextprotocol/inspector ma 11,0 tys. gwiazdek na GitHubie, a mcp-builder ma 118 601 instalacji łącznie według zewnętrznego zrzutu skills.sh (LinklyAI/best-skills, z datą 2026-09-26; źródło wtórne, bo samego skills.sh nie udało się odczytać).