Eigene MCP-Server entwickeln
Claude
>_
Claude AI · Model Context Protocol · Tool Calling · Entwicklung
Eigene MCP-Server entwickeln
Tools, Resources und Prompts für Claude bauen und testen

Ein eigener MCP-Server verbindet Claude mit internen Systemen wie Projektdaten, Datenbanken oder APIs, ohne dass jedes Werkzeug einzeln in den Assistenten programmiert werden muss. Dieser Artikel zeigt den Aufbau eines minimalen Servers mit einem echten Tool, die Protokollstruktur aus Tools, Resources und Prompts sowie das lokale Testen vor der Anbindung.

18 Min. Lesezeit MCP · Tools · Resources · Prompts · stdio Claude Code · Python · TypeScript

1. Was das Model Context Protocol wirklich löst

Das Model Context Protocol (MCP) ist ein offener Standard von Anthropic, der beschreibt, wie ein KI-Assistent wie Claude strukturiert auf externe Werkzeuge, Datenquellen und Vorlagen zugreift. Vor MCP musste jede Integration individuell in einen Assistenten eingebaut werden: eine Anbindung an ein Ticketsystem, eine an eine interne Datenbank, eine weitere an ein Dateisystem. Jede dieser Integrationen kannte nur der jeweilige Client, und jede Änderung am Backend erforderte eine Anpassung im Assistenten selbst. MCP trennt diese Zuständigkeiten: Ein MCP-Server kapselt den Zugriff auf ein System und spricht ein einheitliches Protokoll, das jeder MCP-fähige Client, etwa Claude Code oder Claude Desktop, ohne Zusatzaufwand versteht.

Für Magento- und PHP-Entwickler bedeutet das konkret: Ein selbst geschriebener MCP-Server kann interne Projektdaten, etwa den Status von Deployment-Skripten, offene Tickets aus einem internen Tracker oder Konfigurationswerte aus einer Datenbank, gegenüber Claude zugänglich machen, ohne dass sensible Zugangsdaten oder Geschäftslogik in den Prompt-Kontext kopiert werden müssen. Der Assistent ruft stattdessen ein klar definiertes Tool auf, das serverseitig validiert, geloggt und mit Rechteverwaltung versehen werden kann. Das macht MCP zu einer Brücke zwischen generischer KI-Fähigkeit und projektspezifischem Wissen, die sauber getrennt bleibt.

2. Protokollarchitektur: Tools, Resources und Prompts

MCP definiert drei primitive Bausteine, die ein Server anbieten kann. Tools sind Funktionen mit klar definierten Eingabeparametern und einem JSON-Schema, die der Client, also das Sprachmodell, aktiv aufruft, um eine Aktion auszuführen oder Daten abzurufen. Ein Tool entspricht am ehesten einem klassischen Function-Call: Es hat Seiteneffekte oder liefert berechnete Ergebnisse. Resources hingegen sind passive, adressierbare Datenquellen, etwa eine Datei, ein Datenbankeintrag oder ein API-Endpunkt, die der Client lesen kann, ohne dass das Modell aktiv eine Aktion auslösen muss. Resources eignen sich für Kontext, der eher wie ein Dokument gelesen als wie eine Funktion aufgerufen wird.

Prompts sind vordefinierte, parametrisierbare Vorlagen für wiederkehrende Interaktionsmuster, die ein Nutzer explizit auswählen kann, etwa ein Prompt, der einen strukturierten Code-Review-Ablauf anstößt. Alle drei Bausteine werden über JSON-RPC 2.0 als Transportformat ausgetauscht, wobei der Server seine Fähigkeiten beim Verbindungsaufbau über eine Capability-Verhandlung ankündigt. Der Client fragt zunächst tools/list, resources/list und prompts/list ab, um zu erfahren, was der Server anbietet, bevor er einzelne Elemente mit tools/call oder resources/read tatsächlich nutzt. Diese explizite Verhandlung macht das Protokoll erweiterbar, ohne Breaking Changes zu erzwingen.

3. Projekt-Setup: Grundgerüst eines MCP-Servers

Für den Einstieg eignet sich das offizielle Python-SDK mcp, das mit dem Modul FastMCP ein deklaratives, decorator-basiertes API bereitstellt und den Boilerplate-Code für JSON-RPC-Handling, Capability-Verhandlung und Serialisierung vollständig übernimmt. Alternativ existiert ein äquivalentes TypeScript-SDK, das sich anbietet, wenn der Server ohnehin in einem Node.js-Kontext läuft, etwa neben einer bestehenden Express-Anwendung. Beide SDKs unterstützen als Transportmechanismus sowohl stdio, also die Kommunikation über Standard-Ein- und Ausgabe, als auch HTTP mit Server-Sent Events für entfernte Server.

Für lokale Entwicklungswerkzeuge, die von Claude Code oder Claude Desktop als Subprozess gestartet werden, ist stdio der pragmatische Standardfall: Der Client startet den Serverprozess, kommuniziert über die Pipes, und beendet ihn wieder, wenn die Sitzung endet. Es ist kein offener Netzwerkport nötig, was die Angriffsfläche für rein lokale Werkzeuge deutlich reduziert. Die Projektstruktur bleibt bewusst schlank: eine virtuelle Umgebung, eine pyproject.toml mit der Abhängigkeit mcp[cli], und eine einzelne Einstiegsdatei, die den Server instanziiert und beim Start blockierend auf eingehende Anfragen wartet.


# Project setup for a minimal MCP server using the Python SDK
mkdir project-mcp-server && cd project-mcp-server
python3 -m venv .venv
source .venv/bin/activate

# Install the official MCP SDK with CLI/dev tooling included
pip install "mcp[cli]"

# Create the entry point file
touch server.py

# Run the server locally over stdio for a first smoke test
python server.py

# Or use the built-in dev inspector (see section 7)
mcp dev server.py

4. Das erste Tool: interne Projektdaten abfragen

Das nützlichste Einstiegsbeispiel ist ein Tool, das echte interne Daten liefert, statt eine triviale Rechenoperation zu simulieren. Ein realistisches Szenario für ein Magento-Projekt: ein Tool get_deployment_status, das den Zustand des zuletzt ausgeführten Deploy-Skripts aus einer lokalen SQLite-Datenbank oder einer JSON-Logdatei ausliest und strukturiert zurückgibt. Entscheidend ist, dass jedes Tool eine präzise Typsignatur besitzt: Parameter werden über Python-Typannotationen definiert, aus denen FastMCP automatisch ein JSON-Schema generiert, das der Client vor dem Aufruf einsehen kann.

Die Docstring-Beschreibung eines Tools ist kein Kommentar zur Dokumentation, sondern Teil des Protokolls: Sie wird dem Sprachmodell als Entscheidungsgrundlage angezeigt, wann und wie das Tool aufgerufen werden soll. Eine präzise, knappe Beschreibung mit klaren Angaben zu Parametern und Rückgabewert reduziert Fehlaufrufe erheblich. Rückgabewerte sollten strukturierte Objekte sein, keine unformatierten Textblöcke, damit das Modell die Ergebnisse zuverlässig weiterverarbeiten kann.


# server.py - minimal MCP server exposing one real tool
from mcp.server.fastmcp import FastMCP
import sqlite3
from pathlib import Path

mcp = FastMCP("project-data-server")

DB_PATH = Path(__file__).parent / "deployments.db"


@mcp.tool()
def get_deployment_status(environment: str) -> dict:
    """Return the status of the most recent deployment for a given environment.

    Args:
        environment: Target environment name, e.g. "staging" or "production".

    Returns:
        A dict with keys: environment, status, timestamp, commit_hash.
    """
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    try:
        row = conn.execute(
            "SELECT status, timestamp, commit_hash FROM deployments "
            "WHERE environment = ? ORDER BY timestamp DESC LIMIT 1",
            (environment,),
        ).fetchone()
    finally:
        conn.close()

    if row is None:
        return {"environment": environment, "status": "unknown", "timestamp": None, "commit_hash": None}

    return {
        "environment": environment,
        "status": row["status"],
        "timestamp": row["timestamp"],
        "commit_hash": row["commit_hash"],
    }


if __name__ == "__main__":
    mcp.run(transport="stdio")

5. Resources: Kontext bereitstellen statt Funktionen aufrufen

Während Tools für aktive Aktionen gedacht sind, eignen sich Resources für Inhalte, die eher gelesen als berechnet werden. Ein typisches Beispiel: die aktuelle composer.json eines Projekts, ein Changelog, oder eine Übersicht aller registrierten Cronjobs. Resources werden über URIs adressiert, etwa project://changelog/latest, und können sowohl statisch als auch dynamisch mit Parametern in der URI-Vorlage definiert werden. Der Client kann eine Liste verfügbarer Resources abfragen und gezielt einzelne davon in den Kontext laden, ohne dass das Modell dafür ein Tool aufrufen muss.

Der praktische Unterschied zu einem Tool zeigt sich in der Nutzererfahrung: Resources können in Clients wie Claude Desktop explizit vom Nutzer ausgewählt und an eine Konversation angehängt werden, bevor das Modell überhaupt eine Anfrage stellt. Das eignet sich für Kontext, der fast immer relevant ist, etwa die Projektstruktur oder eine Konfigurationsübersicht, während Tools für punktuelle, bedarfsgesteuerte Abfragen wie eine Datenbanksuche gedacht sind. Beide Mechanismen ergänzen sich, statt sich zu ersetzen, und ein gut designter Server nutzt in der Regel beide.

6. Prompts: wiederverwendbare Interaktionsvorlagen

Ein Prompt im MCP-Sinne ist keine einzelne Textnachricht, sondern eine serverseitig definierte Vorlage, die Parameter entgegennimmt und daraus eine oder mehrere strukturierte Nachrichten generiert. Der Unterschied zu einem einfachen Copy-Paste-Textbaustein liegt darin, dass Prompts im Client als eigene, auswählbare Aktion erscheinen, etwa als Slash-Befehl oder Menüpunkt, und dabei typisierte Parameter erfragen können. Ein Server für ein Magento-Projekt könnte etwa einen Prompt review_deployment anbieten, der ein Environment als Parameter nimmt und daraus eine vorformulierte Analyseanfrage mit eingebetteten Kontextdaten baut.

Prompts sind besonders nützlich, um Teamwissen zu standardisieren: Statt dass jeder Entwickler eine eigene, leicht unterschiedliche Formulierung für eine wiederkehrende Aufgabe wie einen Security-Review oder eine Migrationsprüfung verwendet, liegt die Vorlage zentral im Server und wird versioniert wie jeder andere Code. Änderungen an der Vorlage wirken sich sofort auf alle Nutzer aus, ohne dass einzelne Prompt-Dateien in verschiedenen Editoren synchronisiert werden müssen. In der Praxis werden Prompts seltener genutzt als Tools, sind aber für standardisierte Workflows in Teams ein unterschätztes Werkzeug.


# Exposing a static and a dynamic (templated) resource, plus a reusable prompt template
import json
from pathlib import Path
from mcp.server.fastmcp.prompts import base

CHANGELOG_PATH = Path(__file__).parent / "CHANGELOG.md"


@mcp.resource("project://changelog/latest")
def read_changelog() -> str:
    """Return the full contents of the project changelog file."""
    return CHANGELOG_PATH.read_text(encoding="utf-8")


@mcp.resource("project://cronjobs/{environment}")
def read_cronjobs(environment: str) -> str:
    """Return the list of registered cronjobs for a given environment as JSON."""
    cronjobs_file = Path(__file__).parent / f"cronjobs-{environment}.json"
    if not cronjobs_file.exists():
        return json.dumps({"environment": environment, "jobs": []})
    return cronjobs_file.read_text(encoding="utf-8")


@mcp.prompt()
def review_deployment(environment: str) -> list[base.Message]:
    """Build a structured deployment review request for the given environment."""
    return [
        base.UserMessage(
            f"Please review the last deployment on '{environment}'. "
            f"Use the get_deployment_status tool to fetch the current state, "
            f"then flag any status other than 'success' and explain likely causes."
        )
    ]

7. Lokal testen mit dem MCP Inspector

Bevor ein MCP-Server an einen KI-Assistenten angebunden wird, lohnt sich ein Test mit dem offiziellen MCP Inspector, einem browserbasierten Debugging-Werkzeug, das direkt mit dem SDK ausgeliefert wird. Der Befehl mcp dev server.py startet den Server, öffnet eine lokale Weboberfläche und listet dort alle registrierten Tools, Resources und Prompts einzeln auf. Jedes Tool kann mit frei wählbaren Parametern manuell aufgerufen werden, die Antwort erscheint sofort im Browser inklusive vollständiger JSON-RPC-Nachricht. Das macht Fehler in der Typsignatur oder in der Serialisierung sichtbar, lange bevor ein Sprachmodell überhaupt beteiligt ist.

Diese Trennung ist wichtig: Ein Fehler, der beim Testen mit einem echten Assistenten auftritt, kann entweder am Server liegen, an einer unklaren Tool-Beschreibung, oder am Verhalten des Modells selbst. Der Inspector eliminiert die dritte Fehlerquelle vollständig, weil er Anfragen direkt und deterministisch stellt. Ergänzend empfiehlt sich ein einfacher Satz automatisierter Tests, der die Tool-Funktionen direkt als Python-Funktionen aufruft, unabhängig vom Protokoll-Layer, um Regressionen bei Änderungen an der Datenbankstruktur oder den Rückgabewerten frühzeitig zu erkennen.


# Launch the MCP Inspector against the local server for manual testing
mcp dev server.py
# Opens a local web UI, typically at http://localhost:6274

# List all exposed tools, resources and prompts via the CLI as well
mcp inspect server.py --list-tools
mcp inspect server.py --list-resources

# Call a tool directly with a JSON payload for scripted smoke tests
echo '{"environment": "staging"}' | mcp call server.py get_deployment_status

8. Anbindung an Claude Code und Claude Desktop

Ist der Server lokal getestet, erfolgt die Anbindung an Claude Code über eine einfache Konfigurationsdatei, die den Startbefehl und optionale Umgebungsvariablen definiert. Claude Code liest diese Konfiguration entweder aus einer projektspezifischen .mcp.json im Repository-Root oder aus der globalen Nutzerkonfiguration, je nachdem, ob der Server nur für ein Projekt oder für alle Sitzungen verfügbar sein soll. Nach dem Neustart der Sitzung erscheinen die vom Server bereitgestellten Tools automatisch in der Liste der verfügbaren Werkzeuge und können vom Modell wie jedes eingebaute Tool aufgerufen werden.

Bei Claude Desktop erfolgt die Konfiguration analog über eine JSON-Datei im Anwendungsverzeichnis, die pro Server einen Eintrag mit Befehl, Argumenten und Umgebungsvariablen enthält. Wichtig für beide Clients: Der Startbefehl muss exakt dem Befehl entsprechen, der beim lokalen Testen funktioniert hat, inklusive korrektem Pfad zur virtuellen Umgebung oder zum Node-Binary. Ein häufiger Stolperstein ist ein relativer Pfad, der beim manuellen Testen im Projektverzeichnis funktioniert, beim Start durch den Client aber fehlschlägt, weil der Client mit einem anderen Arbeitsverzeichnis startet. Absolute Pfade vermeiden dieses Problem zuverlässig.


{
  "mcpServers": {
    "project-data-server": {
      "command": "/absolute/path/to/project-mcp-server/.venv/bin/python",
      "args": ["/absolute/path/to/project-mcp-server/server.py"],
      "env": {
        "PROJECT_DB_PATH": "/absolute/path/to/project-mcp-server/deployments.db"
      }
    }
  }
}

9. Sicherheit, Fehlerbehandlung und Vergleich der Transportarten

Ein MCP-Server, der auf interne Systeme zugreift, sollte dieselben Sicherheitsprinzipien befolgen wie jede andere Schnittstelle mit Datenzugriff: Eingaben validieren, Rechte prüfen und niemals Rohdaten ungeprüft in Shell-Befehle oder SQL-Queries einsetzen. Da das Sprachmodell die Parameter für einen Tool-Aufruf generiert, sind sie im Prinzip nicht vertrauenswürdiger als Nutzereingaben aus einem Webformular. Parametrisierte Queries statt String-Konkatenation und eine strikte Whitelist erlaubter Werte, etwa für Environment-Namen, sind hier Pflicht, keine Kür.

Fehler sollten als strukturierte MCP-Fehlermeldungen zurückgegeben werden, nicht als rohe Exceptions oder Stack-Traces, damit das Modell eine verständliche Grundlage für eine Nutzerantwort hat. Bei der Wahl der Transportart gilt: stdio für lokale, vom Client selbst gestartete Werkzeuge, HTTP mit Server-Sent Events für Server, die zentral gehostet und von mehreren Nutzern gleichzeitig angesprochen werden. Die folgende Tabelle fasst die wichtigsten Unterschiede zusammen.

Kriterium Unsicher / ungeeignet Empfohlenes Pattern Vorteil
SQL-Parameter aus Tool-Input String-Konkatenation im Query Parametrisierte Queries Kein SQL-Injection-Risiko
Lokales Entwicklerwerkzeug HTTP-Server mit offenem Port stdio-Transport als Subprozess Keine Netzwerk-Angriffsfläche
Zentral gehosteter Server stdio über SSH-Tunnel erzwingen HTTP mit Server-Sent Events Mehrere Clients gleichzeitig
Fehlerrückgabe Roher Stack-Trace als Text Strukturierte MCP-Fehlermeldung Modell kann sinnvoll reagieren
Environment-Parameter Beliebiger Freitext akzeptiert Enum/Whitelist im JSON-Schema Ungültige Werte fallen früh auf

Diese Prinzipien gelten unabhängig davon, ob der Server intern für ein einzelnes Team oder als Teil eines größeren Produkts betrieben wird. Wer einen MCP-Server öffentlich oder für mehrere Teams bereitstellt, sollte zusätzlich Authentifizierung, Rate-Limiting und Audit-Logging einplanen, da jeder Tool-Aufruf faktisch eine autorisierte Aktion im Namen des jeweiligen Nutzers darstellt.

Mironsoft

Claude-Integration, MCP-Server-Entwicklung und KI-gestützte Entwicklungsworkflows

Eigene MCP-Server für euer Projekt entwickeln?

Wir bauen maßgeschneiderte MCP-Server, die Claude sicher an interne Systeme, Datenbanken und APIs anbinden, inklusive Rechteverwaltung, Fehlerbehandlung und Anbindung an Claude Code oder Claude Desktop.

MCP-Server-Entwicklung

Maßgeschneiderte Tools, Resources und Prompts für euren Tech-Stack

Sicherheits-Review

Validierung, Rechteverwaltung und Audit-Logging für bestehende Server

Team-Einführung

Claude Code und MCP-Workflows im Entwicklerteam etablieren

10. Zusammenfassung

Ein eigener MCP-Server löst ein konkretes Integrationsproblem: Claude erhält strukturierten, kontrollierten Zugriff auf interne Systeme, ohne dass jede Anbindung individuell in den Assistenten programmiert werden muss. Tools eignen sich für aktive Abfragen und Aktionen mit klarer Typsignatur, Resources für passiven, adressierbaren Kontext wie Dateien oder Konfigurationen, und Prompts für standardisierte, team-weite Interaktionsvorlagen. Das offizielle Python-SDK mit FastMCP reduziert den Boilerplate-Aufwand auf ein Minimum und macht den Einstieg mit wenigen Zeilen Code möglich.

Der MCP Inspector ist beim Testen unverzichtbar, weil er Server-Fehler von Modell-Verhalten trennt, bevor ein Assistent überhaupt beteiligt ist. Bei der Anbindung an Claude Code oder Claude Desktop entscheiden absolute Pfade und eine saubere Konfigurationsdatei über Erfolg oder frustrierendes Debugging. Sicherheitsprinzipien wie parametrisierte Queries, Whitelists und strukturierte Fehlerrückgaben gelten für MCP-Server genauso wie für jede andere Schnittstelle mit Datenzugriff, da Tool-Parameter letztlich vom Sprachmodell generiert und damit nicht per se vertrauenswürdig sind.

Eigene MCP-Server entwickeln - Das Wichtigste auf einen Blick

Drei Bausteine

Tools für Aktionen, Resources für passiven Kontext, Prompts für standardisierte Vorlagen. Alle über JSON-RPC 2.0 ausgetauscht.

SDK & Transport

Python-SDK mit FastMCP für schnellen Einstieg. stdio für lokale Werkzeuge, HTTP/SSE für zentral gehostete Server.

Lokal testen

mcp dev server.py startet den MCP Inspector - trennt Server-Fehler von Modellverhalten vor der echten Anbindung.

Sicherheit

Tool-Parameter wie Nutzereingaben behandeln: parametrisierte Queries, Whitelists, strukturierte Fehlermeldungen.

11. FAQ: Eigene MCP-Server entwickeln

1Was ist das Model Context Protocol in einem Satz?
Ein offener Standard von Anthropic für strukturierten Zugriff eines KI-Assistenten auf externe Tools, Resources und Prompts, ohne individuelle Integration in den Assistenten selbst.
2Unterschied zwischen Tool und Resource?
Tools sind aktiv aufgerufene Funktionen mit Seiteneffekten oder Berechnungen. Resources sind passive, adressierbare Datenquellen, die wie Dokumente gelesen werden.
3Welches SDK für den Einstieg?
Das offizielle Python-SDK mit FastMCP: decorator-basiert, übernimmt JSON-RPC und Capability-Verhandlung automatisch. Alternativ das TypeScript-SDK für Node.js.
4stdio oder HTTP als Transport?
stdio für lokale, vom Client gestartete Werkzeuge ohne offenen Port. HTTP mit Server-Sent Events für zentral gehostete Server mit mehreren Nutzern.
5Wie teste ich vor der Anbindung?
Mit mcp dev server.py und dem MCP Inspector im Browser: alle Tools/Resources/Prompts einzeln testbar, unabhängig vom Sprachmodell.
6Warum ist die Docstring-Beschreibung wichtig?
Sie ist Teil des Protokolls und zeigt dem Modell, wann und wie ein Tool aufgerufen werden soll. Präzise Beschreibungen reduzieren Fehlaufrufe deutlich.
7Anbindung an Claude Code?
Über .mcp.json im Projekt oder globale Konfiguration mit Startbefehl, Argumenten und Umgebungsvariablen. Absolute Pfade vermeiden Probleme mit dem Arbeitsverzeichnis.
8Sind Tool-Parameter vertrauenswürdig?
Nein, wie Nutzereingaben behandeln: parametrisierte Queries, Whitelists, strikte Validierung, da das Modell die Parameter generiert.
9Wofür eignen sich Prompts?
Für standardisierte, team-weite Interaktionsvorlagen wie Reviews oder Analysen, zentral versioniert im Server statt individuell in jedem Editor.
10Häufiger Fehler bei Claude Desktop?
Relative Pfade, die lokal funktionieren, aber beim Start durch den Client fehlschlagen. Absolute Pfade zu Interpreter und Skript verwenden.