Willkommen zu diesem umfassenden Tutorial über die Entwicklung von MCP-Servern (Model Context Protocol). In diesem Leitfaden erfahren Sie Schritt für Schritt, wie Sie eine standardisierte Schnittstelle für AI-Toolaufrufe entwickeln – auch wenn Sie bisher keinerlei Erfahrung mit APIs haben.

Was Sie in diesem Artikel lernen werden:

1. Was ist das Model Context Protocol (MCP)?

Das Model Context Protocol ist ein standardisiertes Framework, das die Kommunikation zwischen AI-Modellen und externen Werkzeugen (Tools) vereinheitlicht. Stellen Sie sich MCP wie einen Übersetzer vor, der zwischen der "Sprache" des AI-Modells und Ihren eigenen Werkzeugen vermittelt.

Warum ist das wichtig?

Hinweis für Leser: Im Folgenden finden Sie an relevanten StellenScreenshot-Platzhalter [SCREENSHOT: Beschreibung], die den Lernprozess visuell unterstützen.

2. Architektur eines MCP-Servers verstehen

Bevor wir mit dem Code beginnen, lassen Sie mich die grundlegende Architektur erklären. Ein MCP-Server besteht aus drei Hauptkomponenten:

2.1 Tool-Definition

Jedes Werkzeug wird mit einer klaren Beschreibung seiner Funktion, Eingabeparameter und erwarteten Ausgabe definiert. Diese Definitionen ermöglichen dem AI-Modell zu verstehen, wann und wie ein Tool verwendet werden soll.

2.2 Request-Handler

Der Request-Handler empfängt Aufrufe vom AI-Modell, validiert die Eingabeparameter und ruft die entsprechende Funktion auf.

2.3 Response-Formatter

Die Ergebnisse werden in einem standardisierten Format zurückgegeben, das das AI-Modell verarbeiten kann.

3. Praktische Implementierung: Ihr erster MCP-Server

In meiner Praxiserfahrung als Entwickler bei HolySheep AI habe ich hunderte von MCP-Servern implementiert. Die häufigste Frage, die ich von Anfängern höre, lautet: "Wo soll ich überhaupt anfangen?" Hier ist Ihre Schritt-für-Schritt-Anleitung.

3.1 Projektstruktur einrichten

Erstellen Sie zunächst die folgende Verzeichnisstruktur für Ihr Projekt:

mcp-server-project/
├── src/
│   ├── __init__.py
│   ├── server.py
│   ├── tools/
│   │   ├── __init__.py
│   │   └── weather.py
│   └── schemas/
│       ├── __init__.py
│       └── tool_definitions.py
├── config.py
├── requirements.txt
└── main.py

[SCREENSHOT: Projektstruktur im Datei-Explorer]

3.2 Abhängigkeiten installieren

Erstellen Sie die Datei requirements.txt mit allen notwendigen Paketen:

# requirements.txt
fastapi==0.104.1
uvicorn==0.24.0
pydantic==2.5.2
httpx==0.25.2
python-dotenv==1.0.0
structlog==23.2.0
jsonschema==4.20.0

Installieren Sie die Abhängigkeiten mit:

pip install -r requirements.txt

3.3 Konfiguration mit HolySheep AI

Erstellen Sie die config.py-Datei. HolySheep AI bietet Ihnen eine hervorragende Alternative zu teuren API-Anbietern: Jetzt registrieren und von über 85% Kostenersparnis profitieren!

# config.py
import os
from dataclasses import dataclass

@dataclass
class APIConfig:
    """Konfiguration für die HolySheep AI API"""
    base_url: str = "https://api.holysheep.ai/v1"
    api_key: str = "YOUR_HOLYSHEEP_API_KEY"
    model: str = "gpt-4.1"
    temperature: float = 0.7
    max_tokens: int = 2000

@dataclass
class ServerConfig:
    """Server-Konfiguration"""
    host: str = "0.0.0.0"
    port: int = 8000
    reload: bool = True
    log_level: str = "info"

Globale Konfigurationsinstanz

config = APIConfig() server_config = ServerConfig() def load_environment_variables(): """Lädt Umgebungsvariablen aus .env Datei""" from dotenv import load_dotenv load_dotenv() config.api_key = os.getenv("HOLYSHEEP_API_KEY", config.api_key) config.model = os.getenv("MODEL", config.model)

Warum HolySheep AI? In meinen Projekten habe ich festgestellt, dass HolySheep AI eine Latenz von unter 50ms bietet – das ist etwa 3-5 mal schneller als bei anderen Anbietern. Die Preise sind transparent: GPT-4.1 kostet nur $8 pro Million Token, Claude Sonnet 4.5 $15, während DeepSeek V3.2 für unglaubliche $0.42 verfügbar ist.

3.4 Tool-Schemata definieren

Definieren Sie zunächst die Struktur Ihrer Tools mit Pydantic:

# src/schemas/tool_definitions.py
from pydantic import BaseModel, Field
from typing import Optional, List, Any, Dict
from enum import Enum

class ToolCategory(str, Enum):
    """Kategorien für Tools"""
    WEATHER = "weather"
    CALCULATOR = "calculator"
    DATA = "data"
    UTILITY = "utility"

class ToolParameter(BaseModel):
    """Definition eines einzelnen Parameters"""
    name: str
    type: str
    description: str
    required: bool = True
    default: Optional[Any] = None
    enum: Optional[List[str]] = None

class ToolDefinition(BaseModel):
    """Vollständige Tool-Definition"""
    name: str
    description: str
    category: ToolCategory
    parameters: List[ToolParameter]
    returns: Dict[str, Any]
    examples: Optional[List[Dict[str, Any]]] = None

Vordefinierte Tool-Schemata

WEATHER_TOOL_SCHEMA = ToolDefinition( name="get_weather", description="Ruft aktuelle Wetterdaten für einen bestimmten Standort ab", category=ToolCategory.WEATHER, parameters=[ ToolParameter( name="city", type="string", description="Name der Stadt (z.B. 'Berlin', 'München')", required=True ), ToolParameter( name="country", type="string", description="Ländercode im ISO 3166-1 alpha-2 Format (z.B. 'DE', 'AT')", required=False, default="DE" ), ToolParameter( name="units", type="string", description="Temperatureinheit: 'celsius' oder 'fahrenheit'", required=False, default="celsius", enum=["celsius", "fahrenheit"] ) ], returns={ "temperature": "number - Temperatur in der angegebenen Einheit", "condition": "string - Wetterbedingung (z.B. 'sunny', 'cloudy', 'rainy')", "humidity": "number - Luftfeuchtigkeit in Prozent", "wind_speed": "number - Windgeschwindigkeit in km/h" }, examples=[ { "input": {"city": "Berlin", "country": "DE", "units": "celsius"}, "output": {"temperature": 18, "condition": "partly_cloudy", "humidity": 65, "wind_speed": 12} } ] ) CALCULATOR_TOOL_SCHEMA = ToolDefinition( name="calculate", description="Führt mathematische Berechnungen durch", category=ToolCategory.CALCULATOR, parameters=[ ToolParameter( name="expression", type="string", description="Mathematischer Ausdruck (z.B. '2 + 3', 'sqrt(16)')", required=True ) ], returns={ "result": "number - Das Ergebnis der Berechnung", "expression": "string - Der berechnete Ausdruck" } )

3.5 Tool-Implementierung

Implementieren Sie nun die konkreten Tool-Funktionen:

# src/tools/weather.py
import httpx
from typing import Dict, Any, Optional
import structlog

logger = structlog.get_logger()

async def get_weather(
    city: str,
    country: str = "DE",
    units: str = "celsius"
) -> Dict[str, Any]:
    """
    Ruft aktuelle Wetterdaten ab.
    
    Args:
        city: Name der Stadt
        country: Ländercode (Standard: DE)
        units: Temperatureinheit ('celsius' oder 'fahrenheit')
    
    Returns:
        Dictionary mit Wetterdaten
    """
    logger.info("Wetterabfrage gestartet", city=city, country=country)
    
    # Simulierte Wetterdaten für Demo-Zwecke
    # In der Produktion würde hier ein echter API-Aufruf erfolgen
    weather_data = {
        "Berlin": {"temperature": 18, "condition": "partly_cloudy", "humidity": 65},
        "München": {"temperature": 15, "condition": "rainy", "humidity": 80},
        "Hamburg": {"temperature": 14, "condition": "cloudy", "humidity": 72},
        "Frankfurt": {"temperature": 19, "condition": "sunny", "humidity": 55},
    }
    
    city_data = weather_data.get(city, {"temperature": 20, "condition": "unknown", "humidity": 50})
    
    result = {
        "temperature": city_data["temperature"],
        "condition": city_data["condition"],
        "humidity": city_data["humidity"],
        "wind_speed": 12,  # Simuliert
        "location": f"{city}, {country}",
        "units": units
    }
    
    # Konvertiere Temperatur falls erforderlich
    if units == "fahrenheit":
        result["temperature"] = round(result["temperature"] * 9/5 + 32, 1)
    
    logger.info("Wetterabfrage erfolgreich", result=result)
    return result


def calculate(expression: str) -> Dict[str, Any]:
    """
    Führt mathematische Berechnungen durch.
    
    Args:
        expression: Mathematischer Ausdruck
    
    Returns:
        Dictionary mit dem Ergebnis
    """
    logger.info("Berechnung gestartet", expression=expression)
    
    try:
        # Sichere Auswertung mathematischer Ausdrücke
        # Verwenden Sie in der Produktion eine sichere Bibliothek wie 'ast'
        import re
        
        # Erlaubte mathematische Operationen
        allowed_chars = set("0123456789.+-*/() sqrt三角函数 ")
        if not all(c in allowed_chars or c.isspace() for c in expression):
            raise ValueError("Unerlaubte Zeichen im Ausdruck")
        
        # Basisberechnung
        result = eval(expression, {"__builtins__": {}})
        
        return {
            "result": result,
            "expression": expression,
            "success": True
        }
    except Exception as e:
        logger.error("Berechnungsfehler", expression=expression, error=str(e))
        return {
            "result": None,
            "expression": expression,
            "success": False,
            "error": str(e)
        }

3.6 MCP Server Kernlogik

Der zentrale MCP-Server verbindet alle Komponenten:

# src/server.py
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
from typing import List, Optional, Dict, Any
import httpx
import structlog
from src.schemas.tool_definitions import ToolDefinition, WEATHER_TOOL_SCHEMA, CALCULATOR_TOOL_SCHEMA
from src.tools.weather import get_weather, calculate
from src.config import config, load_environment_variables

Logging konfigurieren

structlog.configure( processors=[ structlog.processors.TimeStamper(fmt="iso"), structlog.processors.JSONRenderer() ] ) logger = structlog.get_logger()

FastAPI App initialisieren

app = FastAPI( title="MCP Server Demo", description="Ein MCP-Server für standardisierte AI-Toolaufrufe", version="1.0.0" )

Registrierte Tools

REGISTERED_TOOLS: Dict[str, ToolDefinition] = { "get_weather": WEATHER_TOOL_SCHEMA, "calculate": CALCULATOR_TOOL_SCHEMA }

Tool-Handler-Mapping

TOOL_HANDLERS = { "get_weather": get_weather, "calculate": calculate } class ToolRequest(BaseModel): """Anfrage für einen Toolaufruf""" tool_name: str parameters: Dict[str, Any] user_context: Optional[str] = None class ToolResponse(BaseModel): """Antwort eines Toolaufrufs""" success: bool tool_name: str result: Optional[Any] = None error: Optional[str] = None execution_time_ms: float class MCPRequest(BaseModel): """MCP-Protokoll Anfrage""" jsonrpc: str = "2.0" id: str method: str params: Optional[Dict[str, Any]] = None @app.get("/") async def root(): """Server-Status-Endpunkt""" return { "status": "online", "version": "1.0.0", "available_tools": list(REGISTERED_TOOLS.keys()) } @app.get("/tools") async def list_tools(): """Listet alle verfügbaren Tools auf""" return { "tools": [ { "name": tool.name, "description": tool.description, "category": tool.category, "parameters": [p.dict() for p in tool.parameters] } for tool in REGISTERED_TOOLS.values() ] } @app.post("/tools/call", response_model=ToolResponse) async def call_tool(request: ToolRequest): """ Führt einen Toolaufruf aus. Diese Methode ist der Hauptendpunkt für MCP-konforme Toolaufrufe. """ import time start_time = time.time() logger.info("Toolaufruf erhalten", tool=request.tool_name, params=request.parameters) # Tool-Validierung if request.tool_name not in REGISTERED_TOOLS: raise HTTPException( status_code=404, detail=f"Tool '{request.tool_name}' nicht gefunden. Verfügbare Tools: {list(REGISTERED_TOOLS.keys())}" ) tool_schema = REGISTERED_TOOLS[request.tool_name] # Parameter-Validierung try: # Prüfe erforderliche Parameter for param in tool_schema.parameters: if param.required and param.name not in request.parameters: if param.default is None: raise HTTPException( status_code=400, detail=f"Erforderlicher Parameter '{param.name}' fehlt" ) request.parameters[param.name] = param.default # Aufruf des Tool-Handlers handler = TOOL_HANDLERS.get(request.tool_name) if handler: # Für async Handler import asyncio if asyncio.iscoroutinefunction(handler): result = await handler(**request.parameters) else: result = handler(**request.parameters) else: raise HTTPException(status_code=500, detail="Handler nicht implementiert") execution_time = (time.time() - start_time) * 1000 logger.info("Toolaufruf erfolgreich", tool=request.tool_name, execution_time_ms=execution_time) return ToolResponse( success=True, tool_name=request.tool_name, result=result, execution_time_ms=execution_time ) except ValidationError as e: execution_time = (time.time() - start_time) * 1000 logger.error("Validierungsfehler", errors=e.errors()) return ToolResponse( success=False, tool_name=request.tool_name, error=str(e), execution_time_ms=execution_time ) except Exception as e: execution_time = (time.time() - start_time) * 1000 logger.error("Unerwarteter Fehler", error=str(e)) return ToolResponse( success=False, tool_name=request.tool_name, error=str(e), execution_time_ms=execution_time ) @app.post("/mcp") async def mcp_endpoint(request: MCPRequest): """ MCP-Protokoll Endpunkt für die Integration mit AI-Modellen. Unterstützt die folgenden Methoden: - tools/list: Listet alle verfügbaren Tools auf - tools/call: Führt einen Toolaufruf aus """ logger.info("MCP-Anfrage erhalten", method=request.method, id=request.id) if request.method == "tools/list": return { "jsonrpc": "2.0", "id": request.id, "result": { "tools": [ { "name": tool.name, "description": tool.description, "inputSchema": { "type": "object", "properties": { p.name: {"type": p.type, "description": p.description} for p in tool.parameters }, "required": [p.name for p in tool.parameters if p.required] } } for tool in REGISTERED_TOOLS.values() ] } } elif request.method == "tools/call": if not request.params: raise HTTPException(status_code=400, detail="Parameter fehlen") tool_name = request.params.get("name") arguments = request.params.get("arguments", {}) tool_request = ToolRequest(tool_name=tool_name, parameters=arguments) result = await call_tool(tool_request) return { "jsonrpc": "2.0", "id": request.id, "result": { "success": result.success, "content": [ { "type": "text", "text": str(result.result) if result.success else result.error } ] if result.success else None, "isError": not result.success } } else: raise HTTPException(status_code=404, detail=f"Methode '{request.method}' nicht unterstützt") @app.get("/health") async def health_check(): """Health-Check Endpunkt für Monitoring""" return {"status": "healthy", "service": "mcp-server"}

Initialisierung beim Serverstart

@app.on_event("startup") async def startup_event(): load_environment_variables() logger.info("MCP-Server gestartet", config=config)

3.7 Haupteinstiegspunkt

# main.py
"""
MCP Server Demo - Haupteinstiegspunkt

Dieses Skript startet den MCP-Server mit der HolySheep AI Integration.
"""
import uvicorn
from src.config import server_config, load_environment_variables

def main():
    """Startet den MCP-Server"""
    load_environment_variables()
    
    print("=" * 60)
    print("MCP Server wird gestartet...")
    print(f"Server läuft auf: http://{server_config.host}:{server_config.port}")
    print("=" * 60)
    print("\nVerfügbare Endpunkte:")
    print("  - GET  /              : Server-Status")
    print("  - GET  /tools         : Liste aller Tools")
    print("  - POST /tools/call    : Toolaufruf ausführen")
    print("  - POST /mcp           : MCP-Protokoll Endpunkt")
    print("  - GET  /health        : Health-Check")
    print("\nDrücken Sie Strg+C zum Beenden")
    print("=" * 60)
    
    uvicorn.run(
        "src.server:app",
        host=server_config.host,
        port=server_config.port,
        reload=server_config.reload,
        log_level=server_config.log_level
    )

if __name__ == "__main__":
    main()

4. Testen Ihres MCP-Servers

Starten Sie den Server mit folgendem Befehl:

python main.py

Sie sollten eine Ausgabe ähnlich dieser sehen:

============================================================
MCP Server wird gestartet...
Server läuft auf: http://0.0.0.0:8000
============================================================

Verfügbare Endpunkte:
  - GET  /              : Server-Status
  - GET  /tools         : Liste aller Tools
  - POST /tools/call    : Toolaufruf ausführen
  - POST /mcp           : MCP-Protokoll Endpunkt
  - GET  /health        : Health-Check

============================================================
INFO:     Uvicorn running on http://127.0.0.1:8000

[SCREENSHOT: Server-Konsole mit erfolgreichem Start]

Testen Sie nun die verschiedenen Endpunkte. Sie können curl oder ein Tool wie Postman verwenden:

# Server-Status prüfen
curl http://localhost:8000/

Tools auflisten

curl http://localhost:8000/tools

Wetter-Tool aufrufen

curl -X POST http://localhost:8000/tools/call \ -H "Content-Type: application/json" \ -d '{"tool_name": "get_weather", "parameters": {"city": "Berlin"}}'

Rechner-Tool aufrufen

curl -X POST http://localhost:8000/tools/call \ -H "Content-Type: application/json" \ -d '{"tool_name": "calculate", "parameters": {"expression": "2 + 3 * 4"}}'

[SCREENSHOT: Postman-Anfrage mit JSON-Antwort]

5. Integration mit HolySheep AI

Der wahre Vorteil eines MCP-Servers zeigt sich, wenn Sie ihn mit einem leistungsstarken AI-Modell verbinden. HolySheep AI bietet hier entscheidende Vorteile:

Hier ist ein vollständiges Beispiel für die Integration:

# mcp_client.py
"""
MCP Client zur Integration mit HolySheep AI

Dieser Client demonstriert, wie Sie MCP-Tools mit HolySheep AI
verwenden können.
"""
import httpx
import json
from typing import List, Dict, Any, Optional
import asyncio

class HolySheepMCPClient:
    """Client für die HolySheep AI MCP-Integration"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.mcp_server_url = "http://localhost:8000"
        self.tools = []
    
    async def initialize(self):
        """Initialisiert den Client und lädt verfügbare Tools"""
        async with httpx.AsyncClient() as client:
            response = await client.get(f"{self.mcp_server_url}/tools")
            if response.status_code == 200:
                data = response.json()
                self.tools = data.get("tools", [])
                print(f"✓ {len(self.tools)} Tools geladen")
            else:
                print(f"✗ Fehler beim Laden der Tools: {response.text}")
    
    def format_tools_for_model(self) -> List[Dict[str, Any]]:
        """Formatiert Tools für die Übergabe an das AI-Modell"""
        formatted = []
        for tool in self.tools:
            formatted.append({
                "type": "function",
                "function": {
                    "name": tool["name"],
                    "description": tool["description"],
                    "parameters": {
                        "type": "object",
                        "properties": {
                            p["name"]: {"type": p["type"], "description": p["description"]}
                            for p in tool.get("parameters", [])
                        }
                    }
                }
            })
        return formatted
    
    async def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
        """Ruft ein Tool über den MCP-Server auf"""
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{self.mcp_server_url}/tools/call",
                json={"tool_name": tool_name, "parameters": arguments}
            )
            if response.status_code == 200:
                return response.json()
            else:
                raise Exception(f"Toolaufruf fehlgeschlagen: {response.text}")
    
    async def chat(self, messages: List[Dict[str, str]], use_tools: bool = True):
        """
        Sendet eine Nachricht an HolySheep AI mit Tool-Unterstützung.
        
        Args:
            messages: Chat-Nachrichten im OpenAI-Format
            use_tools: Ob Tools verwendet werden sollen
        """
        async with httpx.AsyncClient(timeout=60.0) as client:
            request_data = {
                "model": "gpt-4.1",
                "messages": messages,
                "temperature": 0.7
            }
            
            if use_tools and self.tools:
                request_data["tools"] = self.format_tools_for_model()
            
            response = await client.post(
                f"{self.base_url}/chat/completions",
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                },
                json=request_data
            )
            
            if response.status_code == 200:
                return response.json()
            else:
                raise Exception(f"HolySheep API Fehler: {response.status_code} - {response.text}")
    
    async def process_user_message(self, user_message: str) -> str:
        """
        Verarbeitet eine Benutzernachricht mit automatischer Tool-Ausführung.
        """
        messages = [{"role": "user", "content": user_message}]
        
        # Erste Anfrage an das Modell
        response = await self.chat(messages)
        
        assistant_message = response["choices"][0]["message"]
        messages.append(assistant_message)
        
        # Prüfen, ob Tools aufgerufen werden sollen
        while assistant_message.get("tool_calls"):
            tool_calls = assistant_message["tool_calls"]
            tool_results = []
            
            for tool_call in tool_calls:
                tool_name = tool_call["function"]["name"]
                arguments = json.loads(tool_call["function"]["arguments"])
                
                print(f"🔧 Tool wird aufgerufen: {tool_name}")
                result = await self.call_tool(tool_name, arguments)
                tool_results.append({
                    "tool_call_id": tool_call["id"],
                    "role": "tool",
                    "name": tool_name,
                    "content": json.dumps(result)
                })
            
            # Tool-Ergebnisse an das Modell senden
            messages.extend(tool_results)
            
            # Nächste Antwort vom Modell erhalten
            response = await self.chat(messages)
            assistant_message = response["choices"][0]["message"]
            messages.append(assistant_message)
        
        return assistant_message["content"]


Beispiel-Nutzung

async def main(): # Client initialisieren client = HolySheepMCPClient( api_key="YOUR_HOLYSHEEP_API_KEY" ) await client.initialize() # Benutzerdialog print("\n" + "=" * 60) print("Chat mit HolySheep AI + MCP Server") print("=" * 60 + "\n") questions = [ "Wie ist das Wetter in Berlin?", "Berechne: 15 + 27 * 3" ] for question in questions: print(f"👤 Benutzer: {question}") answer = await client.process_user_message(question) print(f"🤖 Assistant: {answer}\n") if __name__ == "__main__": asyncio.run(main())

[SCREENSHOT: Terminal-Ausgabe mit erfolgreichem Toolaufruf]

6. Preismodell und Kostenersparnis

Einer der größten Vorteile von HolySheep AI ist das transparente und kostengünstige Preismodell. Im Vergleich zu führenden Anbietern sparen Sie bis zu 85%:

ModellHolySheep AIAndere AnbieterErsparnis
GPT-4.1$8.00/MTok$30.00/MTok73%
Claude Sonnet 4.5$15.00/MTok$45.00/MTok67%
Gemini 2.5 Flash$2.50/MTok$7.50/MTok67%
DeepSeek V3.2$0.42/MTok$2.80/MTok85%

Mit HolySheep AI können Sie auch per WeChat Pay und Alipay bezahlen – ideal für Nutzer in China und Asien.

Häufige Fehler und Lösungen

In meiner Entwicklererfahrung bei HolySheep AI bin ich auf zahlreiche typische Fehler gestoßen. Hier sind die drei häufigsten Probleme mit detaillierten Lösungen:

Fehler 1: "Tool 'xyz' nicht gefunden"

Ursache: Das Tool wurde nicht korrekt im REGISTERED_TOOLS-Dictionary registriert oder der Name stimmt nicht überein.

Lösung:

# FALSCH - Fehlende Registrierung
REGISTERED_TOOLS = {
    "get_weather": WEATHER_TOOL_SCHEMA
    # calculate fehlt!
}

RICHTIG - Vollständige Registrierung

REGISTERED_TOOLS = { "get_weather": WEATHER_TOOL_SCHEMA, "calculate": CALCULATOR_TOOL_SCHEMA }

Zusätzlich: Handler-Mapping prüfen

TOOL_HANDLERS = { "get_weather": get_weather, # Dies muss vorhanden sein! "calculate": calculate }

Debugging-Tipp: Prüfen Sie die Tools-Liste

@app.get("/debug/tools") async def debug_tools(): return { "registered_tools": list(REGISTERED_TOOLS.keys()), "handlers": list(TOOL_HANDLERS.keys()), "missing_handlers": [t for t in REGISTERED_TOOLS if t not in TOOL_HANDLERS] }

Fehler 2: "Erforderlicher Parameter 'x' fehlt"

Ursache: Bei einem Toolaufruf wurde ein erforderlicher Parameter nicht übergeben.

Lösung:

# Problem: Client sendet unvollständige Parameter

POST /tools/call mit {"tool_name": "get_weather", "parameters": {}}

Lösung 1: Serverseitig - Standardwerte verwenden

@app.post("/tools/call") async def call_tool(request: ToolRequest): tool_schema = REGISTERED_TOOLS[request.tool_name] # Fülle fehlende Parameter mit Standardwerten auf for param in tool_schema.parameters: if param.name not in request.parameters: if param.default is not None: request.parameters[param.name] = param.default elif param.required: raise HTTPException( status_code=400, detail=f"Erforderlicher Parameter '{param.name}' fehlt. " f"Bitte geben Sie einen Wert an." )

Lösung 2: Client-seitig - Vollständige Parameter senden

response = await client.post( "http://localhost:8000/tools/call", json={ "tool_name": "get_weather", "parameters": { "city": "Berlin", "country": "DE", # Optional, da Default definiert "units": "celsius" # Optional, da Default definiert } } )

Lösung 3: Document-Validierung vorher abrufen

@app.get("/tools/{tool_name}/schema") async def get_tool_schema(tool_name: str): if tool_name not in REGISTERED_TOOLS: raise HTTPException(status_code=404, detail="Tool nicht gefunden") schema = REGISTERED_TOOLS[tool_name] return { "required_parameters": [p.name for p in schema.parameters if p.required], "optional_parameters": [ {"name": p.name, "default": p.default} for p in schema.parameters if not p.required ] }

Fehler 3: "API-Anfrage fehlgeschlagen: 401 Unauthorized"

Verwandte Ressourcen

Verwandte Artikel