Polecenia z tego poradnika zostały uruchomione 6 października 2026 w czystym systemie (Ubuntu 24.04.5 LTS, Node.js 24.21.0, Python 3.12.3). Wyniki pod poleceniami pochodzą z tego uruchomienia.

Własny MCP server w TypeScript zbudujesz, instalując SDK, tworząc McpServer, rejestrując narzędzie przez registerTool i uruchamiając komunikację przez serveStdio. To podstawowy schemat pokazany w dokumentacji SDK. Poniżej przygotowuję kompletny przykład: narzędzie odczytujące demonstracyjne zgłoszenie, sprawdzenie jego działania i podłączenie do VS Code.

W skrócie

  • Na początek polecam jedno narzędzie wykonujące wyłącznie odczyt.
  • Najpierw sprawdź je bez modelu, potem podłącz do aplikacji AI.
  • Przed integracją z firmowymi danymi zaplanuj uprawnienia i obsługę błędów.

Dokumentację sprawdziłem 6 października 2026 r.

Czym jest MCP server i gdzie działa?

Serwer MCP to program udostępniający funkcje lub dane klientowi MCP. Host, czyli aplikacja AI, zarządza klientami łączącymi się z serwerami. Takie rozdzielenie ról opisuje architektura MCP.

W moim przykładzie hostem będzie VS Code z Copilotem, a serwerem lokalny proces TypeScript. Zamiast prawdziwego systemu zgłoszeń wykorzystuję mały zbiór danych w pamięci. Dzięki temu można prześledzić cały przepływ bez konta w zewnętrznym serwisie.

flowchart TD
    U[Użytkownik] --> H[Aplikacja AI]
    H <--> M[Model]
    H --> C[Klient MCP]
    C <-->|stdio| S[Serwer TypeScript]
    S --> D[Demonstracyjne zgłoszenia]

MCP rozróżnia narzędzia, zasoby i szablony promptów. Narzędzie jest funkcją wykonywaną na żądanie, zasób dostarcza kontekst, a prompt jest szablonem interakcji. Definicje znajdziesz w opisie elementów protokołu.

Do sprawdzania statusu zgłoszenia wybieram narzędzie. Polecam nazwę opisującą konkretną czynność, taką jak get-ticket, zamiast ogólnego execute, które niewiele mówi o zastosowaniu funkcji.

Budowa serwera krok po kroku

1. Przygotuj projekt i zależności

Przygotuj Node.js co najmniej 22.19.0 oraz npm. Wyższe wymaganie wynika z aktualnej dokumentacji Inspectora, którego użyję do sprawdzenia serwera.

W nowym projekcie wybieram stabilną linię SDK v2, wskazaną w dokumentacji TypeScript. Pakiet serwerowy nazywa się @modelcontextprotocol/server; starsze poradniki mogą używać @modelcontextprotocol/sdk, co wyjaśnia opis pakietów i importów.

W katalogu swoich projektów wykonaj poniższe polecenia. Kolejne polecenia w artykule uruchamiaj już z katalogu mcp-tickets:

mkdir mcp-tickets
cd mcp-tickets
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server zod tsx
mkdir src
Wynik w czystym systemie:
Wrote to /work/cb0e66ce-e7e7-44cd-a861-3b5d039513ef/mcp-tickets/package.json:

{
  "name": "mcp-tickets",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
…
npm warn install-scripts Run `npm install-scripts ls` to review, or `npm install-scripts approve <pkg>` to allow.

To układ z oficjalnego przewodnika budowy serwera, z własną nazwą projektu. type=module ustawia moduły ES, a tsx pozwala uruchamiać TypeScript bez osobnego kroku kompilacji.

2. Zarejestruj narzędzie odczytujące zgłoszenie

Narzędzie potrzebuje nazwy, konfiguracji i funkcji obsługującej wywołanie. Schemat argumentów definiuję przez Zod, zgodnie z dokumentacją registerTool.

Utwórz plik src/index.ts:

import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

interface Ticket {
  title: string;
  status: string;
}

const tickets = new Map<string, Ticket>([
  ['SUP-101', { title: 'Błąd logowania', status: 'otwarte' }],
  ['SUP-102', { title: 'Zmiana adresu e-mail', status: 'zamknięte' }]
]);

function createServer(): McpServer {
  const server = new McpServer({
    name: 'ticket-demo',
    version: '1.0.0'
  });

  server.registerTool(
    'get-ticket',
    {
      description:
        'Odczytuje demonstracyjne zgłoszenie po identyfikatorze. Nie zmienia danych.',
      inputSchema: z.object({
        id: z.string().length(7)
          .describe('Identyfikator zgłoszenia, np. SUP-101')
      })
    },
    async ({ id }) => {
      const ticket = tickets.get(id);

      if (!ticket) {
        return {
          content: [{ type: 'text', text: `Brak zgłoszenia ${id}.` }],
          isError: true
        };
      }

      return {
        content: [{
          type: 'text',
          text: JSON.stringify({ id, ...ticket })
        }]
      };
    }
  );

  return server;
}

void serveStdio(createServer);
console.error('Serwer zgłoszeń oczekuje na klienta MCP.');

SDK wyprowadza z inputSchema schemat JSON udostępniany klientowi i sprawdza argumenty przed wykonaniem funkcji. Opis dodany przez .describe() trafia również do schematu, zgodnie z dokumentacją narzędzi.

W tym przykładzie sprawdzam typ i długość identyfikatora. Nie sprawdzam jego prefiksu: dowolny tekst o odpowiedniej długości przejdzie walidację, a dopiero wyszukanie ustali, czy zgłoszenie istnieje. Jeśli potrzebujesz bardziej restrykcyjnego formatu, polecam rozszerzyć schemat.

serveStdio obsługuje wejście i wyjście procesu. Żądania przychodzą przez stdin, odpowiedzi wychodzą przez stdout, co opisuje przewodnik transportu stdio.

Uwaga: Przy stdio zapisuj diagnostykę przez console.error. stdout służy do komunikacji protokołu, więc zwykły console.log może zakłócić jej parsowanie, jak pokazuje dokumentacja transportu.

3. Uruchom serwer i sprawdź wyniki

Z katalogu projektu wykonaj:

npx tsx src/index.ts
Wynik w czystym systemie:
Serwer zgłoszeń oczekuje na klienta MCP.

Powinien pojawić się komunikat z ostatniej linii pliku. Proces czeka na klienta, dlatego samo uruchomienie nie wyświetli danych zgłoszenia. Takie zachowanie opisuje instrukcja uruchomienia serwera.

Zatrzymaj proces przez Ctrl+C, a następnie uruchom Inspector:

npx @modelcontextprotocol/inspector npx tsx src/index.ts

Inspector uruchamia podane polecenie serwera i łączy się z nim przez stdio, zgodnie z przewodnikiem transportu.

  1. Otwórz w przeglądarce adres wypisany przez Inspector, zawierający token sesji.
  2. W zakładce Servers połącz się z przekazanym serwerem.
  3. Przejdź do Tools, wybierz get-ticket, wpisz SUP-101 w polu id i wykonaj wywołanie.

Zakładki i formularz argumentów opisuje dokumentacja interfejsu Inspectora. W tekstowym bloku odpowiedzi mojego narzędzia powinno znaleźć się:

{"id":"SUP-101","title":"Błąd logowania","status":"otwarte"}

Polecam sprawdzić następujące przypadki:

Argument idOczekiwany wynik przykładuCo sprawdzasz
SUP-101Dane otwartego zgłoszeniaPoprawny odczyt
SUP-102Dane zamkniętego zgłoszeniaRozróżnianie rekordów
SUP-999Brak zgłoszenia SUP-999. i isError: trueObsługę braku danych
badOdrzucenie argumentuWalidację długości

Błędny argument możesz przesłać bez formularza. Zatrzymaj Inspector i wykonaj polecenie oparte na udokumentowanym trybie CLI:

npx @modelcontextprotocol/inspector --cli npx tsx src/index.ts \
  --method tools/call \
  --tool-name get-ticket \
  --tool-args-json '{"id":"bad"}'

Oczekuj błędu walidacji zamiast komunikatu o braku zgłoszenia. SDK odrzuca nieprawidłowe argumenty przed wykonaniem funkcji, co pokazuje przykład walidacji wejścia.

4. Podłącz serwer do VS Code

Do tego kroku przygotuj VS Code z rozszerzeniem GitHub Copilot i zalogowanym kontem. Konfigurację lokalnego serwera opisuje przewodnik podłączenia do hosta.

Otwórz katalog mcp-tickets jako katalog główny projektu. Utwórz katalog .vscode, a w nim plik .vscode/mcp.json:

{
  "servers": {
    "tickets": {
      "type": "stdio",
      "command": "npx",
      "args": ["tsx", "src/index.ts"]
    }
  }
}

Następnie:

  1. Potwierdź zaufanie do dodanego serwera.
  2. Otwórz paletę poleceń i uruchom MCP: List Servers.
  3. Sprawdź, czy tickets działa.
  4. Otwórz Copilot Chat, wybierz tryb Agent i poproś: „Sprawdź status zgłoszenia SUP-101”.
  5. Zatwierdź proponowane wywołanie narzędzia, jeśli aplikacja poprosi o zgodę.

Polecenie, tryb czatu i przebieg wywołania są opisane w instrukcji integracji z VS Code. Host uruchamia proces z katalogu głównego projektu, dlatego względna ścieżka src/index.ts pasuje do tej konfiguracji.

Jak przejść od przykładu do firmowej integracji?

Polecam zachować kontrakt get-ticket, a odczyt z Map zastąpić osobną funkcją komunikującą się z API systemu zgłoszeń. W takiej funkcji zaplanowałbym limit czasu, obsługę awarii i sprawdzenie, czy użytkownik może zobaczyć wskazany rekord.

Przed dodaniem operacji zapisu przygotowałbym następujące elementy:

  • ograniczony zakres zwracanych danych;
  • poświadczenia przechowywane poza kodem;
  • kontrolę uprawnień do konkretnego zgłoszenia;
  • potwierdzenie operacji zmieniających dane;
  • logi bez sekretów i pełnej treści zgłoszeń.

Dla zdalnego endpointu polecam osobno zaprojektować uwierzytelnianie. Dokumentacja autoryzacji SDK pokazuje weryfikację tokenów dostępu przed obsługą żądań. Sam przykład powyżej korzysta wyłącznie z demonstracyjnych danych lokalnych.

FAQ

Czy serwer MCP musi działać w chmurze?

Nie. MCP przewiduje serwery lokalne i zdalne, co opisuje dokumentacja architektury. Do pierwszego narzędzia polecam lokalny proces stdio.

Czy potrzebuję klucza API do modelu?

Do uruchomienia tego przykładu i wywołań w Inspectorze nie potrzebujesz klucza do modelu. Kod odczytuje wyłącznie dane z Map; dostęp do modelu konfigurujesz osobno w wybranym hoście.

Czy muszę kompilować TypeScript przed uruchomieniem?

W tym wariancie nie. Używam tsx, które uruchamia TypeScript bez osobnego kroku budowania, zgodnie z oficjalnym przewodnikiem.

Jak udostępnić istniejące API przez MCP?

Polecam zacząć od jednej funkcji biznesowej, np. odczytu zgłoszenia. Opisz jej argumenty, wywołaj API wewnątrz funkcji obsługującej narzędzie i zwróć tylko dane potrzebne do odpowiedzi.

Co dalej

Po zbudowaniu lokalnego narzędzia przejdź do materiału o skalowaniu serwera MCP. Jeśli potrzebujesz pomocy przy połączeniu MCP z firmowymi narzędziami, napisz do mnie.

Źródła

  1. MCP TypeScript SDKts.sdk.modelcontextprotocol.io
  2. Architecture overviewmodelcontextprotocol.io
  3. Packages and subpath exportsts.sdk.modelcontextprotocol.io
  4. Build your first serverts.sdk.modelcontextprotocol.io
  5. Toolsts.sdk.modelcontextprotocol.io
  6. Serve over stdiots.sdk.modelcontextprotocol.io
  7. MCP Inspectormodelcontextprotocol.io
  8. Web clientmodelcontextprotocol.io
  9. CLI clientmodelcontextprotocol.io
  10. Plug into a real hostts.sdk.modelcontextprotocol.io
  11. Require authorizationts.sdk.modelcontextprotocol.io

Autor The Prompt. Rozwija Czatowy, Sklepowy i TerazRobot.