MCP Server von Grund auf entwickeln
Vollständiger Entwicklerleitfaden

Wenn Claude / GPT / Cursor nur chatten, aber keine Datenbanken abfragen, Dateien lesen oder APIs aufrufen können — fehlt nicht ein längerer Prompt, sondern eine wiederverwendbare Tool-Schicht. Dieser Leitfaden richtet sich an Backend- und Fullstack-Entwickler: von Hello World bis zum ChromaDB-Wissensbasis-MCP Server, mit Tools / Resources / Prompts, stdio und HTTP+SSE, Debugging, Tests und Docker-Produktionsdeployment. Nach dem Lesen haben Sie eigene Tools in Cursor und einen klaren Pfad für 7×24-Betrieb auf einem dedizierten Remote-Mac (Protokoll-Hintergrund: MCP-Protokoll-Leitfaden).

01

Warum KI einen MCP Server braucht: Ein LLM ohne Tools ist nur ein redendes Gehirn

Große Modelle haben Trainings-Stichtage und erreichen Ihr CRM, Git-Repository oder interne APIs nicht. Vor 2024 schrieben Sie Function Calling für Claude, Plugins für GPT und ein anderes Format für Cursor — Modellwechsel = Neuanfang. Ein MCP Server kapselt Tool-Fähigkeiten in einem eigenen Prozess: einmal schreiben, nutzen in Claude Desktop, Cursor und Gemini.

Typische Szenarien: Postgres-Verkaufsdaten aus Claude Desktop abfragen; Cursor-Agent liest Projekt-Docs und ändert Code; GPT ruft Ihr Ticketsystem per HTTP-MCP auf — alles über denselben Server.

Was dieser Leitfaden liefert: nicht nur Konzept, sondern den Pfad von say_hello bis zum produktionsreifen Wissensbasis-Server mit Vektorsuche. Zielgruppe: Entwickler mit Python- oder TypeScript-Basis, die KI in IDE oder Desktop erweitern wollen.

Sechs Pain Points: Warum API-Wrapper allein nicht reichen

  1. 01

    Anbieter-Lock-in: OpenAI Function Calling und Claude Tool Use nutzen unterschiedliche Formate — jeder Wechsel erfordert eine neue Adapter-Schicht.

  2. 02

    Tools nicht auffindbar: REST-APIs hängen an statischen Docs; KI kann zur Laufzeit kein tools/list aufrufen, um Fähigkeiten selbst zu entdecken.

  3. 03

    IDE-Silos: Cursor, VS Code-Erweiterungen und JetBrains-Plugins definieren Tools jeweils anders — Sie pflegen N×M-Integrationen.

  4. 04

    Kontext und Daten getrennt: LLMs lesen Konfiguration, Nutzerprofile oder Live-Logs nicht zuverlässig — standardisierte Nur-Lese-Resources sind nötig.

  5. 05

    Prompt-Vorlagen verstreut: Code Review und Incident-Reports haben kein zentrales Register; Teams kopieren unabhängig.

  6. 06

    Lokal vs. Remote chaotisch: stdio-Kindprozesse passen zur Entwicklung; Produktions-HTTP-Gateways, Auth und Monitoring fehlen oft ein gemeinsames Muster (siehe stdio-Subprozess-Management).

„Einen MCP Server an KI anzuschließen ist wie IDE-Plugins für Entwickler — die Fähigkeitsgrenze springt von Chat zu Operationen in der realen Welt.“

02

Was ist MCP: Von Function Calling zum offenen Protokoll

Evolution: Function Calling (2023)ChatGPT PluginsMCP (Nov. 2024, Anthropic Open Source). Anthropic entwarf MCP als „USB-C“ zwischen KI und Außenwelt: Der Host (Cursor / Claude Desktop) enthält einen MCP Client und öffnet eine 1:1-Sitzung mit Ihrem MCP Server.

Architektur: Client / Server und drei Fähigkeiten

  • Tools: aufrufbare Operationen mit Seiteneffekten — Datenbankabfragen, Dateischreiben, HTTP-Requests.
  • Resources: Nur-Lese-Kontext — Konfiguration, Doc-Snippets, Nutzerprofile, per URI adressiert.
  • Prompts: vorgefertigte mehrstufige Dialog-Skelette — Code Review, Incident-Postmortem.

Kommunikation über JSON-RPC 2.0: initializetools/list / tools/callresources/read. Zwei Transport-Lebenszyklen:

  • stdio: Host startet Server als Kindprozess; stdin/stdout tragen JSON-RPC; Sitzung endet beim Prozessende.
  • HTTP + SSE: Client verbindet zu Remote-URL; Server pusht Event-Stream — geeignet für Team-Sharing und horizontale Skalierung.

Vollständige Spezifikation: modelcontextprotocol.io.

MCP vs OpenAI FC vs LangChain Tools

DimensionMCPOpenAI Function CallingLangChain Tools
OffenheitAnbieterübergreifendes offenes Protokoll, AAIF-GovernanceAn OpenAI API gebundenFramework-Abstraktion, kein Transportstandard
DiscoveryLaufzeit-tools/listInline-functions-Array in RequestCode-Registrierung, kein Standard-Discovery
Nur-Lese-DatenResources + URI-SchemaKein gleichwertiges First-Class-FeatureRetriever-Konzept, nicht Protokollebene
Prompt-VorlagenPrompts-StandardinterfaceKeinePromptTemplate-Klasse
Transportstdio / HTTP+SSE / Streamable HTTPHTTPS-API gebündeltAbhängig vom Agent-Runtime
WiederverwendungEin Server für Cursor + Claude + GeminiNur OpenAI-ÖkosystemFramework-übergreifend Neuimplementierung
03

Entwicklungsumgebung: Python FastMCP vs TypeScript SDK

Zwei Hauptrouten: Python mcp + FastMCP (daten-/skriptfreundlich) und TypeScript @modelcontextprotocol/sdk (Web/API-Integration, Typsicherheit). SDK-Repos: python-sdk, typescript-sdk.

bash
# Python-Route
python -m venv .venv && source .venv/bin/activate
pip install "mcp[cli]" httpx pydantic

# TypeScript-Route
npm init -y && npm install @modelcontextprotocol/sdk zod
npm install -D typescript tsx @types/node

Empfohlene Projektstruktur

tree
my-mcp-server/
├── pyproject.toml          # oder package.json
├── src/
│   ├── server.py           # FastMCP-Einstieg
│   ├── tools/              # Tool-Module
│   ├── resources/          # Resource-Provider
│   └── prompts/            # Prompt-Vorlagen
├── tests/
│   └── test_tools.py       # pytest + ClientSession
├── Dockerfile
└── README.md

Sechs-Schritte-Umgebungs-Checkliste

  1. 01

    Stack wählen: Daten-/ML-Teams bevorzugen Python; Node-Fullstack-Teams TypeScript.

  2. 02

    Virtuelle Umgebung und Dependency-Lock: pip freeze oder package-lock.json, um Schema-Drift zu vermeiden.

  3. 03

    MCP Inspector installieren: npx @modelcontextprotocol/inspector für visuelles JSON-RPC-Debugging.

  4. 04

    Claude Desktop konfigurieren: ~/Library/Application Support/Claude/claude_desktop_config.json bearbeiten und Server command/args hinzufügen.

  5. 05

    Cursor konfigurieren: Settings → MCP → Add Server; für stdio python -m src.server oder absoluten Pfad.

  6. 06

    Inspector-Verbindung prüfen: Server starten → Inspector verbinden → tools/list liefert nicht-leere Liste.

json
// Cursor / Claude Desktop MCP-Konfiguration
{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["-m", "src.server"],
      "env": { "API_KEY": "your-key" }
    }
  }
}
04

Hello World: Ersten MCP Server in 30 Sekunden starten

Mit FastMCP ein say_hello-Tool bauen und die Kette validieren: Code → Inspector → Cursor.

python
# src/server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-server")

@mcp.tool()
def say_hello(name: str = "World") -> str:
    """Begrüßung für angegebenes Objekt"""
    return f"Hello, {name}! MCP is working."

if __name__ == "__main__":
    mcp.run()  # stdio-Transport (Standard)
bash
# Mit Inspector debuggen
npx @modelcontextprotocol/inspector python -m src.server

# Oder direkt per stdio starten
python -m src.server

Nach dem Hinzufügen desselben Commands in Cursor den Agent bitten: „Nutze say_hello, um NodeMini zu begrüßen.“ JSON-Ergebnis = Client ↔ Server-Handshake erfolgreich.

info

Hinweis: FastMCP generiert JSON Schema automatisch aus Docstrings und Typannotationen — keine handgeschriebenen Parameterbeschreibungen nötig.

05

Tools vertieft: Von Schema bis fünf produktionsreife Tools

Tools sind MCPs Kernfähigkeit: KI führt Seiteneffekt-Operationen per tools/call aus. Jedes Tool exponiert Name, Beschreibung und inputSchema; FastMCP nutzt Pydantic-Modelle zur Validierung.

python
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(..., description="Suchbegriff")
    limit: int = Field(10, ge=1, le=100, description="Max. Treffer")

@mcp.tool()
async def search_docs(params: SearchInput) -> str:
    """Suche in der Dokumentenbibliothek"""
    results = await index.search(params.query, params.limit)
    return json.dumps(results, ensure_ascii=False)

Fünf häufige Tool-Muster

  • calculator: sicheres eval oder ast.literal_eval; niemals exec.
  • file_read / file_write: Root-Verzeichnis-Whitelist gegen Path Traversal.
  • fetch_url (async): httpx mit Timeout und Domain-Whitelist.
  • db_query: Nur-Lese-SQL mit parametrisierten Queries; kein DDL.
  • get_current_time: ISO8601 mit Zeitzone gegen LLM-Zeit-Halluzination.
python
import httpx
from datetime import datetime, timezone

@mcp.tool()
async def fetch_url(url: str) -> str:
    """HTTP GET für URL-Inhalt (Domain-Whitelist)"""
    allowed = ("api.github.com", "nodemini.com")
    if not any(url.startswith(f"https://{d}") for d in allowed):
        raise ValueError(f"Domain not allowed: {url}")
    async with httpx.AsyncClient(timeout=10.0) as client:
        resp = await client.get(url)
        resp.raise_for_status()
        return resp.text[:8000]

@mcp.tool()
def get_current_time() -> str:
    """Aktuelle UTC-Zeit"""
    return datetime.now(timezone.utc).isoformat()

Fehlerbehandlung: Best Practices

  • Strukturierte Fehler: raise ValueError("human-readable msg"); Client gibt Message an LLM zurück.
  • Retryable vs. fatal trennen: Netzwerk-Timeout als retryable; Berechtigungsverweigerung sofort fail.
  • Logging und Redaktion: Tool-Name und Latenz loggen; keine vollständigen API-Keys oder PII — besonders relevant unter DSGVO.
  • Idempotenz: Schreiboperationen mit idempotency_key, um doppelte Agent-Aufrufe zu vermeiden.
06

Resources: Nur-Lese-Kontext und URI-Schemata

Tool vs. Resource: Tools haben Seiteneffekte und werden von KI aufgerufen; Resources sind Nur-Lese-Kontext, den der Host vor dem Dialog injiziert oder den KI per resources/read zieht. URI-Schemata sind frei definierbar — z. B. config://, user://, file://.

python
@mcp.resource("config://app/settings")
def app_settings() -> str:
    """Statische App-Konfiguration (text/plain)"""
    return open("config/settings.json").read()

@mcp.resource("user://{user_id}/profile")
def user_profile(user_id: str) -> str:
    """Dynamisches Nutzerprofil (application/json)"""
    return json.dumps(get_user(user_id))

Resource-Inhaltstypen

MIME-TypEinsatzBeispiel
text/plainLogs, READMEfile://logs/app.log
application/jsonKonfiguration, API-Antwortenconfig://env
application/octet-streamBinär (base64)PDF-Zusammenfassung
text/event-streamLive-SubscriptionLog-Tail, Metrics-Stream

Filesystem-Resource-Server-Muster: resources/list scannt Verzeichnisse, resources/read liest per URI, resources/subscribe beobachtet watchfiles-Änderungen und pusht Updates — ideal, um Codebase-Docs an Cursor-Agenten zu exponieren. Personenbezogene Daten in Resources nur mit Zugriffskontrolle und dokumentierter Verarbeitung (DSGVO).

07

Prompts: Wiederverwendbare mehrstufige Dialogvorlagen

Ein MCP-Prompt ist ein auf dem Server registriertes Dialog-Skelett. Der Client holt per prompts/get eine Message-Liste mit user / assistant und Parameter-Platzhaltern — Teams teilen Code Review und Incident-Workflows ohne pro-Nutzer-Prompt-Dateien.

python
from mcp.types import PromptMessage, TextContent

@mcp.prompt()
def code_review_prompt(language: str = "python") -> list[PromptMessage]:
    """Standardisiertes Code-Review-Mehrstufig-Template"""
    return [
        PromptMessage(role="user", content=TextContent(
            type="text",
            text=f"Du bist Senior-{language}-Entwickler. Prüfe den Diff nach Sicherheit, Performance und Lesbarkeit."
        )),
        PromptMessage(role="assistant", content=TextContent(
            type="text",
            text="Bitte Diff einfügen oder PR-Nummer nennen — ich liefere strukturiertes Review per CHECKLIST."
        )),
    ]

Mehrstufige Templates können Variablen nesten ({ticket_id}, {severity}). Der Server verwaltet Versionen; Client-Upgrade des Servers synchronisiert Review-Standards im Team.

08

HTTP-Transport: Von stdio zu Streamable HTTP in Produktion

DimensionstdioHTTP + SSE / Streamable HTTP
DeploymentLokaler Kindprozess, Host-gestartetEigenständiger Dienst, URL-Verbindung
SkalierungEinzelmaschine, schwer horizontalLoad Balancing, mehrere Replikate
AuthHost-UmgebungsvariablenBearer Token / API Key / mTLS
DebuggingInspector-Direktverbindungcurl + SSE-Client
EinsatzPersönliche Entwicklung, lokales CursorTeam-Sharing, SaaS-Integration
python
# Streamable HTTP (FastMCP 2026)
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("prod-server", host="0.0.0.0", port=8080)

# ... Tools registrieren ...

if __name__ == "__main__":
    mcp.run(transport="streamable-http")

Produktions-Pflichten: Bearer-Token-Validierung, CORS-Whitelist (nur eigene Host-Domains), Rate Limit (z. B. 100 req/min/IP), HTTPS am Reverse Proxy. Gateway-Ops: HTTP-Gateway-Management. Für EU-Workloads: Datenresidenz und Zugriffsprotokolle dokumentieren (DSGVO).

warning

Warnung: HTTP-MCP niemals ohne Auth ins öffentliche Internet — 2026 sind viele Server noch unauthentifiziert exponiert. Auth und IP-Beschränkung sind Pflicht.

09

Debugging und Tests: Inspector + pytest Unit-Tests

MCP Inspector ist der offizielle visuelle Debugger: per stdio oder URL verbinden, tools/list und tools/call manuell senden, JSON-RPC-Roundtrips prüfen — deutlich schneller als Cursor-Logs interpretieren.

python
# tests/test_tools.py
import pytest
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

@pytest.mark.asyncio
async def test_say_hello():
    params = StdioServerParameters(command="python", args=["-m", "src.server"])
    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("say_hello", {"name": "MCP"})
            assert "MCP" in result.content[0].text

Häufige Fehler: Referenz

SymptomUrsacheFix
Server endet sofort nach Startstdout durch print verunreinigtLogs nach stderr; kein print auf stdout
tools/list leerDecorator nicht registriert oder Import-Reihenfolge@mcp.tool() vor run() ausführen
Cursor zeigt disconnectedFalscher command-Pfad oder venv nicht aktivAbsolute Pfade; vollständigen python-Pfad in Config
JSON-RPC parse errorNicht-JSON auf stdioDebug-Banner aus; Log-Level WARNING+
10

Produktionsdeployment: Docker, Cloud-Plattformen und Observability

dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY src/ src/
EXPOSE 8080
HEALTHCHECK CMD curl -f http://localhost:8080/health || exit 1
CMD ["python", "-m", "src.server", "--transport", "streamable-http"]

Plattform-Auswahl: Railway / Render für schnelle Validierung; AWS ECS / GCP Cloud Run für Enterprise-Compliance und DSGVO-konforme Regionen; VPS + Docker Compose günstig, aber Patch-Management selbst.

Zitierfähige Produktionsparameter (EEAT)

  • Protokollversion: MCP-Spec 2025-03-26 führt Streamable HTTP ein; Client verhandelt protocolVersion bei initialize — Server sollte kompatible Range declarieren.
  • Ressourcen-Baseline: leichter Tool-Server ~128 MB RAM; ChromaDB-Vektorindex empfiehlt ≥2 GB RAM und SSD-Persistent Volume.
  • Observability-Stack: strukturierte JSON-Logs → Loki/CloudWatch; Prometheus /metrics (Tool-QPS, P99-Latenz); Sentry für unbehandelte Exceptions; /health für K8s-Liveness.
11

Praxisprojekt: ChromaDB-Wissensbasis MCP Server

Interne Wiki- und Markdown-Docs vektorisieren und index_document, search_knowledge und write_note als Tools exponieren — Cursor-Agent kann „erst Firmenwissen suchen, dann Code schreiben“.

Anforderungen: inkrementelle Indexierung (watchfiles auf docs/), semantische Top-K-Suche, optional Scratchpad-Schreiben.

python
import chromadb
from chromadb.utils.embedding_functions import SentenceTransformerEmbeddingFunction

client = chromadb.PersistentClient(path="./data/chroma")
collection = client.get_or_create_collection(
    "wiki", embedding_function=SentenceTransformerEmbeddingFunction()
)

@mcp.tool()
def search_knowledge(query: str, top_k: int = 5) -> str:
    """Semantische Suche in interner Wissensbasis"""
    hits = collection.query(query_texts=[query], n_results=top_k)
    return json.dumps(hits["documents"][0], ensure_ascii=False)

@mcp.tool()
def index_document(path: str) -> str:
    """Einzelne Markdown-Datei indexieren"""
    text = open(path).read()
    collection.upsert(ids=[path], documents=[text], metadatas=[{"path": path}])
    return f"Indexed: {path}"

Cursor-Demo-Query: „Suche in der Wissensbasis Docs zu MCP-HTTP-Deployment und fasse eine Drei-Schritte-Go-Live-Checkliste zusammen“ — Agent ruft zuerst search_knowledge auf. Größere Skalierung: Vektorstore auf Qdrant (Remote gRPC). Interne Dokumente nur auf isolierten Instanzen indexieren, wenn DSGVO oder Vertraulichkeit greifen.

12

Ökosystem, Trends 2026 und Lernpfad

Offizielle und Community-Server sind einsatzbereit — nicht alles neu bauen:

  • mcp-server-filesystem — sandboxed Datei-Lese/Schreib
  • mcp-server-github — PR/Issue-API
  • brave-search / postgres / slack — Suche, SQL, Team-Kollaboration

Trends 2026: MCP-Marketplaces, OAuth 2.1 Tool-Autorisierung auf der Spec-Roadmap, Streamable HTTP ersetzt schrittweise pure SSE. Lernpfad: ① Spec lesen → ② Hello World → ③ drei Tools → ④ Resource → ⑤ pytest → ⑥ Docker → ⑦ Cursor anbinden.

Zusammenfassung

Von say_hello bis ChromaDB-Wissensbasis: voller MCP-Server-Stack — Tools-Ausführung, Resources-Kontext, Prompts-Vorlagen, Dual-Transport, Tests und Produktions-Ops. Nächster Schritt: Community-Server forken oder Firmen-APIs als Team-Tool-Schicht wrappen.

Lokales stdio eignet sich für Experimente; mehrere parallele Server, persistente Vektorindizes und HTTP-Langverbindungen treiben 16-GB-Notebooks in häufigen Swap. Günstige Linux-VPS hosten macOS-spezifische Toolchains schlecht. Selbst gebaute HTTP-Gateways ohne Session-Affinität und Auth leiden oft unter Connection Leaks und unautorisierter Exposition — Langzeitstabilität bleibt unter Erwartung.

Teams, die MCP als Produktionsinfrastruktur betreiben und parallel Cursor-Agenten sowie iOS/macOS-CI fahren, hosten MCP Server auf einem dedizierten Cloud-Mac 7×24 — planbarer als lokales Notebook oder generische VM. Wer Anforderungen an stabile SSH-Langsession, Keychain-Isolation, planbare Bandbreite und — wo DSGVO greift — kontrollierte Verarbeitung auf dedizierten Instanzen hat, profitiert von exklusiver Hardware. NodeMini Mac-Mini-Cloud-Miete als MCP- und Agent-Ausführungsschicht: LLM wechseln, SSH-Knoten und Server-Config bleiben. Specs: Mietpreise; Onboarding: Hilfezentrum.

FAQ

Häufige Fragen

Python FastMCP ist der schnellste Einstieg für Daten- und Skript-Tools; TypeScript SDK bietet Typsicherheit und nahtlose Node-Integration. Beide sind vollständig protokollkompatibel. Für mehrere Server 7×24: Mietpreise für Remote-Mac-Konfigurationen.

Function Calling bindet an OpenAI; MCP ist ein offenes Protokoll über Claude, GPT, Gemini und Cursor mit Resources und Prompts. Hintergrund: MCP-Protokoll-Leitfaden.

Leichtes stdio läuft lokal; mehrere Server + Vektorstore + HTTP-Langverbindungen brauchen einen dedizierten Remote-Mac. Onboarding: Hilfezentrum; Ops: stdio-Subprozess-Management.