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).
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.
Anbieter-Lock-in: OpenAI Function Calling und Claude Tool Use nutzen unterschiedliche Formate — jeder Wechsel erfordert eine neue Adapter-Schicht.
Tools nicht auffindbar: REST-APIs hängen an statischen Docs; KI kann zur Laufzeit kein tools/list aufrufen, um Fähigkeiten selbst zu entdecken.
IDE-Silos: Cursor, VS Code-Erweiterungen und JetBrains-Plugins definieren Tools jeweils anders — Sie pflegen N×M-Integrationen.
Kontext und Daten getrennt: LLMs lesen Konfiguration, Nutzerprofile oder Live-Logs nicht zuverlässig — standardisierte Nur-Lese-Resources sind nötig.
Prompt-Vorlagen verstreut: Code Review und Incident-Reports haben kein zentrales Register; Teams kopieren unabhängig.
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.“
Evolution: Function Calling (2023) → ChatGPT Plugins → MCP (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.
Kommunikation über JSON-RPC 2.0: initialize → tools/list / tools/call → resources/read. Zwei Transport-Lebenszyklen:
Vollständige Spezifikation: modelcontextprotocol.io.
| Dimension | MCP | OpenAI Function Calling | LangChain Tools |
|---|---|---|---|
| Offenheit | Anbieterübergreifendes offenes Protokoll, AAIF-Governance | An OpenAI API gebunden | Framework-Abstraktion, kein Transportstandard |
| Discovery | Laufzeit-tools/list | Inline-functions-Array in Request | Code-Registrierung, kein Standard-Discovery |
| Nur-Lese-Daten | Resources + URI-Schema | Kein gleichwertiges First-Class-Feature | Retriever-Konzept, nicht Protokollebene |
| Prompt-Vorlagen | Prompts-Standardinterface | Keine | PromptTemplate-Klasse |
| Transport | stdio / HTTP+SSE / Streamable HTTP | HTTPS-API gebündelt | Abhängig vom Agent-Runtime |
| Wiederverwendung | Ein Server für Cursor + Claude + Gemini | Nur OpenAI-Ökosystem | Framework-übergreifend Neuimplementierung |
Zwei Hauptrouten: Python mcp + FastMCP (daten-/skriptfreundlich) und TypeScript @modelcontextprotocol/sdk (Web/API-Integration, Typsicherheit). SDK-Repos: python-sdk, typescript-sdk.
# 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
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
Stack wählen: Daten-/ML-Teams bevorzugen Python; Node-Fullstack-Teams TypeScript.
Virtuelle Umgebung und Dependency-Lock: pip freeze oder package-lock.json, um Schema-Drift zu vermeiden.
MCP Inspector installieren: npx @modelcontextprotocol/inspector für visuelles JSON-RPC-Debugging.
Claude Desktop konfigurieren: ~/Library/Application Support/Claude/claude_desktop_config.json bearbeiten und Server command/args hinzufügen.
Cursor konfigurieren: Settings → MCP → Add Server; für stdio python -m src.server oder absoluten Pfad.
Inspector-Verbindung prüfen: Server starten → Inspector verbinden → tools/list liefert nicht-leere Liste.
// Cursor / Claude Desktop MCP-Konfiguration
{
"mcpServers": {
"my-tools": {
"command": "python",
"args": ["-m", "src.server"],
"env": { "API_KEY": "your-key" }
}
}
}
Mit FastMCP ein say_hello-Tool bauen und die Kette validieren: Code → Inspector → Cursor.
# 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)
# 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.
Hinweis: FastMCP generiert JSON Schema automatisch aus Docstrings und Typannotationen — keine handgeschriebenen Parameterbeschreibungen nötig.
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.
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)
ast.literal_eval; niemals exec.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()
raise ValueError("human-readable msg"); Client gibt Message an LLM zurück.retryable; Berechtigungsverweigerung sofort fail.idempotency_key, um doppelte Agent-Aufrufe zu vermeiden.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://.
@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))
| MIME-Typ | Einsatz | Beispiel |
|---|---|---|
| text/plain | Logs, README | file://logs/app.log |
| application/json | Konfiguration, API-Antworten | config://env |
| application/octet-stream | Binär (base64) | PDF-Zusammenfassung |
| text/event-stream | Live-Subscription | Log-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).
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.
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.
| Dimension | stdio | HTTP + SSE / Streamable HTTP |
|---|---|---|
| Deployment | Lokaler Kindprozess, Host-gestartet | Eigenständiger Dienst, URL-Verbindung |
| Skalierung | Einzelmaschine, schwer horizontal | Load Balancing, mehrere Replikate |
| Auth | Host-Umgebungsvariablen | Bearer Token / API Key / mTLS |
| Debugging | Inspector-Direktverbindung | curl + SSE-Client |
| Einsatz | Persönliche Entwicklung, lokales Cursor | Team-Sharing, SaaS-Integration |
# 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).
Warnung: HTTP-MCP niemals ohne Auth ins öffentliche Internet — 2026 sind viele Server noch unauthentifiziert exponiert. Auth und IP-Beschränkung sind Pflicht.
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.
# 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
| Symptom | Ursache | Fix |
|---|---|---|
| Server endet sofort nach Start | stdout durch print verunreinigt | Logs nach stderr; kein print auf stdout |
| tools/list leer | Decorator nicht registriert oder Import-Reihenfolge | @mcp.tool() vor run() ausführen |
| Cursor zeigt disconnected | Falscher command-Pfad oder venv nicht aktiv | Absolute Pfade; vollständigen python-Pfad in Config |
| JSON-RPC parse error | Nicht-JSON auf stdio | Debug-Banner aus; Log-Level WARNING+ |
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.
protocolVersion bei initialize — Server sollte kompatible Range declarieren./metrics (Tool-QPS, P99-Latenz); Sentry für unbehandelte Exceptions; /health für K8s-Liveness.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.
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.
Offizielle und Community-Server sind einsatzbereit — nicht alles neu bauen:
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.
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.
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.