✨ Świeża dostawa•nowe kody na kinetyka.pl: Gemini Pro 18 mies. 170 zł•Cursor, ElevenLabs, Lovable i więcej, roczne plany AI w ułamku ceny Zobacz →
Przejdź do treści
Artykuły

Własny serwer MCP w 15 minut: Python SDK, Inspector i Claude Code

Buduję serwer MCP z polskimi narzędziami w oficjalnym Python SDK, testuję go w MCP Inspector i podłączam do Claude Code. Z pułapką FastMCP w wersji 2.

11 min czytania
Logo Model Context Protocol - własny serwer MCP w Pythonie

👁 116 przeczytań

// w skrócie
  • Własny serwer MCP w Pythonie można zbudować w 15 minut, używając oficjalnego SDK w wersji 2.3.0 i klasy MCPServer z dekoratorem @mcp.tool().
  • W pakiecie mcp 2.3.0 klasa FastMCP zmieniła nazwę na MCPServer, przez co kod z poradników z 2025 roku zwraca błąd 'No module named mcp.server.fastmcp'.
  • Test trzech narzędzi w Claude Code z modelem Claude Haiku 4.5 przez OpenRouter kosztował około 0,06 USD, a samo wywołanie serwera w Pythonie zajęło 0,36 sekundy.

Serwer MCP to mały program, który wystawia Twoje funkcje w standardzie Model Context Protocol, tak że może ich używać Claude Code, Claude Desktop, Cursor, ChatGPT czy własny agent. W oficjalnym Python SDK piszesz zwykłe funkcje z dekoratorem @mcp.tool() i jedną linię uruchomienia. Zbudowałem serwer z trzema polskimi narzędziami (kurs NBP, dni robocze ze świętami, wyszukiwanie w notatkach), sprawdziłem go w MCP Inspector i podłączyłem do Claude Code. Całość zajęła mi kwadrans, łącznie z pułapką, na którą trafi każdy, kto kopiuje stare poradniki. Tekst jest częścią ścieżki Agenci AI od zera.

Stan na 4 października 2026

  • Oficjalny pakiet mcp dla Pythona ma wersję 2.3.0. W wersji 2 klasa FastMCP zmieniła nazwę na MCPServer, więc kod z większości poradników z 2025 roku nie działa bez poprawki.
  • MCP Inspector (narzędzie do testowania serwerów) ma wersję 2.9.0 i tryb wiersza poleceń --cli.
  • Najnowsza wersja specyfikacji MCP na modelcontextprotocol.io nosi datę 2026-07-28.
  • Testy: Windows 11, Python 3.13, Node.js 26, Claude Code 2.1.287. Koszt testu w Claude Code z modelem Claude Haiku 4.5 przez OpenRouter: około 0,06 USD.

MCP w jednym akapicie

Bez MCP każdą funkcję trzeba opisać osobno dla każdej aplikacji: inaczej dla API OpenAI, inaczej dla Claude, inaczej dla edytora kodu. MCP to wspólna wtyczka. Piszesz serwer raz, a każdy klient zgodny z MCP sam pyta go „jakie masz narzędzia?” i wywołuje je, kiedy model o to poprosi. Pod spodem to ten sam function calling, tylko z ustandaryzowanym transportem. Szersze wprowadzenie do samego protokołu jest w tekście MCP: co to jest.

Serwer może wystawiać trzy rodzaje rzeczy:

  • narzędzia (tools): funkcje, które model wywołuje, np. „pobierz kurs waluty”;
  • zasoby (resources): dane do odczytu, np. treść pliku albo rekord z bazy;
  • prompty: gotowe szablony poleceń, które użytkownik wybiera z listy.

W tym tekście robię tylko narzędzia, bo od nich zaczyna się 90% praktycznych serwerów.

Krok 1: instalacja (2 minuty)

  1. Utwórz środowisko: python -m venv .venv i .venv\Scripts\activate.
  2. Zainstaluj SDK: pip install "mcp[cli]" requests.
  3. Do testów w przeglądarce potrzebujesz Node.js (MCP Inspector uruchamia się przez npx).

Krok 2: serwer z trzema narzędziami (5 minut)

"""05 - Własny serwer MCP (oficjalne Python SDK, wersja 2.x: klasa MCPServer, dawniej FastMCP).
Test w przeglądarce:  npx @modelcontextprotocol/inspector python 05_serwer_mcp.py
W Claude Code:        claude mcp add polskie-narzedzia -- python C:/pelna/sciezka/05_serwer_mcp.py
"""
import datetime as dt, pathlib
import requests
from mcp.server import MCPServer

mcp = MCPServer("polskie-narzedzia", instructions="Kursy NBP, dni robocze w Polsce i notatki z folderu dane/.")
NOTATKI = (pathlib.Path(__file__).parent / "dane").resolve()

@mcp.tool()
def kurs_nbp(waluta: str = "EUR") -> dict:
    """Średni kurs waluty z tabeli A NBP (np. EUR, USD, CHF, GBP)."""
    r = requests.get(f"https://api.nbp.pl/api/exchangerates/rates/a/{waluta.lower()}/?format=json", timeout=15)
    if r.status_code != 200:
        return {"blad": f"NBP nie zna waluty {waluta}"}
    k = r.json()["rates"][0]
    return {"waluta": waluta.upper(), "kurs_pln": k["mid"], "data_tabeli": k["effectiveDate"], "tabela": k["no"]}

def wielkanoc(rok: int) -> dt.date:  # algorytm Meeusa/Jonesa/Butchera
    a, b, c = rok % 19, rok // 100, rok % 100
    d, e = divmod(b, 4); f = (b + 8) // 25; g = (b - f + 1) // 3
    h = (19 * a + b - d - g + 15) % 30; i, k = divmod(c, 4)
    l = (32 + 2 * e + 2 * i - h - k) % 7; m = (a + 11 * h + 22 * l) // 451
    return dt.date(rok, (h + l - 7 * m + 114) // 31, (h + l - 7 * m + 114) % 31 + 1)

def swieta(rok: int) -> set:
    w = wielkanoc(rok)
    stale = [(1, 1), (1, 6), (5, 1), (5, 3), (8, 15), (11, 1), (11, 11), (12, 24), (12, 25), (12, 26)]  # 24.12 od 2025
    return {dt.date(rok, m, d) for m, d in stale} | {w, w + dt.timedelta(1), w + dt.timedelta(49), w + dt.timedelta(60)}

@mcp.tool()
def dni_robocze(od: str, do: str) -> dict:
    """Liczy dni robocze w Polsce między datami RRRR-MM-DD (włącznie), bez weekendów i świąt ustawowych."""
    a, b = dt.date.fromisoformat(od), dt.date.fromisoformat(do)
    sw = set().union(*(swieta(r) for r in range(a.year, b.year + 1)))
    dni = [a + dt.timedelta(n) for n in range((b - a).days + 1)]
    robocze = [d for d in dni if d.weekday() < 5 and d not in sw]
    return {"od": od, "do": do, "dni_robocze": len(robocze), "swieta_w_okresie": sorted(str(d) for d in dni if d in sw)}

@mcp.tool()
def szukaj_w_notatkach(fraza: str) -> list[dict]:
    """Szuka frazy w plikach .txt z folderu dane/ i zwraca pasujące linie."""
    wyniki = []
    for p in NOTATKI.rglob("*.txt"):
        for nr, linia in enumerate(p.read_text(encoding="utf-8").splitlines(), 1):
            if fraza.lower() in linia.lower():
                wyniki.append({"plik": p.name, "linia": nr, "tekst": linia.strip()})
    return wyniki[:20]

if __name__ == "__main__":
    mcp.run()  # domyślnie stdio: klient (Claude Code, Inspector) uruchamia ten plik jako podproces

Co tu się dzieje:

  • MCPServer("polskie-narzedzia", instructions=...) tworzy serwer. Instrukcje trafiają do klienta i podpowiadają modelowi, do czego serwer służy;
  • każda funkcja z @mcp.tool() staje się narzędziem. Nazwa funkcji, docstring i podpowiedzi typów zamieniają się w opis i schemat JSON, który widzi model. Dlatego docstringi piszę jak instrukcje;
  • funkcja może zwrócić słownik albo listę, SDK sam zamieni wynik na JSON;
  • mcp.run() uruchamia serwer w trybie stdio: klient odpala ten plik jako podproces i rozmawia z nim przez standardowe wejście i wyjście. Nie potrzebujesz portu ani serwera WWW.

Narzędzie dni_robocze liczy Wielkanoc algorytmem Meeusa, a z niej Poniedziałek Wielkanocny, Zielone Świątki i Boże Ciało. Ma też Wigilię, która jest dniem wolnym od pracy od 2025 roku. Takiej wiedzy model nie ma pewnej w głowie, a to klasyczne miejsce na narzędzie.

Pułapka: FastMCP w wersji 2 już nie istnieje

Większość poradników (także oficjalnych przykładów z 2025 roku) zaczyna się od from mcp.server.fastmcp import FastMCP. Na pakiecie mcp 2.3.0 dostałem:

No module named 'mcp.server.fastmcp'. This is mcp 2.x, where FastMCP was renamed to MCPServer
(from mcp.server.mcpserver import MCPServer) and other APIs changed; see the migration guide
at https://py.sdk.modelcontextprotocol.io/v2/migration/#fastmcp-renamed-to-mcpserver
or pin 'mcp<2' to keep running v1 code.

Dwie drogi: przepisać import na from mcp.server import MCPServer (dekoratory @mcp.tool() działają tak samo) albo zainstalować starą wersję poleceniem pip install "mcp<2". Wybrałem pierwszą.

Krok 3: test bez żadnego klienta AI (1 minuta)

Zanim podłączysz serwer do modelu, sprawdź go z Pythona. SDK ma klienta, który łączy się z serwerem w pamięci:

"""Test serwera MCP z Pythona (bez Claude Code i bez Inspectora): lista narzędzi + 3 wywołania."""
import anyio, importlib, json
from mcp import Client

serwer = importlib.import_module("05_serwer_mcp").mcp   # klient w pamięci; zamiast tego może być adres http://.../mcp

async def main():
    async with Client(serwer) as c:
        for t in (await c.list_tools()).tools:
            print("NARZĘDZIE:", t.name, "-", t.description)
        for nazwa, args in [("kurs_nbp", {"waluta": "CHF"}), ("dni_robocze", {"od": "2026-12-01", "do": "2026-12-31"}),
                            ("szukaj_w_notatkach", {"fraza": "termin"})]:
            r = await c.call_tool(nazwa, args)
            print(f"\n{nazwa}({json.dumps(args, ensure_ascii=False)}) ->", r.content[0].text)

anyio.run(main)

Wynik dla grudnia 2026: 21 dni roboczych, święta 24, 25 i 26 grudnia (26 grudnia wypada w sobotę, więc nie zmniejsza liczby dni roboczych). Kurs franka z tabeli NBP z 2 października: 4,6942 zł. Całość wykonała się w 0,36 sekundy.

Krok 4: MCP Inspector (3 minuty)

MCP Inspector to oficjalne narzędzie do podglądania serwerów. Uruchamiasz je jedną komendą: npx @modelcontextprotocol/inspector python 05_serwer_mcp.py. W konsoli pojawia się adres z jednorazowym tokenem (http://127.0.0.1:6274?MCP_INSPECTOR_API_TOKEN=...). Po otwarciu włączasz przełącznik przy serwerze, a Inspector pokazuje listę narzędzi i log całej rozmowy w protokole (initialize, tools/list, tools/call).

MCP Inspector 2.9.0 po połączeniu z moim serwerem: trzy narzędzia po lewej, formularz narzędzia dni_robocze wygenerowany z sygnatury funkcji, po prawej log protokołu.
MCP Inspector 2.9.0 po połączeniu z moim serwerem: trzy narzędzia po lewej, formularz narzędzia dni_robocze wygenerowany z sygnatury funkcji, po prawej log protokołu.
Wynik wywołania dni_robocze dla listopada 2026: 20 dni roboczych, święta 1 i 11 listopada. W logu po prawej widać wywołanie tools/call trwające 20 ms.
Wynik wywołania dni_robocze dla listopada 2026: 20 dni roboczych, święta 1 i 11 listopada. W logu po prawej widać wywołanie tools/call trwające 20 ms.

Inspector ma też tryb bez przeglądarki, przydatny w skryptach i testach automatycznych:

> npx @modelcontextprotocol/inspector --cli python 05_serwer_mcp.py --method tools/call --tool-name dni_robocze --tool-arg od=2026-11-01 --tool-arg do=2026-11-30
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"od\": \"2026-11-01\",\n  \"do\": \"2026-11-30\",\n  \"dni_robocze\": 20,\n  \"swieta_w_okresie\": [\n    \"2026-11-01\",\n    \"2026-11-11\"\n  ]\n}"
    }
  ],
  "isError": false
}

Listopad 2026 ma 20 dni roboczych: 1 listopada wypada w niedzielę, a 11 listopada w środę.

Krok 5: podłączenie do Claude Code (4 minuty)

Nie przepłacaj za te subskrypcje

Prowadzę sklep z rocznymi dostępami do narzędzi AI - te same konta, o których piszę wyżej, tylko taniej niż w cenniku producenta.

Zobacz, co jest dostępne

Na stałe dodajesz serwer jednym poleceniem (zakres użytkownika albo projektu):

claude mcp add polskie-narzedzia -- python C:\sciezka\do\05_serwer_mcp.py
claude mcp list

Ja nie chciałem zmieniać konfiguracji Claude Code na tym komputerze, więc przekazałem serwer jednorazowo plikiem JSON (--mcp-config, z --strict-mcp-config, żeby nie mieszać go z innymi serwerami) w trybie bez okna (-p):

{"mcpServers": {"polskie-narzedzia": {
  "command": "C:/.../.venv/Scripts/python.exe",
  "args": ["C:/.../05_serwer_mcp.py"],
  "env": {"PYTHONUTF8": "1"}}}}

Przebieg z 4 października (model Claude Haiku 4.5):

> claude -p --mcp-config mcp_cfg.json --strict-mcp-config --model anthropic/claude-haiku-4.5 "Mam fakturę na 120 EUR z terminem płatności 14 dni roboczych od 2026-11-02. Podaj kwotę w złotych po aktualnym kursie NBP i sprawdź, ile dni roboczych jest w listopadzie 2026. Użyj narzędzi MCP."

[init] serwery MCP: polskie-narzedzia (connected)
[Claude] Sprawdzę kurs EUR i dni robocze w listopadzie.
[narzędzie] mcp__polskie-narzedzia__kurs_nbp {"waluta": "EUR"}
[wynik] {"waluta": "EUR", "kurs_pln": 4.3745, "data_tabeli": "2026-10-02", "tabela": "192/A/NBP/2026"}
[narzędzie] mcp__polskie-narzedzia__dni_robocze {"od": "2026-11-01", "do": "2026-11-30"}
[wynik] {"od": "2026-11-01", "do": "2026-11-30", "dni_robocze": 20, "swieta_w_okresie": ["2026-11-01", "2026-11-11"]}
[narzędzie] mcp__polskie-narzedzia__dni_robocze {"od": "2026-11-02", "do": "2026-12-31"}
[wynik] {"od": "2026-11-02", "do": "2026-12-31", "dni_robocze": 41, "swieta_w_okresie": ["2026-11-11", "2026-12-24", "2026-12-25", "2026-12-26"]}
[Claude] Mam już kurs i dni robocze w listopadzie. Teraz sprawdzę dokładny termin płatności - 14 dni roboczych od 2026-11-02:
[narzędzie] mcp__polskie-narzedzia__dni_robocze {"od": "2026-11-02", "do": "2026-11-24"}
[wynik] {"od": "2026-11-02", "do": "2026-11-24", "dni_robocze": 16, "swieta_w_okresie": ["2026-11-11"]}
[narzędzie] mcp__polskie-narzedzia__dni_robocze {"od": "2026-11-02", "do": "2026-11-20"}
[wynik] {"od": "2026-11-02", "do": "2026-11-20", "dni_robocze": 14, "swieta_w_okresie": ["2026-11-11"]}
[Claude] Oto wyniki:

**Przeliczenie na złote:**
- Kurs EUR z tabeli NBP 192/A/2026 (z dnia 2026-10-02): **4,3745 PLN/EUR**
- 120 EUR × 4,3745 = **524,94 PLN**

**Dni robocze w listopadzie 2026:** **20 dni roboczych**
(Uwzględniając wolne: 1 listopada - Wszystkich Świętych i 11 listopada - Święto Niepodległości)

**Termin płatności:**
- Od: 2 listopada 2026
- 14 dni roboczych = do **20 listopada 2026** (piątek)

Faktura powinna być zapłacona najpóźniej 20 listopada 2026 roku w kwocie **524,94 PLN**.

(tur: 6, czas: 27.2 s)

Claude sam wymyślił, jak policzyć termin płatności narzędziem, które umie tylko liczyć dni robocze w przedziale: zgadywał datę końcową, aż wyszło 14 (najpierw do 24, potem do 20 listopada). Wynik jest poprawny: 2-6 listopada to 5 dni, 9-13 listopada to 4 dni (bez 11.11), 16-20 listopada to 5 dni. To dobry przykład, jak model korzysta z narzędzi kreatywnie, ale też podpowiedź, że brakuje mi narzędzia dodaj_dni_robocze(od, ile). Dopisanie go to 5 linii.

Ważne przy podłączaniu na Windows:

  • w konfiguracji podawaj pełną ścieżkę do python.exe z venv, inaczej klient uruchomi systemowego Pythona bez zainstalowanego mcp;
  • dodaj PYTHONUTF8=1, żeby polskie znaki w wynikach nie zamieniały się w krzaczki;
  • serwer w trybie stdio nie może pisać nic na standardowe wyjście (żadnych print), bo to kanał protokołu. Logi kieruj na stderr albo do pliku.

Gdzie jeszcze zadziała ten sam serwer

KlientJak dodać serwer
Claude Codeclaude mcp add nazwa -- polecenie albo plik .mcp.json w projekcie
Claude DesktopUstawienia, sekcja deweloperska, plik claude_desktop_config.json (ten sam format mcpServers)
Cursor, VS Code, Windsurfplik konfiguracyjny MCP w ustawieniach edytora, format jak wyżej
Własny agentOpenAI Agents SDK, Claude Agent SDK i LangGraph mają klientów MCP. Opis w tekście Frameworki agentów AI
Zdalnie przez HTTPmcp.run(transport="streamable-http"), serwer nasłuchuje pod adresem /mcp

Bezpieczeństwo serwerów MCP

  • Serwer działa z Twoimi uprawnieniami. Narzędzie „czytaj plik” bez ograniczenia ścieżki to dostęp do całego dysku. U mnie wyszukiwanie widzi tylko folder dane/.
  • Gotowe serwery z internetu instaluj tylko z zaufanych źródeł i czytaj ich kod. Złośliwy serwer może w opisie narzędzia przemycić polecenia dla modelu.
  • Narzędzia, które piszą, wysyłają albo płacą, oznacz jako wymagające potwierdzenia. Claude Code domyślnie pyta o zgodę przy każdym nowym narzędziu.
  • Serwera HTTP nie wystawiaj publicznie bez uwierzytelniania. SDK obsługuje OAuth.

Najczęstsze pytania

Co to jest serwer MCP?

Program, który udostępnia narzędzia, dane i szablony poleceń w standardzie Model Context Protocol. Klient (np. Claude Code) łączy się z nim i przekazuje te narzędzia modelowi.

Czy do serwera MCP potrzebny jest klucz API?

Do samego serwera nie. Mój serwer nie płaci za nic: kurs bierze z darmowego API NBP, resztę liczy lokalnie. Płacisz tylko za model w kliencie, który z serwera korzysta.

Python czy TypeScript do serwera MCP?

Oba SDK są oficjalne i równorzędne. Wybierz język, który znasz. W Pythonie najmniej kodu daje MCPServer z dekoratorami.

Czym się różni MCP od zwykłego API?

API wymaga, żeby każda aplikacja nauczyła się jego formatu. MCP odwraca to: serwer sam opisuje swoje narzędzia w standardowym formacie, a każdy zgodny klient umie z nich korzystać bez dodatkowego kodu.

Czy MCP działa z ChatGPT i Gemini?

Standard przyjęły wszystkie duże firmy, a OpenAI Agents SDK i Google ADK mają wbudowanych klientów MCP. Szczegóły podłączania w aplikacjach czatowych zmieniają się często, więc sprawdzaj dokumentację konkretnej aplikacji.

Jak debugować serwer MCP, który nie działa?

Najpierw testuj klientem z Pythona albo Inspectorem w trybie --cli. Jeśli tam działa, a w Claude Code nie, prawie zawsze winna jest ścieżka do Pythona albo print na standardowe wyjście.

Google · Twoje źródłaPromptowy wyżej w Twoim Google - jednym kliknięciemDodaj do preferowanych źródeł →

Źródła i data sprawdzenia

// Newsletter

Cały tydzień w AI, w jednym mailu

Wybrane premiery, narzędzia i analizy. Raz w tygodniu, prosto do skrzynki.

Zapisz się za darmo →
Za darmo. Wypisujesz się jednym kliknięciem.
// czytaj też

Podobne tematy na Promptowym

Piotr Olszewski

Piotr Olszewski

AUTOR I WYDAWCA

Piotr Olszewski - twórca i autor Promptowego, polskiego serwisu o sztucznej inteligencji. Codziennie śledzi premiery modeli, narzędzia i regulacje AI, i tłumaczy je prostym, konkretnym językiem.

// mapa strony

🛒 Sklep Kinetyka Google AI Gemini Pro 170 zł CapCut Pro 460 zł/rok Lovable Pro 400 zł/rok Zobacz wszystko →
promptowy w liczbach 0tekstów w archiwum0newsów z ostatnich 7 dni0modeli wideo w obserwatorium0zagadek w grach
× ‹ powiększenie ›