Schnell MCP Server erstellen für Claude Code

Audrey Lopez

Audrey Lopez

12 June 2025

Schnell MCP Server erstellen für Claude Code

Das Model Context Protocol (MCP) revolutioniert die Interaktion von KI-Assistenten mit externen Tools und Datenquellen. Stellen Sie sich MCP als einen universellen USB-C-Anschluss für KI-Anwendungen vor – es bietet eine standardisierte Möglichkeit, Claude Code mit praktisch jeder erdenklichen Datenquelle, API oder jedem Tool zu verbinden. Dieser umfassende Leitfaden führt Sie Schritt für Schritt durch den Aufbau Ihres eigenen MCP-Servers, sodass Claude Code auf benutzerdefinierte Funktionen zugreifen kann, die seine Fähigkeiten weit über seine integrierten Features hinaus erweitern.

Ob Sie Datenbanken, APIs, Dateisysteme integrieren oder vollständig benutzerdefinierte Tools erstellen möchten, MCP bietet die Grundlage für grenzenlose Erweiterbarkeit. Am Ende dieses Tutorials werden Sie einen funktionierenden MCP-Server haben und verstehen, wie Sie ihn für jeden Anwendungsfall erweitern können.

💡
Sie suchen ein großartiges API-Test-Tool, das schöne API-Dokumentation generiert?

Sie möchten eine integrierte All-in-One-Plattform für Ihr Entwicklerteam, um mit maximaler Produktivität zusammenzuarbeiten?

Apidog erfüllt all Ihre Anforderungen und ersetzt Postman zu einem viel günstigeren Preis!
button

Was ist ein MCP-Server und warum spricht jeder darüber?

Was macht MCP anders?

MCP (Model Context Protocol) ist ein offenes Protokoll, das von Anthropic entwickelt wurde und es KI-Modellen ermöglicht, über eine standardisierte Schnittstelle mit externen Servern zu kommunizieren. Im Gegensatz zu traditionellen API-Integrationen, bei denen Sie spezifische Endpunkte fest codieren, bietet MCP eine strukturierte Möglichkeit für KI-Assistenten, externe Tools dynamisch zu entdecken, zu verstehen und zu nutzen.

Das Geniale an MCP liegt in seiner Entdeckbarkeit. Wenn Claude Code sich mit Ihrem MCP-Server verbindet, lernt es automatisch, welche Tools verfügbar sind, wie sie verwendet werden und welche Parameter sie akzeptieren. Das bedeutet, Sie können neue Funktionen hinzufügen, ohne Claude Code selbst aktualisieren zu müssen.

MCP-Architektur im Detail

Das Protokoll folgt einer Client-Server-Architektur mit klar definierten Rollen:

Erklärung des Kommunikationsflusses

Wenn Claude Code ein externes Tool verwenden muss, geschieht Folgendes:

  1. Erkennungsphase: Claude Code fragt Ihren Server nach verfügbaren Tools ab
  2. Schema-Validierung: Ihr Server antwortet mit Tool-Definitionen und Eingabeschemata
  3. Tool-Auswahl: Claude Code wählt geeignete Tools basierend auf Benutzeranfragen aus
  4. Ausführungsphase: Claude Code sendet Tool-Aufrufe mit validierten Parametern
  5. Ergebnisverarbeitung: Ihr Server verarbeitet die Anfrage und gibt strukturierte Ergebnisse zurück

Dieser Fluss gewährleistet Typsicherheit, ordnungsgemäße Fehlerbehandlung und konsistentes Verhalten über alle MCP-Integrationen hinweg.

Voraussetzungen und Umgebungseinrichtung

Analyse der Systemanforderungen

Bevor Sie Ihren MCP-Server erstellen, müssen Sie Ihre Entwicklungsumgebung verstehen und die richtigen Tools auswählen. MCP-Server können in mehreren Sprachen erstellt werden, aber Python und TypeScript werden am häufigsten mit umfangreichen Tools unterstützt.

Für die Python-Entwicklung:

Für die TypeScript/JavaScript-Entwicklung:

Kernabhängigkeiten:

Schritt-für-Schritt-Vorbereitung der Umgebung

1. Claude Code CLI installieren

Die Claude Code CLI ist Ihr primäres Tool zur Verwaltung von MCP-Servern. Installieren Sie sie global, um den Zugriff von jedem Verzeichnis aus zu gewährleisten:

# Install Claude Code globally
npm install -g @anthropic-ai/claude-code

Warum die globale Installation wichtig ist: Die globale Installation stellt sicher, dass der Befehl claude systemweit verfügbar ist, was Pfadprobleme beim Registrieren von MCP-Servern aus verschiedenen Verzeichnissen verhindert.

2. Installation überprüfen

Überprüfen Sie, ob Claude Code korrekt installiert und zugänglich ist:

# Verify installation and check version
claude --version

# Check available commands
claude --help

3. Kritische Ersteinrichtung der Berechtigungen

Dieser Schritt ist absolut essentiell und wird oft übersehen:

# Run initial setup with permissions bypass
claude --dangerously-skip-permissions

Was dieser Befehl tut:

Warum dies erforderlich ist: Ohne diesen Schritt können MCP-Server keine sicheren Verbindungen mit Claude Code herstellen, was zu Authentifizierungsfehlern und Verbindungs-Timeouts führt.

Sicherheitsaspekte: Das Flag --dangerously-skip-permissions ist für Entwicklungsumgebungen sicher, umgeht aber normale Sicherheitsabfragen. In Produktionsumgebungen überprüfen Sie jede Berechtigungsanfrage sorgfältig.

Kritische Konfiguration: Verständnis von MCP-Scopes

Warum Konfigurations-Scopes wichtig sind

Eine der häufigsten Fallstricke beim Aufbau von MCP-Servern ist die unsachgemäße Verwaltung des Konfigurations-Scopes. Das Verständnis von Scopes ist entscheidend, da sie bestimmen, wo und wann Ihr MCP-Server für Claude Code verfügbar ist. Viele Entwickler verbringen Stunden damit, "Server nicht gefunden"-Fehler zu debuggen, die auf eine Fehlkonfiguration des Scopes zurückzuführen sind.

Claude Code verwendet ein hierarchisches Konfigurationssystem, das Flexibilität bietet und gleichzeitig die Sicherheit gewährleistet. Jeder Scope dient einem spezifischen Zweck und hat unterschiedliche Anwendungsfälle.

Erklärung der Konfigurations-Scope-Hierarchie

1. Projekt-Scope (.mcp.json) - Höchste Priorität

Ort: Stammverzeichnis des Projekts in einer Datei namens .mcp.json

Zweck: Projektspezifische MCP-Server, die nur verfügbar sein sollen, wenn in diesem spezifischen Projekt gearbeitet wird

Anwendungsfall: Datenbankverbindungen, die spezifisch für ein Projekt sind, projektspezifische Linter oder benutzerdefinierte Build-Tools

Wann der Projekt-Scope angemessen ist:

2. Benutzer-Scope (-scope user) - Globale Konfiguration

Ort: Konfiguration im Home-Verzeichnis des Benutzers

Zweck: MCP-Server, die global über alle Projekte und Verzeichnisse hinweg verfügbar sind

Anwendungsfall: Allzweck-Tools wie Wetter-APIs, Rechner-Tools oder Systemdienstprogramme

Warum der Benutzer-Scope normalerweise bevorzugt wird:

3. Lokaler Scope (Standard) - Verzeichnis-spezifisch

Ort: Kontext des aktuellen Arbeitsverzeichnisses

Zweck: Schnelle, temporäre Einrichtung von MCP-Servern

Einschränkung: Funktioniert nur, wenn Sie Claude Code aus diesem spezifischen Verzeichnis ausführen

Häufige Konfigurationsfehler

❌ Falscher Ansatz (Lokaler Scope - eingeschränkte Funktionalität):

claude mcp add my-server python3 /path/to/server.py

Problem: Dieser Server funktioniert nur, wenn Sie sich in genau dem Verzeichnis befinden, in dem Sie ihn registriert haben.

✅ Korrekter Ansatz (Benutzer-Scope - globaler Zugriff):

claude mcp add --scope user my-server python3 /path/to/server.py

Vorteil: Dieser Server funktioniert von jedem Verzeichnis auf Ihrem System aus.

Strategische Verzeichnisplanung

Empfohlene Verzeichnisstruktur

Erstellen Sie eine gut organisierte Verzeichnisstruktur für langfristige Wartbarkeit:

# Create permanent storage location
mkdir -p ~/.claude-mcp-servers/

# Organize by functionality
mkdir -p ~/.claude-mcp-servers/apis/
mkdir -p ~/.claude-mcp-servers/utilities/
mkdir -p ~/.claude-mcp-servers/development/

Vorteile einer organisierten Struktur

Wartbarkeit: Einfaches Auffinden und Aktualisieren von Servern später

Sicherheit: Klare Trennung zwischen verschiedenen Tool-Typen

Backup: Einfaches Sichern aller MCP-Server durch Sichern eines Verzeichnisses

Teilen: Einfaches Teilen von Serverkonfigurationen mit Teammitgliedern

Leitfaden zur Fehlerbehebung bei Scopes

Diagnose von Scope-Problemen

Wenn Ihr MCP-Server nicht angezeigt wird, folgen Sie dieser Diagnose-Sequenz:

  1. Aktuelle Scope-Konfiguration überprüfen:
claude mcp list

  1. Überprüfen, ob Sie sich nicht in einem Verzeichnis mit widersprüchlichem Projekt-Scope befinden:
ls .mcp.json

  1. Von verschiedenen Verzeichnissen aus testen:
cd ~ && claude mcp list
cd /tmp && claude mcp list

Beheben von Scope-Problemen

Problem: Server funktioniert nur in einem Verzeichnis

Lösung: Lokale Konfiguration entfernen und mit Benutzer-Scope erneut hinzufügen

# Remove problematic local configuration
claude mcp remove my-server

# Re-add with global user scope
claude mcp add --scope user my-server python3 /path/to/server.py

Ihren ersten MCP-Server erstellen

Verständnis des Entwicklungsprozesses

Der Aufbau eines MCP-Servers erfordert das Verständnis sowohl des MCP-Protokolls als auch der spezifischen Anforderungen Ihres Anwendungsfalls. Wir beginnen mit einem einfachen "Hello World"-Server, um die Grundlagen zu verstehen, und bauen dann auf diesem Fundament auf.

Der Entwicklungsprozess folgt diesen Phasen:

  1. Einrichtung der Serverstruktur: Erstellen der grundlegenden Dateistruktur und des Einstiegspunkts
  2. Protokollimplementierung: Implementierung der erforderlichen MCP-Methoden
  3. Tool-Definition: Definieren, welche Tools Ihr Server bereitstellt
  4. Registrierung & Testen: Hinzufügen des Servers zu Claude Code und Überprüfung der Funktionalität
  5. Erweiterung & Produktion: Hinzufügen realer Funktionalität und Fehlerbehandlung

Schritt 1: Projektgrundlage und Struktur

Erstellen der Entwicklungsumgebung

Zuerst richten Sie eine geeignete Entwicklungsumgebung für Ihren MCP-Server ein:

# Navigate to your MCP servers directory
cd ~/.claude-mcp-servers/

# Create a new server project
mkdir my-first-server
cd my-first-server

# Initialize the project structure
touch server.py
touch requirements.txt
touch .env

Warum diese Struktur wichtig ist

Organisierte Entwicklung: Das Halten jedes Servers in seinem eigenen Verzeichnis verhindert Konflikte und erleichtert die Wartung.

Abhängigkeitsisolierung: Jeder Server kann seine eigenen Anforderungen haben, ohne andere zu beeinflussen.

Konfigurationsverwaltung: Umgebungsvariablen ermöglichen eine sichere Konfiguration ohne Hardcoding von Werten.

Verständnis der MCP-Serveranforderungen

Jeder MCP-Server muss drei Kern-JSON-RPC-Methoden implementieren:

  1. initialize: Stellt die Verbindung her und deklariert die Serverfähigkeiten
  2. tools/list: Gibt verfügbare Tools und deren Schemata zurück
  3. tools/call: Führt spezifische Tools mit bereitgestellten Parametern aus

Schritt 2: Implementierung des Kern-Server-Frameworks

Erstellen Sie eine Datei namens server.py mit der grundlegenden MCP-Servervorlage:

#!/usr/bin/env python3
"""
Custom MCP Server for Claude Code Integration
"""

import json
import sys
import os
from typing import Dict, Any, Optional

# Ensure unbuffered output for proper MCP communication
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)

def send_response(response: Dict[str, Any]):
    """Send a JSON-RPC response to Claude Code"""
    print(json.dumps(response), flush=True)

def handle_initialize(request_id: Any) -> Dict[str, Any]:
    """Handle MCP initialization handshake"""
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "protocolVersion": "2024-11-05",
            "capabilities": {
                "tools": {}
            },
            "serverInfo": {
                "name": "my-custom-server",
                "version": "1.0.0"
            }
        }
    }

def handle_tools_list(request_id: Any) -> Dict[str, Any]:
    """List available tools for Claude Code"""
    tools = [
        {
            "name": "hello_world",
            "description": "A simple demonstration tool",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name to greet"
                    }
                },
                "required": ["name"]
            }
        }
    ]

    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "tools": tools
        }
    }

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Execute tool calls from Claude Code"""
    tool_name = params.get("name")
    arguments = params.get("arguments", {})

    try:
        if tool_name == "hello_world":
            name = arguments.get("name", "World")
            result = f"Hello, {name}! Your MCP server is working perfectly."
        else:
            raise ValueError(f"Unknown tool: {tool_name}")

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "content": [
                    {
                        "type": "text",
                        "text": result
                    }
                ]
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {
                "code": -32603,
                "message": str(e)
            }
        }

def main():
    """Main server loop handling JSON-RPC communication"""
    while True:
        try:
            line = sys.stdin.readline()
            if not line:
                break

            request = json.loads(line.strip())
            method = request.get("method")
            request_id = request.get("id")
            params = request.get("params", {})

            if method == "initialize":
                response = handle_initialize(request_id)
            elif method == "tools/list":
                response = handle_tools_list(request_id)
            elif method == "tools/call":
                response = handle_tool_call(request_id, params)
            else:
                response = {
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32601,
                        "message": f"Method not found: {method}"
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32603,
                        "message": f"Internal error: {str(e)}"
                    }
                }

            send_response(response)

        except json.JSONDecodeError:
            continue
        except EOFError:
            break
        except Exception as e:
            if 'request_id' in locals():
                send_response({
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32603,
                        "message": f"Internal error: {str(e)}"
                    }
                })

if __name__ == "__main__":
    main()

Erklärung der Code-Architektur

Ein-/Ausgabe-Setup: Die ersten Zeilen konfigurieren ungepufferte E/A, was für die MCP-Kommunikation entscheidend ist. Gepufferte Ausgabe kann zu Verzögerungen bei der Nachrichtenübermittlung führen, die das Protokoll stören.

JSON-RPC-Behandlung: Die Hauptschleife liest JSON-RPC-Anfragen von stdin und schreibt Antworten nach stdout. Dies folgt der MCP-Spezifikation für die lokale Serverkommunikation.

Strategie zur Fehlerbehandlung: Der Code implementiert mehrere Ebenen der Fehlerbehandlung:

Protokollkonformität: Jede Antwort enthält das erforderliche Feld jsonrpc: "2.0" und die Anforderungs-ID zur korrekten Zuordnung.

Schritt 3: Servervorbereitung und Testen

Server ausführbar machen

# Make the server executable
chmod +x server.py

Warum ausführbare Berechtigungen wichtig sind: MCP-Server werden von Claude Code als Subprozess gestartet. Ohne Ausführungsberechtigungen schlägt der Start mit kryptischen Berechtigungsfehlern fehl.

Manuelles Protokolltesten

Testen Sie die Protokollimplementierung des Servers, bevor Sie ihn bei Claude Code registrieren:

# Test the initialize handshake
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py

Was zu erwarten ist: Sie sollten eine JSON-Antwort sehen, die die Protokollversion und die Fähigkeiten enthält. Wenn Sie Fehlermeldungen oder keine Ausgabe sehen, überprüfen Sie Ihre Python-Installation und die Skriptsyntax.

Validierungsschritte

Führen Sie diese Validierungsprüfungen durch, bevor Sie fortfahren:

  1. Syntaxprüfung: python3 -m py_compile server.py
  2. Importtest: python3 -c "import json, sys, os"
  3. Ausführungstest: Überprüfen Sie, ob der manuelle Protokolltest funktioniert

Schritt 4: Registrierung bei Claude Code

Ihren Server hinzufügen

Registrieren Sie Ihren Server mit dem richtigen Scope und absoluten Pfaden:

# Register with global user scope for universal access
claude mcp add --scope user my-first-server python3 ~/.claude-mcp-servers/my-first-server/server.py

Wichtige Details:

Überprüfung und Fehlerbehebung

# Verify registration
claude mcp list

# Check for any connection issues
claude mcp get my-first-server

Häufige Registrierungsprobleme:

Fortgeschrittenes Beispiel: Wetter-API-Integration

Über "Hello World" hinausgehen

Nachdem Sie nun die grundlegende Struktur eines MCP-Servers verstehen, erstellen wir einen praktischeren Server, der reale Integrationsmuster demonstriert. Dieser Wetter-API-Server wird Ihnen beibringen:

Planung Ihrer API-Integration

Bevor Sie Code schreiben, berücksichtigen Sie diese Integrationsaspekte:

API-Auswahl: Wir verwenden die OpenWeatherMap API wegen ihrer Einfachheit und des kostenlosen Tarifs

Datenfluss: Benutzeranfrage → Parametervalidierung → API-Aufruf → Antwortformatierung → Claude-Antwort

Fehlerszenarien: Netzwerkfehler, ungültige API-Schlüssel, fehlerhafte Antworten, Ratenbegrenzung

Sicherheit: API-Schlüssel in Umgebungsvariablen gespeichert, Bereinigung der Eingaben

Implementierungsstrategie

Wir bauen diesen Server schrittweise auf und implementieren jedes Teil mit vollständiger Fehlerbehandlung:

#!/usr/bin/env python3
import json
import sys
import os
import requests
from typing import Dict, Any

# Configuration - use environment variables for security
WEATHER_API_KEY = os.environ.get("OPENWEATHER_API_KEY", "your-api-key-here")

def get_weather(city: str) -> str:
    """Fetch current weather data for a specified city"""
    try:
        url = "<http://api.openweathermap.org/data/2.5/weather>"
        params = {
            "q": city,
            "appid": WEATHER_API_KEY,
            "units": "metric"
        }
        response = requests.get(url, params=params, timeout=10)
        data = response.json()

        if response.status_code == 200:
            temp = data["main"]["temp"]
            desc = data["weather"][0]["description"]
            humidity = data["main"]["humidity"]
            return f"Weather in {city}: {temp}°C, {desc.title()}, Humidity: {humidity}%"
        else:
            return f"Error fetching weather: {data.get('message', 'Unknown error')}"
    except requests.RequestException as e:
        return f"Network error: {str(e)}"
    except Exception as e:
        return f"Error processing weather data: {str(e)}"

def handle_tools_list(request_id: Any) -> Dict[str, Any]:
    """Enhanced tools list with weather functionality"""
    tools = [
        {
            "name": "get_weather",
            "description": "Get current weather conditions for any city worldwide",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name (e.g., 'London', 'Tokyo', 'New York')"
                    }
                },
                "required": ["city"]
            }
        }
    ]

    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "tools": tools
        }
    }

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Enhanced tool execution with weather functionality"""
    tool_name = params.get("name")
    arguments = params.get("arguments", {})

    try:
        if tool_name == "get_weather":
            city = arguments.get("city")
            if not city:
                raise ValueError("City name is required")
            result = get_weather(city)
        else:
            raise ValueError(f"Unknown tool: {tool_name}")

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "content": [
                    {
                        "type": "text",
                        "text": result
                    }
                ]
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {
                "code": -32603,
                "message": str(e)
            }
        }

# Include the same main() function and other handlers from the basic example

Erklärung der erweiterten Funktionen

Sicherheit durch Umgebungsvariablen: Der API-Schlüssel wird aus Umgebungsvariablen geladen, niemals fest codiert. Dies verhindert versehentliche Preisgabe in der Versionskontrolle.

Robuste Fehlerbehandlung: Die Funktion get_weather() behandelt mehrere Fehlerszenarien:

Erweitertes Tool-Schema: Das Wetter-Tool-Schema enthält detaillierte Beschreibungen und Beispiele, die Claude Code helfen, das Tool effektiv zu nutzen.

Schritt 5: Professionelle Abhängigkeits- und Konfigurationsverwaltung

Erstellen einer ordnungsgemäßen Requirements-Datei

requests>=2.28.0
python-dotenv>=1.0.0

Strategie zur Versionsfixierung: Die Verwendung von Mindestversionsanforderungen (>=) gewährleistet Kompatibilität und ermöglicht gleichzeitig Sicherheitsupdates. Für Produktionsserver sollten Sie eine exakte Versionsfixierung in Betracht ziehen.

Sichere Umgebungskonfiguration

Erstellen Sie eine .env-Datei für die Konfigurationsverwaltung:

# Weather API configuration
OPENWEATHER_API_KEY=your_actual_api_key_here

# Server configuration
MCP_LOG_LEVEL=INFO
MCP_DEBUG=false

# Optional: Rate limiting
MCP_MAX_REQUESTS_PER_MINUTE=60

Best Practices für die Sicherheit:

Abhängigkeitsinstallation und -isolierung

# Create virtual environment for isolation
python3 -m venv mcp-env
source mcp-env/bin/activate  # On Windows: mcp-env\\\\Scripts\\\\activate

# Install dependencies
pip install -r requirements.txt

# Verify installation
python3 -c "import requests; print('Dependencies installed successfully')"

Warum virtuelle Umgebungen wichtig sind: Die Isolierung verhindert Abhängigkeitskonflikte zwischen verschiedenen MCP-Servern und Ihrer System-Python-Installation.

Testen und Debuggen Ihres MCP-Servers

Umfassende Teststrategie

Das Testen von MCP-Servern erfordert einen mehrschichtigen Ansatz, da Sie es sowohl mit der Protokollkonformität als auch mit der funktionalen Korrektheit zu tun haben. Eine systematische Teststrategie verhindert, dass Probleme in die Produktion gelangen, und erleichtert das Debugging erheblich.

Testpyramide für MCP-Server

  1. Unit-Tests: Testen einzelner Funktionen
  2. Protokolltests: Überprüfung der JSON-RPC-Konformität
  3. Integrationstests: Testen der Interaktion mit Claude Code
  4. End-to-End-Tests: Validierung des vollständigen Workflows

Ebene 1: Manuelles Protokolltesten

Testen der Kern-MCP-Methoden

Verifizieren Sie vor jeder Integration, dass Ihr Server das MCP-Protokoll korrekt implementiert:

# Test initialization handshake
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py

Erwartete Antwortstruktur:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {"tools": {}},
    "serverInfo": {"name": "your-server", "version": "1.0.0"}
  }
}

Testen der Tool-Erkennung

# Test tools list endpoint
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | python3 server.py

Validierungs-Checkliste:

Testen der Tool-Ausführung

# Test actual tool functionality
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_weather","arguments":{"city":"London"}}}' | python3 server.py

Was zu überprüfen ist:

Ebene 2: Automatisiertes Test-Framework

Erstellen von Testskripten

Erstellen Sie eine Datei test_server.py für automatisierte Tests:

#!/usr/bin/env python3
import json
import subprocess
import sys

def test_mcp_method(method, params=None):
    """Test a specific MCP method"""
    request = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": method,
        "params": params or {}
    }

    try:
        result = subprocess.run(
            [sys.executable, "server.py"],
            input=json.dumps(request),
            capture_output=True,
            text=True,
            timeout=10
        )
        return json.loads(result.stdout.strip())
    except Exception as e:
        return {"error": str(e)}

# Test suite
tests = [
    ("initialize", None),
    ("tools/list", None),
    ("tools/call", {"name": "hello_world", "arguments": {"name": "Test"}})
]

for method, params in tests:
    response = test_mcp_method(method, params)
    print(f"Testing {method}: {'✓ PASS' if 'result' in response else '✗ FAIL'}")

Ebene 3: Integrationstests mit Claude Code

Serverregistrierung und -verifizierung

# Register your server
claude mcp add --scope user test-server python3 /full/path/to/server.py

# Verify registration
claude mcp list | grep test-server

# Check server health
claude mcp get test-server

Live-Integrationstests

# Start Claude Code in test mode
claude

# In Claude Code, test tool discovery
/mcp

# Test tool execution
mcp__test-server__hello_world name:"Integration Test"

Tool-Namensmuster: Claude Code präfixiert Tools mit mcp__<server-name>__<tool-name>, um Namenskonflikte zu vermeiden.

Fortgeschrittene Debugging-Techniken

Debug-Logging aktivieren

Fügen Sie umfassendes Logging zu Ihrem Server hinzu:

import logging
import sys

# Configure logging to stderr (won't interfere with JSON-RPC)
logging.basicConfig(
    level=logging.DEBUG,
    stream=sys.stderr,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

logger = logging.getLogger(__name__)

def handle_tool_call(request_id, params):
    logger.debug(f"Received tool call: {params}")
    # ... your tool logic
    logger.debug(f"Tool execution completed successfully")

Analyse der MCP-Server-Logs

Claude Code führt Logs für jeden MCP-Server:

# View recent logs (macOS)
tail -f ~/Library/Logs/Claude/mcp-server-*.log

# View recent logs (Linux)
tail -f ~/.config/claude/logs/mcp-server-*.log

# Search for errors
grep -i error ~/Library/Logs/Claude/mcp-server-*.log

Häufige Debugging-Muster

Problem: Server startet, aber Tools werden nicht angezeigt

Diagnose: Überprüfen Sie das Format der tools/list-Antwort

Lösung: Validieren Sie die JSON-Schema-Konformität

Problem: Tool-Aufrufe schlagen stillschweigend fehl

Diagnose: Überprüfen Sie die Fehlerbehandlung in tools/call

Lösung: Fügen Sie umfassende Ausnahmebehandlung hinzu

Problem: Serververbindung bricht ab

Diagnose: Überprüfen Sie ungepufferte E/A und ordnungsgemäße Ausnahmebehandlung

Lösung: Überprüfen Sie die Konfiguration von sys.stdout und die Fehlerbehandlung in der Hauptschleife

Performance- und Zuverlässigkeitstests

Lasttests für Ihren Server

# Test multiple rapid requests
for i in {1..10}; do
  echo '{"jsonrpc":"2.0","id":'$i',"method":"tools/list","params":{}}' | python3 server.py &
done
wait

Speicher- und Ressourcenüberwachung

# Monitor server resource usage
python3 -m memory_profiler server.py

# Check for memory leaks during extended operation
python3 -m tracemalloc server.py

Fehlerbehebung bei häufigen Problemen

Probleme auf Protokollebene

  1. Ungültige JSON-Antworten: Verwenden Sie json.loads() zur Validierung der Ausgabe
  2. Fehlende erforderliche Felder: Überprüfen Sie die Einhaltung der MCP-Spezifikation
  3. Falsche Fehlercodes: Verwenden Sie Standard-JSON-RPC-Fehlercodes

Integrationsprobleme

  1. Server wird nicht angezeigt: Überprüfen Sie Dateiberechtigungen und Python-Pfad
  2. Tools nicht zugänglich: Überprüfen Sie die Scope-Konfiguration und Registrierung
  3. Authentifizierungsfehler: Stellen Sie eine ordnungsgemäße MCP-Initialisierung sicher

Best Practices und Sicherheitsaspekte

Produktionsreife Fehlerbehandlung

Implementierung robuster Validierung

Die Fehlerbehandlung in MCP-Servern muss umfassend sein, da Fehler die gesamte Kommunikationskette mit Claude Code unterbrechen können. Implementieren Sie die Validierung auf mehreren Ebenen:

def validate_arguments(arguments: Dict[str, Any], required: List[str]):
    """Validate required arguments are present"""
    missing = [field for field in required if field not in arguments]
    if missing:
        raise ValueError(f"Missing required fields: {', '.join(missing)}")

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Tool execution with proper validation"""
    try:
        tool_name = params.get("name")
        arguments = params.get("arguments", {})

        # Validate before processing
        if tool_name == "get_weather":
            validate_arguments(arguments, ["city"])

        # Process tool logic here

    except ValueError as ve:
        return create_error_response(request_id, -32602, str(ve))
    except Exception as e:
        return create_error_response(request_id, -32603, f"Internal error: {str(e)}")

Standards für Fehlerantworten

Folgen Sie den Konventionen für JSON-RPC 2.0 Fehlercodes:

Umfassendes Sicherheits-Framework

1. Verwaltung von Geheimnissen

Niemals sensible Informationen fest codieren. Verwenden Sie einen geschichteten Ansatz für die Konfiguration:

import os
from pathlib import Path

def load_config():
    """Load configuration with fallback hierarchy"""
    # 1. Environment variables (highest priority)
    api_key = os.environ.get("API_KEY")

    # 2. Local .env file
    if not api_key:
        env_path = Path(".env")
        if env_path.exists():
            # Load from .env file
            pass

    # 3. System keyring (production)
    if not api_key:
        try:
            import keyring
            api_key = keyring.get_password("mcp-server", "api_key")
        except ImportError:
            pass

    if not api_key:
        raise ValueError("API key not found in any configuration source")

    return {"api_key": api_key}

2. Bereinigung und Validierung von Eingaben

Implementieren Sie eine strenge Eingabevalidierung, um Injection-Angriffe zu verhindern:

import re
from typing import Any, Dict

def sanitize_string_input(value: str, max_length: int = 100) -> str:
    """Sanitize string inputs"""
    if not isinstance(value, str):
        raise ValueError("Expected string input")

    # Remove potentially dangerous characters
    sanitized = re.sub(r'[<>"\\\\']', '', value)

    # Limit length to prevent DoS
    if len(sanitized) > max_length:
        raise ValueError(f"Input too long (max {max_length} characters)")

    return sanitized.strip()

def validate_city_name(city: str) -> str:
    """Validate city name input"""
    sanitized = sanitize_string_input(city, 50)

    # Allow only letters, spaces, and common punctuation
    if not re.match(r'^[a-zA-Z\\\\s\\\\-\\\\.]+$', sanitized):
        raise ValueError("Invalid city name format")

    return sanitized

3. Ratenbegrenzung und Ressourcenschutz

Implementieren Sie Ratenbegrenzung, um Missbrauch zu verhindern:

import time
from collections import defaultdict
from threading import Lock

class RateLimiter:
    def __init__(self, max_requests: int = 60, window_seconds: int = 60):
        self.max_requests = max_requests
        self.window_seconds = window_seconds
        self.requests = defaultdict(list)
        self.lock = Lock()

    def allow_request(self, client_id: str = "default") -> bool:
        """Check if request is allowed under rate limit"""
        now = time.time()

        with self.lock:
            # Clean old requests
            self.requests[client_id] = [
                req_time for req_time in self.requests[client_id]
                if now - req_time < self.window_seconds
            ]

            # Check limit
            if len(self.requests[client_id]) >= self.max_requests:
                return False

            # Record this request
            self.requests[client_id].append(now)
            return True

# Global rate limiter instance
rate_limiter = RateLimiter()

Fortgeschrittenes Logging und Monitoring

Implementierung von strukturiertem Logging

Verwenden Sie strukturiertes Logging für besseres Debugging und Monitoring:

import logging
import json
import sys
from datetime import datetime

class MCPFormatter(logging.Formatter):
    """Custom formatter for MCP server logs"""

    def format(self, record):
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
        }

        # Add extra context if available
        if hasattr(record, 'tool_name'):
            log_entry["tool_name"] = record.tool_name
        if hasattr(record, 'request_id'):
            log_entry["request_id"] = record.request_id

        return json.dumps(log_entry)

# Configure structured logging
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(MCPFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)

Performance-Monitoring

Verfolgen Sie Performance-Metriken des Servers:

import time
import statistics
from collections import deque

class PerformanceMonitor:
    def __init__(self, max_samples: int = 1000):
        self.response_times = deque(maxlen=max_samples)
        self.error_count = 0
        self.request_count = 0

    def record_request(self, duration: float, success: bool):
        """Record request metrics"""
        self.request_count += 1
        self.response_times.append(duration)

        if not success:
            self.error_count += 1

    def get_stats(self) -> Dict[str, Any]:
        """Get current performance statistics"""
        if not self.response_times:
            return {"no_data": True}

        return {
            "total_requests": self.request_count,
            "error_rate": self.error_count / self.request_count,
            "avg_response_time": statistics.mean(self.response_times),
            "p95_response_time": statistics.quantiles(self.response_times, n=20)[18],
            "p99_response_time": statistics.quantiles(self.response_times, n=100)[98]
        }

# Global performance monitor
perf_monitor = PerformanceMonitor()

Bereitstellungs- und Wartungsstrategien

Versionsverwaltung

Implementieren Sie eine ordnungsgemäße Versionierung für Ihre MCP-Server:

__version__ = "1.2.3"
__mcp_version__ = "2024-11-05"

def get_server_info():
    """Return server information for MCP initialize"""
    return {
        "name": "my-production-server",
        "version": __version__,
        "mcp_protocol_version": __mcp_version__,
        "capabilities": ["tools", "resources"],  # Declare what you support
    }

Implementierung von Health Checks

Fügen Sie Health-Check-Funktionen für das Monitoring hinzu:

def handle_health_check(request_id: Any) -> Dict[str, Any]:
    """Health check endpoint for monitoring"""
    try:
        # Test core functionality
        test_db_connection()  # Example health check
        test_external_apis()  # Example health check

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "status": "healthy",
                "timestamp": datetime.utcnow().isoformat(),
                "version": __version__,
                "uptime_seconds": time.time() - start_time,
                "performance": perf_monitor.get_stats()
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "status": "unhealthy",
                "error": str(e),
                "timestamp": datetime.utcnow().isoformat()
            }
        }

Behandlung des ordnungsgemäßen Herunterfahrens

Implementieren Sie eine ordnungsgemäße Bereinigung beim Herunterfahren des Servers:

import signal
import sys

class MCPServer:
    def __init__(self):
        self.running = True
        self.active_requests = set()

        # Register signal handlers
        signal.signal(signal.SIGINT, self.shutdown_handler)
        signal.signal(signal.SIGTERM, self.shutdown_handler)

    def shutdown_handler(self, signum, frame):
        """Handle graceful shutdown"""
        logger.info(f"Received signal {signum}, initiating graceful shutdown")
        self.running = False

        # Wait for active requests to complete
        timeout = 30  # seconds
        start_time = time.time()

        while self.active_requests and (time.time() - start_time) < timeout:
            time.sleep(0.1)

        logger.info("Shutdown complete")
        sys.exit(0)

Anwendungsfälle aus der Praxis und fortgeschrittene Anwendungen

Integrationsmuster für Unternehmen

MCP-Server eignen sich hervorragend für Unternehmensumgebungen, in denen Claude Code mit bestehenden Geschäftssystemen integriert werden muss. Hier sind bewährte Integrationsmuster:

Datenbank-Integrationsserver

Automatisierung von Entwicklungs-Workflows

Systemüberwachung und Betrieb

Fortgeschrittene Architekturmuster

Multi-Server-Orchestrierung

Für komplexe Workflows entwerfen Sie MCP-Server, die sich untereinander koordinieren:

# Server coordination pattern
def coordinate_workflow(workflow_id: str, steps: List[Dict]) -> Dict:
    """Coordinate multi-step workflow across servers"""
    results = {}

    for step in steps:
        server_name = step["server"]
        tool_name = step["tool"]
        params = step["params"]

        # Call other MCP server through Claude Code
        result = call_mcp_tool(server_name, tool_name, params)
        results[step["id"]] = result

        # Handle dependencies between steps
        if step.get("depends_on"):
            inject_dependencies(params, results, step["depends_on"])

    return {"workflow_id": workflow_id, "results": results}

Caching und Performance-Optimierung

Implementieren Sie intelligentes Caching für häufig angeforderte Daten:

import hashlib
import pickle
from datetime import datetime, timedelta

class IntelligentCache:
    def __init__(self, default_ttl: int = 3600):
        self.cache = {}
        self.default_ttl = default_ttl

    def get_cache_key(self, tool_name: str, params: Dict) -> str:
        """Generate consistent cache key"""
        key_data = f"{tool_name}:{json.dumps(params, sort_keys=True)}"
        return hashlib.md5(key_data.encode()).hexdigest()

    def get(self, tool_name: str, params: Dict) -> Optional[Any]:
        """Get cached result if valid"""
        key = self.get_cache_key(tool_name, params)

        if key in self.cache:
            data, expiry = self.cache[key]
            if datetime.now() < expiry:
                return data
            else:
                del self.cache[key]

        return None

    def set(self, tool_name: str, params: Dict, result: Any, ttl: Optional[int] = None):
        """Cache result with TTL"""
        key = self.get_cache_key(tool_name, params)
        expiry = datetime.now() + timedelta(seconds=ttl or self.default_ttl)
        self.cache[key] = (result, expiry)

Strategien für die Produktionsbereitstellung

Containerisierte Bereitstellung

Packen Sie Ihren MCP-Server als Docker-Container für eine konsistente Bereitstellung:

FROM python:3.11-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \\\\
    curl \\\\
    && rm -rf /var/lib/apt/lists/*

# Copy and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY server.py .
COPY config/ ./config/

# Create non-root user
RUN useradd -m -s /bin/bash mcpuser
USER mcpuser

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\\\
    CMD python3 -c "import requests; requests.get('<http://localhost:8080/health>')"

CMD ["python3", "server.py"]

Kubernetes-Bereitstellung

Stellen Sie MCP-Server in Kubernetes für Skalierbarkeit und Zuverlässigkeit bereit:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-weather-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mcp-weather-server
  template:
    metadata:
      labels:
        app: mcp-weather-server
    spec:
      containers:
      - name: mcp-server
        image: your-registry/mcp-weather-server:latest
        ports:
        - containerPort: 8080
        env:
        - name: OPENWEATHER_API_KEY
          valueFrom:
            secretKeyRef:
              name: mcp-secrets
              key: openweather-api-key
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

Skalierungs- und Performance-Aspekte

Horizontale Skalierungsmuster

Entwerfen Sie Ihre MCP-Server so, dass sie horizontale Skalierung unterstützen:

  1. Zustandsloses Design: Halten Sie Server zustandslos, um einfache Replikation zu ermöglichen
  2. Lastverteilung: Verteilen Sie Anfragen auf mehrere Serverinstanzen
  3. Datenbank-Pooling: Verwenden Sie Verbindungspools für datenbankgestützte Server
  4. Caching-Strategien: Implementieren Sie Redis oder Memcached für gemeinsames Caching

Performance-Optimierungstechniken

import asyncio
import aiohttp
from concurrent.futures import ThreadPoolExecutor

class HighPerformanceMCPServer:
    def __init__(self):
        self.executor = ThreadPoolExecutor(max_workers=10)
        self.session = None

    async def async_tool_call(self, tool_name: str, params: Dict) -> Dict:
        """Handle tool calls asynchronously"""
        if not self.session:
            self.session = aiohttp.ClientSession()

        # Use async operations for I/O bound tasks
        if tool_name == "web_search":
            return await self.async_web_search(params)
        elif tool_name == "database_query":
            return await self.async_database_query(params)
        else:
            # Use thread pool for CPU-bound tasks
            loop = asyncio.get_event_loop()
            return await loop.run_in_executor(
                self.executor,
                self.sync_tool_call,
                tool_name,
                params
            )

Fazit und nächste Schritte

Beherrschen der MCP-Entwicklung

Der Aufbau von MCP-Servern für Claude Code stellt einen Paradigmenwechsel in der Entwicklung von KI-Anwendungen dar. Im Gegensatz zu traditionellen API-Integrationen, die fest codierte Verbindungen erfordern, bietet MCP eine dynamische, auffindbare Schnittstelle, die KI-Assistenten wirklich erweiterbar macht.

In diesem umfassenden Leitfaden haben Sie gelernt:

Grundlagen:

Produktionsreife:

Fortgeschrittene Funktionen:

Strategischer Entwicklungsansatz

Phase 1: Grundlagen schaffen (Woche 1-2)

Beginnen Sie mit einfachen, auf einen Zweck ausgerichteten Servern, um das Protokoll zu verstehen:

Phase 2: Integration ausbauen (Woche 3-4)

Bauen Sie komplexere Server, die sich in bestehende Systeme integrieren:

Phase 3: Unternehmensweite Bereitstellung (Monat 2+)

Stellen Sie produktionsreife Server mit vollständiger Betriebsunterstützung bereit:

Langfristige Erfolgsstrategien

Community-Engagement

Kontinuierliche Verbesserung

Innovationsmöglichkeiten

Die Zukunft der MCP-Entwicklung

Das Model Context Protocol bildet die Grundlage für ein neues Ökosystem von KI-integrierten Anwendungen. Wenn Sie MCP-Server erstellen, erstellen Sie nicht nur Tools für Claude Code – Sie bauen wiederverwendbare Komponenten, die im wachsenden Ökosystem der MCP-kompatiblen KI-Assistenten funktionieren werden.

Ihre Investition in die MCP-Entwicklung zahlt sich aus durch:

Wichtige Erfolgsfaktoren

Wenn Sie sich auf Ihre MCP-Entwicklungsreise begeben, denken Sie an diese wesentlichen Prinzipien:

  1. Beherrschung des Konfigurations-Scopes: Verwenden Sie immer -scope user für Entwicklungsserver, es sei denn, Sie benötigen spezifische Einschränkungen auf Projektebene
  2. Sicherheit zuerst: Niemals Geheimnisse fest codieren, immer Eingaben validieren, Ratenbegrenzung implementieren
  3. Vollständigkeit der Fehlerbehandlung: Alle Fehlermodi antizipieren und ordnungsgemäß behandeln
  4. Gründlichkeit der Tests: Protokollkonformität, Funktionalität und Integration testen
  5. Qualität der Dokumentation: Dokumentieren Sie Ihre Server für Teamzusammenarbeit und Wartung

Hilfe und Ressourcen erhalten

Wenn Sie auf Herausforderungen stoßen:

Beginnen Sie noch heute mit dem Bauen, iterieren Sie schnell und schließen Sie sich der wachsenden Community von Entwicklern an, die die Fähigkeiten der KI durch das Model Context Protocol erweitern. Ihre benutzerdefinierten MCP-Server werden neue Möglichkeiten für KI-unterstützte Workflows eröffnen, die wir gerade erst zu erahnen beginnen.

Denken Sie daran: Jede komplexe Integration begann mit einem einfachen "Hello World"-Server. Beginnen Sie mit den Grundlagen, beherrschen Sie die Fundamente und bauen Sie schrittweise die KI-integrierten Tools auf, die Ihre Arbeitsweise verändern werden.

💡
Sie suchen ein großartiges API-Test-Tool, das schöne API-Dokumentation generiert?

Sie möchten eine integrierte All-in-One-Plattform für Ihr Entwicklerteam, um mit maximaler Produktivität zusammenzuarbeiten?

Apidog erfüllt all Ihre Anforderungen und ersetzt Postman zu einem viel günstigeren Preis!
button

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen