Skip to content
BotServBotServ
MCPMCP-ServerModel Context ProtocolKI-AgentenLokale KI

Eigenen MCP-Server bauen

Einen eigenen MCP-Server für lokale KI-Agenten bauen. Protokoll, Tools, Transport, JSON-RPC und Best Practices.

S

schutzgeist

4 min read
Eigenen MCP-Server bauen

Eigenen MCP-Server bauen

Was dieser Artikel über das Bauen eines MCP-Servers behandelt

  • Was das Model Context Protocol (MCP) ist.
  • Wie ein MCP-Server aufgebaut ist.
  • Wie man Tools, Ressourcen und Prompts definiert.
  • Welche Transportarten es gibt.
  • Ein einfaches Beispiel in TypeScript und Python.
  • Best Practices und typische Stolpersteine.

Einleitung: Eigenen MCP-Server bauen

Das Model Context Protocol (MCP) ist ein offener Standard, um KI-Agenten mit externen Datenquellen und Werkzeugen zu verbinden. Ein MCP-Server stellt dabei Funktionen bereit, die ein MCP-Client aufrufen kann. Wer einen eigenen MCP-Server baut, kann firmenspezifische Datenbanken, APIs oder lokale Werkzeuge in KI-Workflows einbinden.

Dieser Artikel zeigt, wie man einen einfachen MCP-Server von Grund auf erstellt. Er richtet sich an Entwickler und Selbsthoster, die ihre eigenen Tools für Agenten zugänglich machen wollen.

Was ist MCP?

MCP definiert eine standardisierte Kommunikation zwischen einem MCP-Client und einem MCP-Server. Der Client ist typischerweise ein KI-Agent oder ein Chat-Interface. Der Server bietet:

  • Tools: Funktionen, die der Agent aufrufen kann.
  • Resources: Daten, die der Agent lesen kann.
  • Prompts: Vorlagen für bestimmte Aufgaben.
  • Sampling: Umgekehrte Anfragen vom Server an den Client.

Die Kommunikation läuft über JSON-RPC 2.0.

Wichtige Begriffe

  • MCP-Host: Anwendung, die einen MCP-Client enthält, zum Beispiel Claude Desktop oder ein Agenten-Framework.
  • MCP-Client: Kommuniziert mit einem oder mehreren MCP-Servern.
  • MCP-Server: Stellt Tools, Ressourcen und Prompts bereit.
  • Tool: Ausführbare Funktion mit Name, Beschreibung und JSON-Schema.
  • Resource: Adressierbare Datenquelle, zum Beispiel eine Datei oder Datenbanktabelle.
  • Transport: Kommunikationsweg, meist stdio oder Server-Sent Events über HTTP.
  • JSON-RPC: Leichtgewichtiges Protokoll für entfernte Prozeduraufrufe.

Transportarten

stdio

Der Server läuft als Unterprozess des Clients. Die Kommunikation erfolgt über Standard-Ein- und Ausgabe. Das ist besonders einfach für lokale Tools.

SSE über HTTP

Der Server läuft als eigener Dienst. Der Client verbindet sich über HTTP und empfängt Nachrichten via Server-Sent Events. Das eignet sich für entfernte oder mehrere Clients.

Aufbau eines MCP-Servers

Ein MCP-Server muss folgende Dinge bereitstellen:

  1. Initialisierung: Protokollversion und Fähigkeiten austauschen.
  2. Capabilities: Mitteilen, welche Tools, Ressourcen und Prompts verfügbar sind.
  3. Tool-Handler: Funktionen für jedes Tool ausführen.
  4. Resource-Handler: Ressourcen auf Anfrage zurückgeben.
  5. Fehlerbehandlung: Klare Fehlermeldungen an den Client senden.

Einfaches Beispiel in Python

Dieser Server bietet ein Tool get_current_time an, das die aktuelle Uhrzeit zurückgibt.

# server.py
import json
import sys
from datetime import datetime


def send_message(msg):
    payload = json.dumps(msg)
    print(payload, flush=True)


def handle_request(req):
    method = req.get("method")
    id_ = req.get("id")

    if method == "initialize":
        return {
            "jsonrpc": "2.0",
            "id": id_,
            "result": {
                "protocolVersion": "2024-11-05",
                "capabilities": {"tools": {}},
                "serverInfo": {"name": "time-server", "version": "1.0.0"},
            },
        }

    if method == "tools/list":
        return {
            "jsonrpc": "2.0",
            "id": id_,
            "result": {
                "tools": [
                    {
                        "name": "get_current_time",
                        "description": "Gibt die aktuelle Uhrzeit zurück.",
                        "inputSchema": {
                            "type": "object",
                            "properties": {},
                        },
                    }
                ]
            },
        }

    if method == "tools/call":
        name = req["params"]["name"]
        if name == "get_current_time":
            now = datetime.now().isoformat()
            return {
                "jsonrpc": "2.0",
                "id": id_,
                "result": {
                    "content": [{"type": "text", "text": f"Aktuelle Uhrzeit: {now}"}]
                },
            }
        return {"jsonrpc": "2.0", "id": id_, "error": {"code": -32601, "message": "Tool nicht gefunden"}}

    return {"jsonrpc": "2.0", "id": id_, "error": {"code": -32601, "message": "Methode nicht gefunden"}}


def main():
    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue
        req = json.loads(line)
        resp = handle_request(req)
        send_message(resp)


if __name__ == "__main__":
    main()

Der Server liest Zeile für Zeile JSON-RPC-Anfragen von stdin und schreibt Antworten nach stdout.

Einrichtung in Claude Desktop

Nach dem Bauen der Server-Datei kannst Du sie in Claude Desktop eintragen. Unter macOS liegt die Konfiguration in ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "time": {
      "command": "python3",
      "args": ["/pfad/zu/server.py"]
    }
  }
}

Nach einem Neustart von Claude Desktop steht das Tool get_current_time zur Verfügung.

MCP-SDKs

Statt alles von Hand zu bauen, kann man auf SDKs zurückgreifen:

  • Python SDK: mcp auf PyPI.
  • TypeScript SDK: @modelcontextprotocol/sdk auf npm.
  • Java SDK: mcp-java.

Diese SDKs kümmern sich um Protokollversionen, Transport und JSON-RPC-Details.

Best Practices

  • Klare Tool-Beschreibungen: Das Sprachmodell entscheidet anhand der Beschreibung, ob es ein Tool nutzt.
  • Sichere Eingabenvalidierung: Jedes Tool-Argument muss geprüft werden.
  • Fehlermeldungen: Gebe aussagekräftige Fehler zurück, damit der Agent reagieren kann.
  • Zustandslosigkeit: Tools sollten möglichst keinen versteckten Zustand haben.
  • Berechtigungen: Der Server darf nur Dinge tun, für die er berechtigt ist.
  • Logging: Ausgaben auf stderr, damit stdout sauber für JSON-RPC bleibt.

Typische Stolpersteine

  • Falsches JSON-RPC-Format: Fehlende jsonrpc oder id Felder.
  • Stdout verunreinigt: Debug-Ausgaben auf stdout statt stderr.
  • Fehlende Capabilities: Client weiß nicht, welche Tools verfügbar sind.
  • Unklare Tool-Beschreibungen: Modell ruft falsches Tool auf.
  • Keine Eingabevalidierung: Schadhafte Eingaben führen zu Fehlern.
  • Transport-Mix: stdio und HTTP nicht im selben Server vermischen.

FAQ: Eigenen MCP-Server bauen

Brauche ich ein spezielles Framework? Nein. Ein MCP-Server kann in jeder Sprache implementiert werden, die JSON-RPC spricht. SDKs erleichtern den Einstieg.

Kann ein MCP-Server mehrere Tools bieten? Ja. tools/list gibt ein Array mit allen Tools zurück.

Wie sicher ist ein MCP-Server? Er läuft lokal und führt nur aus, was im Code definiert ist. Trotzdem sollte jede Eingabe geprüft und Berechtigungen eingeschränkt werden.

Was ist der Unterschied zwischen stdio und SSE? stdio ist für lokale Prozesse einfacher, SSE eignet sich für Netzwerk- oder Container-Setups.

Kann ich einen MCP-Server in Docker laufen lassen? Ja. Dann empfiehlt sich SSE über HTTP oder ein Wrapper, der stdio für den Client bereitstellt.

Quellen und weiterführende Literatur

Zusammenfassung: Eigenen MCP-Server bauen

Ein eigener MCP-Server erweitert KI-Agenten um spezialisierte Tools und Datenquellen. Das Model Context Protocol basiert auf JSON-RPC und unterstützt stdio sowie HTTP-Transport. Wichtig sind klare Tool-Beschreibungen, sichere Eingabevalidierung, saubere Fehlerbehandlung und die Trennung von stdout und stderr. Wer das Protokoll versteht, kann firmenspezifische Funktionen sicher in lokale Agenten-Workflows integrieren.

Zurück zum KI Blog
Share:

Ähnliche Beiträge