Key Findings
  • MCP (Model Context Protocol) ist das „USB-C" der KI-Tool-Integration -- ein offenes Protokoll vereinheitlicht alle Tool-Verbindungen und reduziert das N×M-Problem der Anbindung von N KI-Anwendungen an M Tools auf N+M
  • Dreischichtige Architektur: Host (KI-Anwendung, z. B. Claude Desktop) → Client (Protokollschicht, verwaltet Verbindungen und Sicherheit) → Server (Tool- und Datenanbieter) -- klare Trennung der Verantwortlichkeiten
  • Bereits von fuhrenden Entwicklungstools wie Claude Desktop, Cursor, Windsurf, Zed und Sourcegraph Cody ubernommen; die Community hat bereits uber tausend Open-Source MCP Server erstellt
  • Dieser Artikel enthalt zwei Google Colab-Implementierungen: Aufbau eines Wetter-Abfrage MCP Servers von Grund auf und Erstellung eines Multi-Tool MCP Servers mit vollstandigem Client SDK-Testdurchlauf

I. Warum wird MCP benotigt? Das Fragmentierungsproblem der KI-Tool-Integration

Die Leistungsgrenzen von Large Language Models (LLM) hangen davon ab, auf wie viele externe Tools und Daten sie zugreifen konnen. Ob Datenbankabfragen, API-Operationen, Dateisystemzugriff oder Interaktion mit Drittanbieterdiensten -- LLMs benotigen eine zuverlassige „Brucke" zur Verbindung mit der Aussenwelt. Diese Brucke ist jedoch bis heute nicht standardisiert[6].

1.1 Das N×M-Problem: Jede Integration ist eine Insel

Stellen Sie sich vor, Sie sind technischer Leiter eines Unternehmens, und Ihr Team nutzt 3 KI-Anwendungen (Claude, ChatGPT, Gemini) sowie 5 interne Tools (CRM, ERP, Wissensdatenbank, Slack, Jira). Ohne einheitliches Protokoll mussen Sie 3 × 5 = 15 separate Integrationen erstellen. Mit jeder neuen KI-Anwendung oder jedem neuen Tool wachst die Anzahl der Integrationen multiplikativ. Das ist das sogenannte N×M-Problem.

Schick et al. haben in ihrer Toolformer-Forschung[3] bewiesen, dass LLMs eigenstandig lernen konnen, Tools zu verwenden, doch die Zugangsschnittstellen der Tools sind weiterhin fragmentiert. Jede Plattform hat ihr eigenes API-Format, ihre eigenen Authentifizierungsmechanismen und Fehlerbehandlungslogiken, sodass Entwickler fur jede Kombination massgeschneiderten Glue Code schreiben mussen.

1.2 Die Grenzen von Function Calling

Das 2023 von OpenAI eingefuhrte Function Calling[11] war ein wichtiger Versuch. Es ermoglicht Entwicklern, Funktionen mittels JSON Schema zu definieren, sodass das Modell entscheidet, wann es aufruft und welche Parameter es ubergibt. Googles Gemini API bietet einen ahnlichen Mechanismus[12].

Function Calling hat jedoch drei strukturelle Einschrankungen:

1.3 MCPs Losung: Die einheitliche Protokollschicht

Im November 2024 veroffentlichte Anthropic das Model Context Protocol (MCP) als Open Source[2] mit dem Ziel, das „USB-C" der KI-Tool-Integration zu werden -- ein einheitlicher, offener, herstellerneutraler Protokollstandard.

Die Kernerkenntnis von MCP lautet: Anstatt jede KI-Anwendung einzeln an jedes Tool anzubinden (N×M), wird eine zwischengeschaltete Protokollschicht geschaffen. KI-Anwendungen mussen nur einmal einen MCP Client implementieren, um sich mit allen MCP Servern zu verbinden; Tool-Anbieter mussen nur einmal einen MCP Server implementieren, um von allen MCP-kompatiblen KI-Anwendungen angesprochen werden zu konnen. Die Integrationszahl sinkt von N×M auf N+M.

Traditionelles Modell (N×M Integrationen):

  Claude ──┬── Slack-Integration
           ├── GitHub-Integration
           └── PostgreSQL-Integration
  ChatGPT ─┬── Slack-Integration (Neuschreibung)
           ├── GitHub-Integration (Neuschreibung)
           └── PostgreSQL-Integration (Neuschreibung)

MCP-Modell (N+M Integrationen):

  Claude ──── MCP Client ──┐
  ChatGPT ── MCP Client ──┤  MCP-Protokoll
  Cursor ─── MCP Client ──┤
                           ├── Slack MCP Server
                           ├── GitHub MCP Server
                           └── PostgreSQL MCP Server

II. Vollstandige Analyse der MCP-Protokollarchitektur

Das Protokolldesign von MCP folgt dem JSON-RPC 2.0-Standard[1] und definiert drei Kernrollen sowie drei Fahigkeitsprimitive (Primitives). Wer diese sechs Konzepte versteht, beherrscht das vollstandige Bild von MCP.

2.1 Drei-Rollen-Architektur: Host / Client / Server

Host ist die KI-Anwendung, mit der Benutzer direkt interagieren, beispielsweise Claude Desktop, Cursor IDE oder ein selbst entwickelter Chatbot. Der Host ist fur die Benutzeroberflache, die Verwaltung des Gesprachsablaufs und die Entscheidung zustandig, wann externe Tools aufgerufen werden mussen.

Client ist die Protokollschicht-Komponente innerhalb des Hosts. Jeder Client unterhalt eine Eins-zu-eins-zustandsbehaftete Verbindung mit einem Server. Der Client ist zustandig fur den Protokoll-Handshake (Initialization Handshake), die Fahigkeitsaushandlung (Capability Negotiation), das Nachrichten-Routing und -- am wichtigsten -- die Sicherheitskontrolle. Innerhalb eines Hosts konnen gleichzeitig mehrere Clients laufen, die jeweils mit verschiedenen Servern verbunden sind.

Server ist der Anbieter von Tools und Daten. Ein MCP Server kann eine beliebige Anzahl von Tools, Resources und Prompt-Vorlagen bereitstellen. Der Server ist ein leichtgewichtiger Prozess, der typischerweise uber stdio oder HTTP+SSE mit dem Client kommuniziert.

MCP-Architekturdiagramm:

┌─────────────────────────────────────────────┐
│  Host (z. B. Claude Desktop)                │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐     │
│  │ Client A│  │ Client B│  │ Client C│     │
│  └────┬────┘  └────┬────┘  └────┬────┘     │
└───────┼────────────┼────────────┼───────────┘
        │            │            │
   MCP Protocol  MCP Protocol  MCP Protocol
   (JSON-RPC)   (JSON-RPC)   (JSON-RPC)
        │            │            │
   ┌────┴────┐  ┌────┴────┐  ┌────┴────┐
   │Server A │  │Server B │  │Server C │
   │(GitHub) │  │(Slack)  │  │(DB)     │
   └─────────┘  └─────────┘  └─────────┘

2.2 Die drei Fahigkeitsprimitive

MCP Server stellen dem Client ihre Fahigkeiten uber drei Primitive bereit:

Tools sind Funktionen, die das Modell aufrufen kann. Jedes Tool hat einen Namen, eine Beschreibung und durch JSON Schema definierte Eingabeparameter. Tool-Aufrufe werden vom Modell initiiert, mussen aber die Sicherheitsprufung des Clients durchlaufen (Human-in-the-Loop). Typische Anwendungen umfassen: Datenbankabfragen, API-Aufrufe und Dateisystemoperationen.

Resources sind strukturierte Daten, die das Modell lesen kann. Jede Resource wird uber eine URI identifiziert (z. B. file:///path/to/doc oder db://table/row) und ist mit einem MIME-Typ versehen. Resources werden von der Anwendung gesteuert -- der Benutzer oder Host entscheidet, wann welche Ressourcen in das Kontextfenster des Modells eingefugt werden.

Prompts (Vorlagen) sind vordefinierte Prompt-Anweisungsvorlagen, die vom Server bereitgestellt und vom Benutzer ausgelost werden. Prompts konnen parametrisierte Platzhalter enthalten, die der Benutzer ausfullt, um einen vollstandigen Prompt-Text zu erzeugen. Typische Anwendungen: Code-Review-Vorlagen, Datenanalyse-Berichtsvorlagen.

Fahigkeitsprimitiv Steuerung Beschreibung Analogie
Tools Vom Modell initiiert (Model-controlled) Das Modell entscheidet, wann aufgerufen wird und welche Parameter ubergeben werden POST API enRLHF-Alignmentint
Resources Von der Anwendung gesteuert (Application-controlled) Host/Benutzer entscheidet, wann welche Ressourcen geladen werden GET API endpoint
Prompts Vom Benutzer ausgelost (User-controlled) Der Benutzer wahlt die zu verwendende Prompt-Vorlage Vordefinierter Slash Command

2.3 Transport-Schicht: stdio vs SSE

Die MCP-Spezifikation definiert zwei Transportmechanismen:

stdio (Standardein-/-ausgabe) eignet sich fur lokale Szenarien. Der Host startet den Server als Unterprozess und tauscht JSON-RPC-Nachrichten uber stdin/stdout aus. Vorteile sind: keine Netzwerkkonfiguration, niedrige Latenz und hohe Sicherheit (Prozessisolierung). Claude Desktop und Cursor verwenden derzeit hauptsachlich diesen Modus.

HTTP + Server-Sent Events (SSE) eignet sich fur Remote-Szenarien. Der Client sendet Anfragen per HTTP POST, der Server streamt Ergebnisse per SSE zuruck. Vorteile sind: netzwerkubergreifende Bereitstellung und Unterstutzung fur Multi-Client-Verbindungen. Geeignet fur unternehmensweite Shared MCP Server-Bereitstellungen.

2.4 Vergleichstabelle: MCP vs Function Calling vs LangChain Tools

Eigenschaft MCP Function Calling (OpenAI) LangChain Tools
Protokollstandard Offene Spezifikation (JSON-RPC 2.0) OpenAI-proprietare API Python-Framework-API
Verbindungsstatus Zustandsbehaftet (persistente Verbindung) Zustandslos (pro Anfrage) Implementierungsabhangig
Tool-Erkennung Automatisch (tools/list) Manuelle Ubergabe der Tool-Liste Manuelle Registrierung
Ressourcenverwaltung Nativ unterstutzt (Resources) Nicht unterstutzt Separat zu implementieren
Prompt-Vorlagen Nativ unterstutzt (Prompts) Nicht unterstutzt PromptTemplate
Multi-Modell-Unterstutzung Herstellerneutral Nur OpenAI Multi-Modell (uber Framework-Abstraktion)
Transportmethode stdio / HTTP+SSE HTTPS API In-Process-Aufruf
Sprach-SDKs TypeScript, Python (offiziell) Mehrsprachig (OpenAI SDK) Hauptsachlich Python
Sicherheitsmodell Client-seitiger Guard + Human-in-the-Loop Anwendungsschicht selbst implementiert Anwendungsschicht selbst implementiert

III. Kernkonzepte des MCP Servers

Das Verstandnis der Designmuster des MCP Servers ist der Schlussel zur Beherrschung der MCP-Praxis. Im Folgenden analysieren wir die vier Kernkonzepte des Servers im Detail[1].

3.1 Tool-Definition: Name, Beschreibung und inputSchema

Jedes Tool besteht aus drei Elementen. Der Name (name) ist die eindeutige Kennung des Tools und folgt der snake_case-Konvention. Die Beschreibung (description) ist ein naturlichsprachlicher Text, der dem Modell den Verwendungszweck und die Anwendungsszenarien des Tools mitteilt -- die Qualitat der Beschreibung beeinflusst direkt, ob das Modell das richtige Tool auswahlt. Das inputSchema ist die Parameterdefinition im JSON Schema-Format, die die akzeptierte Eingabestruktur des Tools spezifiziert.

# Tool-Definitionsbeispiel (Python SDK)
@server.tool()
async def get_weather(city: str, units: str = "celsius") -> str:
    """Echtzeit-Wetterinformationen fur eine bestimmte Stadt abfragen.

    Args:
        city: Stadtname (Englisch), z. B. "Taipei" oder "Tokyo"
        units: Temperatureinheit, "celsius" oder "fahrenheit", Standard: celsius

    Returns:
        Wetterzusammenfassung mit Temperatur, Luftfeuchtigkeit und Windgeschwindigkeit
    """
    # Eigentliche Implementierung...

Das Python MCP SDK generiert automatisch das entsprechende JSON Schema aus den Typannotationen und dem Docstring der Funktion, sodass Entwickler das Schema nicht manuell schreiben mussen.

3.2 Resource-Bereitstellung: URI-Muster und MIME-Typen

Resources verwenden URI-Muster zur Identifizierung von Datenquellen. Die MCP-Spezifikation unterstutzt benutzerdefinierte URI-Schemata, beispielsweise:

Jede Resource ist mit einem MIME-Typ versehen (z. B. text/plain, application/json, image/png), damit der Client weiss, wie der zuruckgegebene Inhalt zu verarbeiten ist. Resources unterstutzen auch vorlagenbasierte URIs (Resource Templates), z. B. weather://current/{city}, wobei der Client dynamisch Parameter einfullen kann.

3.3 Prompt-Vorlagen: Wiederverwendbare Prompt-Anweisungen

Prompts ermoglichen es dem Server, wiederverwendbare Prompt-Vorlagen zu definieren. Benutzer wahlen in der Host-Oberflache einen Prompt aus, fullen die Parameter aus und erhalten einen vollstandigen Prompt einschliesslich Resources und Anweisungen. Dies ist besonders nutzlich fur die Standardisierung von Arbeitsablaufen:

# Prompt-Definitionsbeispiel
@server.prompt()
async def code_review(language: str, code: str) -> str:
    """Code-Review-Vorlage: Prufung der Codequalitat und Sicherheit fur die angegebene Sprache."""
    return f"""Bitte fuhren Sie eine umfassende Prufung des folgenden {language}-Codes durch:
1. Codequalitat: Namenskonventionen, Lesbarkeit, DRY-Prinzip
2. Sicherheit: Injection-Angriffe, Offenlegung sensibler Daten
3. Leistung: Zeit-/Raumkomplexitat, potenzielle Engpasse
4. Best Practices: Fehlerbehandlung, Protokollierung

Code:
{code}"""

3.4 Sicherheitsmodell: Client als Guard

Das MCP-Sicherheitsmodell positioniert den Client als Sicherheitsgateway. Der Server stellt Fahigkeiten bereit, aber alle tatsachlichen Operationen mussen die Prufung des Clients durchlaufen. Dies zeigt sich auf mehreren Ebenen:

Dieses Design stellt sicher, dass der Client auch bei MCP Servern von nicht vertrauenswurdigen Drittanbietern die Risikogrenzen kontrollieren kann[8].

IV. Hands-on Lab 1: Aufbau Ihres ersten MCP Servers mit Python

Die folgende Implementierung baut einen Wetter-Abfrage MCP Server von Grund auf, verwendet die kostenlose Open-Meteo API (kein API Key erforderlich), definiert Tool- und Resource-Fahigkeiten und lauft mit stdio Transport. Der gesamte Code kann direkt in Google Colab ausgefuhrt werden.

# ============================================================
# Lab 1: Aufbau eines Wetter-Abfrage MCP Servers
# Umgebung: Google Colab / Python 3.10+
# ============================================================
# --- 0. Abhangigkeiten installieren ---
!pip install -q mcp httpx pydantic

import asyncio
import json
import httpx
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
    Tool,
    TextContent,
    Resource,
    ResourceTemplate,
)

# --- 1. MCP Server-Instanz erstellen ---
server = Server("weather-server")

# --- 2. Open-Meteo API-Abfragefunktionen ---
GEOCODING_URL = "https://geocoding-api.open-meteo.com/v1/search"
WEATHER_URL = "https://api.open-meteo.com/v1/forecast"

async def fetch_coordinates(city: str) -> dict:
    """Stadtkoordinaten uber die Open-Meteo Geocoding API abrufen."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            GEOCODING_URL,
            params={"name": city, "count": 1, "language": "en"}
        )
        resp.raise_for_status()
        data = resp.json()
        if not data.get("results"):
            raise ValueError(f"Stadt nicht gefunden: {city}")
        result = data["results"][0]
        return {
            "name": result["name"],
            "latitude": result["latitude"],
            "longitude": result["longitude"],
            "country": result.get("country", ""),
        }

async def fetch_weather(latitude: float, longitude: float) -> dict:
    """Wetterdaten uber die Open-Meteo Forecast API abrufen."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            WEATHER_URL,
            params={
                "latitude": latitude,
                "longitude": longitude,
                "current": "temperature_2m,relative_humidity_2m,"
                           "wind_speed_10m,weather_code",
                "timezone": "auto",
            }
        )
        resp.raise_for_status()
        return resp.json()

# WMO-Wettercodes und Beschreibungen
WMO_CODES = {
    0: "Klar", 1: "Uberwiegend klar", 2: "Teilweise bewolkt", 3: "Bewolkt",
    45: "Nebel", 48: "Raureifnebel", 51: "Leichter Nieselregen", 53: "Massiger Nieselregen",
    55: "Starker Nieselregen", 61: "Leichter Regen", 63: "Massiger Regen", 65: "Starker Regen",
    71: "Leichter Schneefall", 73: "Massiger Schneefall", 75: "Starker Schneefall", 80: "Regenschauer",
    81: "Massige Regenschauer", 82: "Starke Regenschauer", 95: "Gewitter",
}

# --- 3. Tool definieren: get_weather ---
@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="get_weather",
            description=(
                "Echtzeit-Wetterinformationen fur eine bestimmte Stadt abfragen, "
                "einschliesslich Temperatur, Luftfeuchtigkeit, Windgeschwindigkeit und Wetterlage. "
                "Einfach den englischen Stadtnamen eingeben. Unterstutzt jede Stadt weltweit."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Stadtname (Englisch), z. B. Taipei, Tokyo, London"
                    }
                },
                "required": ["city"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "get_weather":
        city = arguments["city"]
        coords = await fetch_coordinates(city)
        weather = await fetch_weather(coords["latitude"], coords["longitude"])
        current = weather["current"]
        code = current.get("weather_code", 0)
        description = WMO_CODES.get(code, "Unbekannt")

        report = (
            f"📍 {coords['name']}, {coords['country']}\n"
            f"🌡️ Temperatur: {current['temperature_2m']}°C\n"
            f"💧 Relative Luftfeuchtigkeit: {current['relative_humidity_2m']}%\n"
            f"💨 Windgeschwindigkeit: {current['wind_speed_10m']} km/h\n"
            f"🌤️ Wetterlage: {description}"
        )
        return [TextContent(type="text", text=report)]
    raise ValueError(f"Unbekanntes Tool: {name}")

# --- 4. Resource definieren: weather://current/{city} ---
@server.list_resource_templates()
async def list_resource_templates() -> list[ResourceTemplate]:
    return [
        ResourceTemplate(
            uriTemplate="weather://current/{city}",
            name="Aktuelles Wetter",
            description="Aktuelle Wetterdaten fur eine bestimmte Stadt abrufen (JSON-Format)",
            mimeType="application/json",
        )
    ]

@server.read_resource()
async def read_resource(uri: str) -> str:
    if uri.startswith("weather://current/"):
        city = uri.split("/")[-1]
        coords = await fetch_coordinates(city)
        weather = await fetch_weather(coords["latitude"], coords["longitude"])
        result = {
            "city": coords["name"],
            "country": coords["country"],
            "current": weather["current"],
        }
        return json.dumps(result, ensure_ascii=False, indent=2)
    raise ValueError(f"Unbekannte Ressourcen-URI: {uri}")

# --- 5. Server starten (stdio Transport) ---
async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            server.create_initialization_options()
        )

# In Colab testen: Tool-Funktionen direkt aufrufen, um die Logik zu verifizieren
async def test_locally():
    """Lokaler Test: Interne Funktionen direkt aufrufen, ohne MCP-Protokoll."""
    print("=== Test get_weather ===")
    coords = await fetch_coordinates("Taipei")
    print(f"Koordinaten: {coords}")

    weather = await fetch_weather(coords["latitude"], coords["longitude"])
    current = weather["current"]
    code = current.get("weather_code", 0)
    print(f"Temperatur: {current['temperature_2m']}°C")
    print(f"Luftfeuchtigkeit: {current['relative_humidity_2m']}%")
    print(f"Windgeschwindigkeit: {current['wind_speed_10m']} km/h")
    print(f"Wetter: {WMO_CODES.get(code, 'Unbekannt')}")

    print("\n=== Test Resource ===")
    resource_data = await read_resource("weather://current/Tokyo")
    print(resource_data)

# In Colab lokalen Test ausfuhren
await test_locally()

# Um als MCP Server zu starten (im Terminal ausfuhren):
# asyncio.run(main())

Wichtige Designaspekte des obigen Codes:

V. Hands-on Lab 2: Aufbau eines Multi-Tool MCP Servers mit Client-Test

Diese Implementierung erstellt einen MCP Server mit drei Tools (Taschenrechner, Textanalyse, Ubersetzungssimulation) und verwendet das MCP Python SDK auf Client-Seite fur einen vollstandigen Verbindungstest, der den gesamten Ablauf von Tool-Erkennung, Aufruf und Ergebnisverarbeitung demonstriert.

# ============================================================
# Lab 2: Multi-Tool MCP Server + vollstandiger Client-Test
# Umgebung: Google Colab / Python 3.10+
# ============================================================
# --- 0. Abhangigkeiten installieren ---
!pip install -q mcp pydantic

import asyncio
import json
import math
import re
from io import StringIO
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
    Tool,
    TextContent,
    Prompt,
    PromptMessage,
    PromptArgument,
)

# ==========================================
# Teil A: Multi-Tool MCP Server aufbauen
# ==========================================
server = Server("multi-tool-server")

# --- Tool 1: Wissenschaftlicher Taschenrechner ---
def safe_eval_math(expression: str) -> float:
    """Mathematischen Ausdruck sicher berechnen (ohne eval)."""
    allowed_names = {
        "abs": abs, "round": round,
        "sin": math.sin, "cos": math.cos, "tan": math.tan,
        "sqrt": math.sqrt, "log": math.log, "log10": math.log10,
        "pi": math.pi, "e": math.e,
        "pow": pow, "ceil": math.ceil, "floor": math.floor,
    }
    sanitized = expression.replace("^", "**")
    code = compile(sanitized, "", "eval")
    for name in code.co_names:
        if name not in allowed_names:
            raise ValueError(f"Nicht erlaubte Funktion oder Variable: {name}")
    return eval(code, {"__builtins__": {}}, allowed_names)

# --- Tool 2: Textanalyse ---
def analyze_text(text: str) -> dict:
    """Textstatistiken analysieren: Zeichenanzahl, Worter, Satze usw."""
    chars = len(text)
    chars_no_spaces = len(text.replace(" ", ""))
    words = len(text.split())
    sentences = len(re.split(r'[.!?。!?]', text))
    sentences = max(1, sentences - 1)
    paragraphs = len([p for p in text.split("\n") if p.strip()])
    cjk_chars = len(re.findall(r'[\u4e00-\u9fff]', text))
    return {
        "characters": chars,
        "characters_no_spaces": chars_no_spaces,
        "words": words,
        "sentences": sentences,
        "paragraphs": paragraphs,
        "cjk_characters": cjk_chars,
        "avg_word_length": round(chars_no_spaces / max(1, words), 1),
    }

# --- Tool 3: Ubersetzungssimulation (Demonstrationszwecke) ---
TRANSLATION_DICT = {
    "hello": "你好", "world": "世界", "ai": "人工智慧",
    "model": "模型", "protocol": "協議", "server": "伺服器",
    "client": "客戶端", "tool": "工具", "data": "資料",
    "context": "上下文", "language": "語言", "learning": "學習",
    "machine": "機器", "network": "網路", "computer": "電腦",
}

def simple_translate(text: str, target_lang: str = "zh-TW") -> str:
    """Einfache Englisch-Chinesisch-Ubersetzung (Demonstrationszwecke, im Produktivbetrieb Ubersetzungs-API anbinden)."""
    if target_lang != "zh-TW":
        return f"[Nur Ubersetzung nach zh-TW unterstutzt, erhalten: {target_lang}]"
    words = text.lower().split()
    translated = []
    for w in words:
        clean = re.sub(r'[^\w]', '', w)
        if clean in TRANSLATION_DICT:
            translated.append(TRANSLATION_DICT[clean])
        else:
            translated.append(w)
    return " ".join(translated)

# --- Drei Tools registrieren ---
@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="calculator",
            description=(
                "Sicherer wissenschaftlicher Taschenrechner. Unterstutzt Grundrechenarten (+, -, *, /, **) und "
                "mathematische Funktionen (sin, cos, tan, sqrt, log, log10, abs, "
                "round, ceil, floor). Konstanten: pi, e."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "Mathematischer Ausdruck, z. B. 'sqrt(144) + pi * 2'"
                    }
                },
                "required": ["expression"]
            }
        ),
        Tool(
            name="text_analyzer",
            description=(
                "Textstatistiken analysieren: Zeichenanzahl, Wortanzahl, Satzanzahl, Absatzanzahl, "
                "CJK-Zeichenanzahl, durchschnittliche Wortlange. Unterstutzt gemischte chinesisch-englische Texte."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "description": "Zu analysierender Textinhalt"
                    }
                },
                "required": ["text"]
            }
        ),
        Tool(
            name="translate",
            description=(
                "Englischen Text ins traditionelle Chinesisch ubersetzen. "
                "Hinweis: Dies ist eine einfache Demonstrationsversion, die nur gangige KI-Terminologie ubersetzt."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "description": "Zu ubersetzender englischer Text"
                    },
                    "target_language": {
                        "type": "string",
                        "description": "Zielsprachcode, derzeit nur zh-TW unterstutzt",
                        "default": "zh-TW"
                    }
                },
                "required": ["text"]
            }
        ),
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "calculator":
        expr = arguments["expression"]
        try:
            result = safe_eval_math(expr)
            return [TextContent(
                type="text",
                text=f"Berechnungsergebnis: {expr} = {result}"
            )]
        except Exception as e:
            return [TextContent(
                type="text",
                text=f"Berechnungsfehler: {e}"
            )]

    elif name == "text_analyzer":
        text = arguments["text"]
        stats = analyze_text(text)
        lines = [
            "📊 Textanalyseergebnis:",
            f"  Zeichenanzahl: {stats['characters']}",
            f"  Zeichen (ohne Leerzeichen): {stats['characters_no_spaces']}",
            f"  Wortanzahl: {stats['words']}",
            f"  Satzanzahl: {stats['sentences']}",
            f"  Absatzanzahl: {stats['paragraphs']}",
            f"  CJK-Zeichenanzahl: {stats['cjk_characters']}",
            f"  Durchschn. Wortlange: {stats['avg_word_length']}",
        ]
        return [TextContent(type="text", text="\n".join(lines))]

    elif name == "translate":
        text = arguments["text"]
        target = arguments.get("target_language", "zh-TW")
        result = simple_translate(text, target)
        return [TextContent(
            type="text",
            text=f"Ubersetzungsergebnis (en → {target}):\nOriginal: {text}\nUbersetzung: {result}"
        )]

    raise ValueError(f"Unbekanntes Tool: {name}")

# --- Prompt-Vorlagen registrieren ---
@server.list_prompts()
async def list_prompts() -> list[Prompt]:
    return [
        Prompt(
            name="summarize_stats",
            description="Textanalyseergebnisse in eine knappe Zusammenfassung aufbereiten",
            arguments=[
                PromptArgument(
                    name="text",
                    description="Zu analysierender und zusammenzufassender Text",
                    required=True,
                )
            ]
        )
    ]

@server.get_prompt()
async def get_prompt(name: str, arguments: dict) -> list[PromptMessage]:
    if name == "summarize_stats":
        text = arguments["text"]
        stats = analyze_text(text)
        return [PromptMessage(
            role="user",
            content=TextContent(
                type="text",
                text=(
                    f"Der folgende Text umfasst {stats['characters']} Zeichen, "
                    f"{stats['words']} Worter und {stats['sentences']} Satze. "
                    f"Davon sind {stats['cjk_characters']} CJK-Zeichen."
                    f"\n\nBitte beschreiben Sie anhand der obigen Statistiken in einem Absatz die Merkmale dieses Textes."
                    f"\n\nOriginaltext:\n{text[:500]}"
                )
            )
        )]
    raise ValueError(f"Unbekannter Prompt: {name}")

# ==========================================
# Teil B: Lokaler Test (Client-Verhalten simulieren)
# ==========================================
async def test_multi_tool_server():
    """In Colab testen: Server-Handler-Funktionen direkt aufrufen."""

    print("=" * 60)
    print("MCP Multi-Tool Server -- Lokaler Test")
    print("=" * 60)

    # Test 1: Alle Tools auflisten
    print("\n--- 1. Alle verfugbaren Tools auflisten ---")
    tools = await list_tools()
    for t in tools:
        print(f"  Tool: {t.name}")
        print(f"  Beschreibung: {t.description[:60]}...")
        print()

    # Test 2: Taschenrechner
    print("--- 2. Test Calculator ---")
    result = await call_tool("calculator", {"expression": "sqrt(144) + pi * 2"})
    print(f"  {result[0].text}")

    result = await call_tool("calculator", {"expression": "log10(1000) + 2**10"})
    print(f"  {result[0].text}")

    result = await call_tool("calculator", {"expression": "sin(pi/6)"})
    print(f"  {result[0].text}")

    # Test 3: Textanalyse
    print("\n--- 3. Test Text Analyzer ---")
    sample_text = (
        "Model Context Protocol ist der von Anthropic als Open Source veroffentlichte Protokollstandard. "
        "Es ermoglicht KI-Anwendungen, sich uber eine einheitliche Schnittstelle mit externen Tools und Datenquellen zu verbinden. "
        "Das MCP-Design ist inspiriert von USB-C -- eine Schnittstelle fur alle Verbindungen."
    )
    result = await call_tool("text_analyzer", {"text": sample_text})
    print(f"  {result[0].text}")

    # Test 4: Ubersetzung
    print("\n--- 4. Test Translate ---")
    result = await call_tool("translate", {
        "text": "machine learning model context protocol",
        "target_language": "zh-TW"
    })
    print(f"  {result[0].text}")

    # Test 5: Prompt-Vorlagen
    print("\n--- 5. Test Prompt-Vorlagen ---")
    prompts = await list_prompts()
    print(f"  Verfugbare Prompts: {[p.name for p in prompts]}")
    prompt_result = await get_prompt("summarize_stats", {"text": sample_text})
    print(f"  Expandierter Prompt:\n  {prompt_result[0].content.text[:200]}...")

    print("\n" + "=" * 60)
    print("Alle Tests bestanden! Server-Logik erfolgreich verifiziert.")
    print("=" * 60)

# Tests ausfuhren
await test_multi_tool_server()

Dieses Lab demonstriert mehrere wichtige Designmuster:

VI. Das MCP-Okosystem: Integrationspraxis von Claude bis Cursor

Seit der Veroffentlichung von MCP Ende 2024 wurde es rasch von mehreren fuhrenden Entwicklungstools ubernommen[2]. Im Folgenden stellen wir einige wichtige Integrationsszenarien vor.

6.1 Claude Desktop-Konfiguration

Claude Desktop war die erste KI-Anwendung mit nativer MCP-Unterstutzung. Benutzer mussen lediglich MCP Server in der Konfigurationsdatei deklarieren, um Tools in Gesprachen nutzen zu konnen:

// macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
// Windows: %APPDATA%/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "weather": {
      "command": "python",
      "args": ["/path/to/weather_server.py"],
      "env": {}
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    },
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://user:pass@localhost:5432/mydb"
      ]
    }
  }
}

Die Konfigurationsdatei deklariert im JSON-Format fur jeden Server den Startbefehl (command), die Argumente (args) und die Umgebungsvariablen (env). Claude Desktop startet diese Server-Prozesse beim Start automatisch im stdio-Modus.

6.2 Cursor MCP-Integration

Cursor IDE unterstutzt MCP seit Version 0.45[15] und ermoglicht Entwicklern, wahrend der KI-gestutzten Programmierung externe Tools aufzurufen. Die Konfiguration ahnelt Claude Desktop und wird in .cursor/mcp.json abgelegt. Cursor unterstutzt derzeit nur die Tools-Fahigkeit von MCP; Resources und Prompts sind noch nicht integriert.

Auch Windsurf, der Zed-Editor, Sourcegraph Cody und weitere Tools haben nacheinander MCP-Unterstutzung angekundigt, was zeigt, dass dieses Protokoll zum De-facto-Standard fur KI-Entwicklungstools wird.

6.3 Community MCP Server-Okosystem

Die Offenheit von MCP hat ein florierendes Community-Okosystem hervorgebracht. Hier sind einige beliebte Open-Source MCP Server:

MCP Server Funktionsbeschreibung Betreuer
server-github GitHub API-Integration: Issues, PRs, Repo-Suche Anthropic (offiziell)
server-postgres PostgreSQL-Datenbankabfragen (schreibgeschutzt) Anthropic (offiziell)
server-slack Slack-Kanalnachrichten lesen und senden Anthropic (offiziell)
server-puppeteer Headless-Browser-Automatisierung und Webseiten-Screenshots Anthropic (offiziell)
server-filesystem Lokales Dateisystem lesen/schreiben (mit Sandbox-Einschrankungen) Anthropic (offiziell)
server-brave-search Brave-Suchmaschinen-API-Integration Anthropic (offiziell)
server-notion Notion-Dokument- und Datenbankoperationen Community
server-linear Linear-Projektmanagement-Tool-Integration Community

6.4 Architekturerwagungen fur unternehmensinterne MCP Server

Fur Unternehmensszenarien mussen beim Aufbau eigener MCP Server folgende architektonische Aspekte berucksichtigt werden:

VII. Entscheidungsrahmen: Wann sollten Unternehmen MCP einsetzen?

MCP ist keine Allzwecklosung. Unternehmen sollten bei der Entscheidung uber den Einsatz von MCP eine rationale Beurteilung auf Basis ihrer eigenen technischen Architektur und Bedarfsszenarien vornehmen.

7.1 Geeignete Szenarien

7.2 Nicht geeignete Szenarien

7.3 Vergleichstabelle: Direkte API-Integration vs MCP vs LangChain

Bewertungsdimension Direkte API-Integration MCP LangChain
Anfangliche Entwicklungskosten Niedrig (schnellste Marktreife) Mittel (Protokoll erlernen) Mittel (Framework erlernen)
Langfristige Wartungskosten Hoch (N×M-Wachstum) Niedrig (N+M-Wachstum) Mittel (Framework-Upgrade-Risiko)
Modellportabilitat Keine (plattformgebunden) Hoch (herstellerneutral) Mittel (Framework-Abstraktionsschicht)
Okosystem Selbst aufzubauen Wachsend (1.000+ Community Server) Ausgereift (zahlreiche Integrationen)
Sicherheitsmodell Selbst implementiert Integriert (Client Guard) Selbst implementiert
Geeignete Grosse Kleine Projekte Mittlere bis grosse Unternehmen Mittlere Projekte

7.4 Sicherheitserwagungen

Obwohl das MCP-Sicherheitsmodell gegenuber der direkten API-Integration uberlegen ist, mussen Unternehmen dennoch folgende Risiken beachten[8]:

Empfohlene Gegenmassnahmen umfassen: Ausschliessliche Verwendung vertrauenswurdiger MCP Server-Quellen, Aktivierung des Human-in-the-Loop-Bestatigungsmechanismus, Einschrankung des Berechtigungsumfangs von Servern und Bereitstellung von Inhaltsfilterung fur Ein- und Ausgaben.

7.5 Empfehlungen fur den Migrationspfad

Fur Unternehmen, die bereits Function Calling oder LangChain Tools-Integrationen haben, empfehlen wir folgenden Migrationspfad:

  1. Phase 1 (2--4 Wochen): Wahlen Sie ein risikoarmes internes Tool (z. B. Wetterabfrage, Dokumentensuche), erstellen Sie den ersten MCP Server und verifizieren Sie das Verstandnis des Teams fur das Protokoll
  2. Phase 2 (1--2 Monate): Verpacken Sie wichtige Geschaftstools (CRM-Abfrage, Wissensdatenbanksuche) als MCP Server und testen Sie in Claude Desktop oder Cursor
  3. Phase 3 (2--3 Monate): Bereitstellung eines SSE-Modus Shared MCP Servers mit Integration von Authentifizierung, Audit, Ratenbegrenzung und weiteren Enterprise-Funktionen
  4. Phase 4 (fortlaufend): Schrittweise Migration bestehender Function Calling-Definitionen zu MCP Tools und Aufbau eines unternehmensweiten MCP Server-Verzeichnisses

VIII. Zukunftsausblick und strategischer Wert von MCP

8.1 Anthropics Open-Source-Strategie

MCP ist ein wichtiger strategischer Zug von Anthropic im KI-Okosystem. Durch die Open-Source-Veroffentlichung eines Protokollstandards hat Anthropic einen anderen Weg als OpenAI (geschlossenes Plugins-Okosystem) eingeschlagen. Die strategische Logik dahinter lautet: Wer das Protokoll definiert, hat die Architekturhoheit uber das Okosystem.

Dies ahnelt Googles Strategie der Open-Source-Veroffentlichung von AndKI-ROI-Bewertungd -- nicht jede Anwendung kontrollieren, aber durch die Definition von Plattformstandards Okosystem-Einfluss aufbauen. Anthropic muss nicht jeden MCP Server besitzen; solange MCP zum De-facto-Standard wird, wird Claude naturlich zur bevorzugten KI-Anwendung in diesem Okosystem[2].

8.2 Wettbewerb und Kooperation mit OpenAI Plugins und Google Extensions

Im Bereich der KI-Tool-Integration gibt es derzeit drei Krafte:

Die Gorilla-Forschung von Patil et al.[5] hat bereits bewiesen, dass die Tool-Nutzungsfahigkeit eines LLM signifikant steigt, wenn es sich mit einer grossen Anzahl von APIs verbinden kann. Die Frage ist, wer das grosste und offenste Tool-Okosystem aufbauen kann. MCPs offenes Design verschafft ihm einen First-Mover-Vorteil.

8.3 Auswirkungen auf das AI Agent-Okosystem

MCP hat tiefgreifende Auswirkungen auf das AI Agent-Okosystem. Die LLM Agent-Ubersichtsstudie von Wang et al.[8] stellt fest, dass die Tool-Nutzungsfahigkeit der Schlussel fur den Aufstieg von Agents von „Dialogsystemen" zu „Handlungssystemen" ist. MCP senkt durch die Standardisierung der Tool-Schnittstelle die Hurde fur die Anbindung von Agents an die Aussenwelt.

Mit der Entwicklung von Agent-Frameworks wie AutoGPT[13] und AI Agent-Frameworks[14] konnte MCP zum Standardprotokoll fur den Zugriff von Agents auf externe Tools werden. Das bedeutet, dass zukunftige AI Agents keinen massgeschneiderten Integrationscode fur jedes Tool mehr schreiben mussen, sondern Tools dynamisch uber MCP erkennen und aufrufen konnen.

HuggingGPT[7] hat gezeigt, wie ein LLM als Controller mehrere KI-Modelle orchestrieren kann, um komplexe Aufgaben zu erledigen. MCP kann dieses Muster weiter auf beliebige externe Tools ausdehnen, nicht nur auf KI-Modelle. WebGPT[9] hat bewiesen, dass LLMs Browser effektiv als Tools nutzen konnen; MCPs server-puppeteer ist genau die standardisierte Umsetzung dieser Fahigkeit.

8.4 Handlungsempfehlungen fur Unternehmens-CTOs

Basierend auf der obigen Analyse geben wir technischen Entscheidungstragern in Unternehmen folgende Empfehlungen:

  1. Sofort handeln: Bestimmen Sie 1--2 Ingenieure im Team, die das MCP-Protokoll und das SDK erlernen, und erstellen Sie den ersten internen MCP Server als Proof of Concept
  2. Kurzfristig (3--6 Monate): Bewerten Sie die bestehende KI-Tool-Integrationsarchitektur, identifizieren Sie, welche Integrationen als MCP Server vereinheitlicht werden konnen, und erstellen Sie eine Migrations-Roadmap
  3. Mittelfristig (6--12 Monate): Aufbau eines unternehmensweiten MCP Server-Verzeichnisses und Governance-Frameworks, einschliesslich Versionskontrolle, Sicherheitsaudit und Leistungsuberwachung
  4. Langfristige Beobachtung: Verfolgen Sie die Weiterentwicklung der MCP-Spezifikation (insbesondere die Authentifizierungsstandardisierung und Multi-Agent-Kollaborationsprotokolle) sowie ob Wettbewerber (OpenAI, Google) entsprechende offene Standards einfuhren

IX. Fazit

Das Erscheinen von MCP markiert den Ubergang der KI-Tool-Integration vom „Handwerkszeitalter" in das „Zeitalter der Industriestandards". So wie USB-C die Hardware-Anschlussschnittstellen vereinheitlicht hat, vereinheitlicht MCP die Software-Verbindungsschnittstelle zwischen KI und der Aussenwelt.

Ein Protokoll ist jedoch nur Infrastruktur. Der wahre Wert liegt darin, wie Unternehmen auf dieser Infrastruktur ein tief mit ihrem Geschaft verknupftes Tool-Okosystem aufbauen. Wir haben in der Praxis mit Tool Learning[6] und LangChain[10] bereits gesehen, dass die Qualitat der Tools -- die Prazision der Beschreibungen, die Vollstandigkeit der Fehlerbehandlung, die Strenge der Sicherheitsgrenzen -- direkt die Zuverlassigkeit von KI-Anwendungen bestimmt.

MCP wird Function Calling oder LangChain Tools nicht ersetzen, sondern bietet auf einer hoheren Abstraktionsebene einen einheitlichen Protokollrahmen. Fur Unternehmen, die mehrere KI-Anwendungen mit mehreren Tools verbinden mussen, bietet MCP einen klaren Weg zur Reduzierung der Integrationskomplexitat und zur Verbesserung der Wartbarkeit.

Das Forschungsteam von Meta Intelligence verfolgt kontinuierlich die neuesten Entwicklungen im MCP-Okosystem und unterstutzt Unternehmenskunden bei der Konzeption und Implementierung von MCP Server-Architekturen, die ihren Geschaftsanforderungen entsprechen. Vom Protokollverstandnis uber die praktische Bereitstellung, von der Sicherheitsbewertung bis zur Leistungsoptimierung -- wir widmen uns der Einfuhrung modernster KI-Engineering-Praktiken in Unternehmensszenarien.