MCP (Model Context Protocol): Der Standard der KI mit allen Tools verbindet
Umfassender Leitfaden zum Model Context Protocol (MCP) von Anthropic: Client/Server-Architektur, Aufbau eines MCP-Servers fuer RAG, Vergleich mit Function Calling und LangChain Tools.
TL;DR
Das Model Context Protocol (MCP) ist ein offener Standard von Anthropic, der es LLMs ermoeglicht, sich ueber eine einheitliche Schnittstelle mit beliebigen Tools oder Datenquellen zu verbinden. 2026 wird MCP von Claude Desktop, Cursor, Windsurf, VS Code und vielen anderen Clients unterstuetzt. Dieser Leitfaden erklaert die MCP-Architektur, zeigt wie man einen MCP-Server fuer RAG baut und vergleicht MCP mit Alternativen (Function Calling, LangChain Tools).
Was ist MCP?
Das Problem das MCP loest
Vor MCP erforderte die Verbindung eines LLM mit Tools eine individuelle Integration fuer jede LLM-Tool-Kombination:
VOR MCP (N x M Integrationen):
┌──────────┐ ┌──────────┐
│ Claude │────→│ Slack │ Custom Integration 1
│ Claude │────→│ GitHub │ Custom Integration 2
│ GPT-4 │────→│ Slack │ Custom Integration 3
│ GPT-4 │────→│ GitHub │ Custom Integration 4
└──────────┘ └──────────┘
= 4 Integrationen fuer 2 LLMs x 2 Tools
MIT MCP (N + M Integrationen):
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Claude │────→│ MCP │←────│ Slack │ 1 MCP Server
│ GPT-4 │────→│ Protokoll│←────│ GitHub │ 1 MCP Server
└──────────┘ └──────────┘ └──────────┘
= 2 Clients + 2 Server = 4 Komponenten (vs. 4 Integrationen)
MCP-Architektur
┌─────────────────────────────────────────────────────┐
│ MCP CLIENT │
│ (Claude Desktop, Cursor, VS Code, Ihre App) │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Server 1 │ │ Server 2 │ │ Server 3 │ │
│ │ (GitHub) │ │ (RAG) │ │ (Slack) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Resources│ │ Tools │ │ Prompts │ │
│ │ (Repos) │ │ (Suche) │ │(Vorlagen)│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────┘
Die 3 MCP-Primitiven
| Primitive | Beschreibung | Beispiel | Kontrolliert durch |
|---|---|---|---|
| Resources | Dem LLM exponierte Daten (Lesen) | Dateien, DBs, API-Antworten | Anwendung (Client) |
| Tools | Aktionen die das LLM ausfuehren kann | Suche, Schreiben, Senden | Modell (LLM) |
| Prompts | Wiederverwendbare Vorlagen | Codeanalyse, Zusammenfassung | Benutzer |
Das MCP-Oekosystem 2026
Client-Adoption
| Client | MCP-Support | Status | Anmerkungen |
|---|---|---|---|
| Claude Desktop | Nativ | Produktion | Erster MCP-Client |
| Cursor | Nativ | Produktion | KI-IDE mit integriertem MCP |
| Windsurf | Nativ | Produktion | Konkurrierende KI-IDE |
| VS Code (Copilot) | Plugin | Produktion | Ueber MCP-Erweiterung |
| Continue.dev | Nativ | Produktion | Open Source IDE |
| Zed | Nativ | Beta | Schneller Editor |
| Claude Code | Nativ | Produktion | CLI mit MCP |
| Cline | Nativ | Produktion | VS Code Agent |
Populaere Community MCP-Server
| Server | Funktion |
|---|---|
| mcp-server-github | Repos, Issues, PRs |
| mcp-server-filesystem | Datei Lesen/Schreiben |
| mcp-server-postgres | PostgreSQL-Abfragen |
| mcp-server-slack | Nachrichten, Kanaele |
| mcp-server-google-drive | Google Drive Dateien |
| mcp-server-notion | Notion-Seiten und Datenbanken |
| mcp-server-puppeteer | Web-Browsing |
| mcp-server-memory | Persistenter Speicher |
| mcp-server-brave-search | Websuche |
| mcp-server-qdrant | Vektordatenbank |
Einen MCP-Server fuer RAG bauen
RAG MCP-Server in Python
DEVELOPERpythonfrom mcp.server import Server, NotificationOptions from mcp.server.models import InitializationOptions from mcp.types import ( Resource, Tool, TextContent, ) import mcp.server.stdio import json # MCP-Server erstellen server = Server("rag-server") # ============ RESOURCES ============ @server.list_resources() async def list_resources() -> list[Resource]: """Listet verfuegbare Datenquellen auf.""" return [ Resource( uri="rag://knowledge-base/status", name="Status der Wissensbasis", description="Statistiken ueber indexierte Dokumente", mimeType="application/json", ), Resource( uri="rag://knowledge-base/sources", name="Indexierte Quellen", description="Liste der aktiven Datenquellen", mimeType="application/json", ), ] @server.read_resource() async def read_resource(uri: str) -> str: if uri == "rag://knowledge-base/status": stats = await get_kb_stats() return json.dumps({ "total_documents": stats.total_docs, "total_chunks": stats.total_chunks, "last_updated": stats.last_update.isoformat(), "embedding_model": "text-embedding-3-small", "vector_db": "Qdrant", }) elif uri == "rag://knowledge-base/sources": sources = await get_active_sources() return json.dumps([ {"name": s.name, "type": s.type, "doc_count": s.count} for s in sources ]) raise ValueError(f"Unbekannte Ressource: {uri}") # ============ TOOLS ============ @server.list_tools() async def list_tools() -> list[Tool]: """Listet verfuegbare RAG-Tools auf.""" return [ Tool( name="search_knowledge_base", description=( "Durchsucht die Wissensbasis. " "Verwendet semantische Suche, um " "die relevantesten Dokumente zu finden." ), inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "Die Frage oder das zu suchende Thema" }, "top_k": { "type": "integer", "description": "Anzahl der Ergebnisse (Standard: 5)", "default": 5 }, "filter_source": { "type": "string", "description": "Nach Quelle filtern (optional)" } }, "required": ["query"] } ), Tool( name="add_document", description=( "Fuegt ein Dokument zur Wissensbasis hinzu. " "Das Dokument wird automatisch aufgeteilt und indexiert." ), inputSchema={ "type": "object", "properties": { "content": { "type": "string", "description": "Der Dokumentinhalt" }, "title": { "type": "string", "description": "Der Dokumenttitel" }, "source": { "type": "string", "description": "Die Dokumentquelle" } }, "required": ["content", "title"] } ), Tool( name="get_answer", description=( "Stellt eine Frage und erhaelt eine Antwort " "basierend auf der Wissensbasis (vollstaendiges RAG)." ), inputSchema={ "type": "object", "properties": { "question": { "type": "string", "description": "Die zu stellende Frage" }, "context": { "type": "string", "description": "Zusaetzlicher Kontext (optional)" } }, "required": ["question"] } ), ] @server.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: """Fuehrt ein RAG-Tool aus.""" if name == "search_knowledge_base": results = await search_vectors( query=arguments["query"], top_k=arguments.get("top_k", 5), filter_source=arguments.get("filter_source"), ) formatted = [] for i, r in enumerate(results): formatted.append( f"[Ergebnis {i+1}] (Score: {r.score:.2f})\n" f"Quelle: {r.metadata.get('source', 'N/A')}\n" f"Inhalt: {r.text}\n" ) return [TextContent( type="text", text="\n---\n".join(formatted) or "Keine Ergebnisse gefunden." )] elif name == "add_document": doc_id = await index_document( content=arguments["content"], title=arguments["title"], source=arguments.get("source", "manual"), ) return [TextContent( type="text", text=f"Dokument erfolgreich hinzugefuegt (ID: {doc_id})" )] elif name == "get_answer": answer = await rag_pipeline( question=arguments["question"], context=arguments.get("context", ""), ) return [TextContent( type="text", text=f"Antwort: {answer.text}\n\n" f"Quellen: {', '.join(answer.sources)}" )] raise ValueError(f"Unbekanntes Tool: {name}") # ============ MAIN ============ async def main(): async with mcp.server.stdio.stdio_server() as (read, write): await server.run( read, write, InitializationOptions( server_name="rag-server", server_version="1.0.0", capabilities=server.get_capabilities( notification_options=NotificationOptions(), experimental_capabilities={}, ), ), ) if __name__ == "__main__": import asyncio asyncio.run(main())
Konfiguration in Claude Desktop
DEVELOPERjson{ "mcpServers": { "rag-knowledge-base": { "command": "python", "args": ["/path/to/rag_mcp_server.py"], "env": { "QDRANT_URL": "http://localhost:6333", "OPENAI_API_KEY": "sk-..." } }, "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..." } } } }
MCP-Server mit FastMCP (vereinfacht)
DEVELOPERpythonfrom fastmcp import FastMCP mcp = FastMCP("RAG Assistent") @mcp.tool() async def search_docs(query: str, top_k: int = 5) -> str: """Durchsucht die RAG-Wissensbasis.""" results = await vector_search(query, top_k) return "\n\n".join( f"[{i+1}] {r.text} (Score: {r.score:.2f})" for i, r in enumerate(results) ) @mcp.tool() async def ask_rag(question: str) -> str: """Stellt eine Frage an das RAG-System.""" answer = await rag_pipeline(question) return f"{answer.text}\n\nQuellen: {answer.sources}" @mcp.resource("rag://stats") async def get_stats() -> str: """Statistiken der Wissensbasis.""" stats = await get_kb_stats() return f"{stats.total_docs} Dokumente, {stats.total_chunks} Chunks" if __name__ == "__main__": mcp.run()
MCP vs. Alternativen
Vergleichstabelle
| Kriterium | MCP | OpenAI Function Calling | LangChain Tools | Custom API |
|---|---|---|---|---|
| Offener Standard | Ja (Anthropic) | Nein (proprietaer) | Nein (Framework) | Nein |
| Interoperabilitaet | Jeder MCP-Client | Nur OpenAI | Nur LangChain | Custom |
| Architektur | Client/Server | Request/Response | Kette | REST/GraphQL |
| Discovery | Automatisch (list_tools) | JSON Schema | Deklarativ | Dokumentation |
| Streaming | Ja (SSE) | Ja | Ja | Moeglich |
| Stateful | Ja (Sitzung) | Nein | Ja (Memory) | Moeglich |
| Resources (Daten) | Ja (native Primitive) | Nein | Nein | Custom |
| Prompt-Vorlagen | Ja (native Primitive) | Nein | Ja (PromptTemplate) | Nein |
| Sicherheit | Granulaere Kontrolle | Begrenzt | Begrenzt | Custom |
| Oekosystem | 100+ Server | N/A | 500+ Tools | N/A |
| Setup-Komplexitaet | Mittel | Einfach | Einfach | Hoch |
Wann was verwenden
| Anwendungsfall | Empfohlene Loesung | Grund |
|---|---|---|
| App mit einem LLM (OpenAI) | Function Calling | Einfacher, nativ |
| App mit mehreren LLMs | MCP | Interoperabler Standard |
| Schneller Prototyp | LangChain Tools | Schnelles Setup, grosses Oekosystem |
| IDE / Desktop-App | MCP | Fertiges Server-Oekosystem |
| Komplexe RAG-Pipeline | MCP + LangChain | Kombination der Staerken |
| Oeffentliche API | Custom API + MCP Wrapper | Maximale Flexibilitaet |
Migration von Function Calling zu MCP
DEVELOPERpython# VORHER: OpenAI Function Calling tools = [ { "type": "function", "function": { "name": "search_knowledge_base", "description": "Durchsucht die Wissensbasis", "parameters": { "type": "object", "properties": { "query": {"type": "string"} }, "required": ["query"] } } } ] response = openai.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, ) # NACHHER: MCP (wiederverwendbar durch jeden MCP-Client) @server.list_tools() async def list_tools(): return [Tool( name="search_knowledge_base", description="Durchsucht die Wissensbasis", inputSchema={ "type": "object", "properties": { "query": {"type": "string"} }, "required": ["query"] } )] # Gleiche Logik, aber zugaenglich fuer Claude Desktop, # Cursor, VS Code und jeden MCP-Client
Fortgeschrittene Anwendungsfaelle
MCP + Agentisches RAG
MCP mit einem RAG-Agenten fuer komplexe Workflows kombinieren:
DEVELOPERpython# RAG-Agent mit Zugriff auf mehrere MCP-Server class RAGAgent: def __init__(self): self.mcp_clients = { "rag": MCPClient("rag-server"), "github": MCPClient("github-server"), "slack": MCPClient("slack-server"), } async def process_query(self, query: str) -> str: # 1. In der RAG-Wissensbasis suchen docs = await self.mcp_clients["rag"].call_tool( "search_knowledge_base", {"query": query, "top_k": 5} ) # 2. Bei Bedarf Code auf GitHub suchen if "code" in query.lower(): code = await self.mcp_clients["github"].call_tool( "search_code", {"query": query, "repo": "my-org/my-repo"} ) docs += f"\n\nGefundener Code:\n{code}" # 3. Antwort generieren response = await self.generate(query, docs) # 4. Optional: auf Slack posten if self.should_notify(query): await self.mcp_clients["slack"].call_tool( "post_message", { "channel": "#support", "text": f"Anfrage bearbeitet: {query[:100]}..." } ) return response
MCP fuer RAG-Datenanreicherung
DEVELOPERpython@mcp.tool() async def enrich_and_index(url: str) -> str: """Ruft ein Web-Dokument ab, reichert es an und indexiert es.""" # 1. Inhalt abrufen content = await fetch_url(url) # 2. Metadaten extrahieren metadata = { "url": url, "title": extract_title(content), "date": extract_date(content), "language": detect_language(content), "summary": await generate_summary(content), } # 3. Aufteilen und indexieren chunks = chunk_document(content, chunk_size=500) doc_id = await index_chunks(chunks, metadata) return f"Indexiert: {metadata['title']} ({len(chunks)} Chunks)"
Sicherheit und Best Practices
MCP-Sicherheitsprinzipien
| Prinzip | Beschreibung | Implementierung |
|---|---|---|
| Geringste Berechtigung | Jeder Server greift nur auf das Noetige zu | Granulaere Berechtigungen pro Tool |
| Benutzereinwilligung | Benutzer genehmigt sensible Aktionen | Bestaetigung vor Schreiben/Senden |
| Isolation | Server sind voneinander isoliert | Separate Prozesse, kein geteilter Speicher |
| Audit | Alle Aktionen werden protokolliert | Logging jedes Tool-Aufrufs |
| Validierung | Eingaben werden serverseitig validiert | JSON Schema + benutzerdefinierte Validierung |
Sicherheits-Checkliste
DEVELOPERpython# Eingabevalidierung in einem MCP-Server @server.call_tool() async def call_tool(name: str, arguments: dict): # 1. Argument-Schema validieren validate_schema(name, arguments) # 2. Berechtigungen pruefen if name in WRITE_TOOLS and not user_has_write_permission(): raise PermissionError("Schreiben nicht autorisiert") # 3. Rate Limiting if not rate_limiter.check(name): raise RateLimitError("Zu viele Anfragen") # 4. Eingaben bereinigen sanitized = sanitize_inputs(arguments) # 5. Aktion protokollieren audit_log(name, sanitized, user_id) # 6. Ausfuehren return await execute_tool(name, sanitized)
MCP-Adoptionstimeline
Nov. 2024: Anthropic veroeffentlicht MCP (Open Source)
Q1 2025: Claude Desktop unterstuetzt MCP nativ; OpenAI uebernimmt MCP (Agents SDK, ChatGPT Desktop)
Q2 2025: Google DeepMind uebernimmt MCP fuer Gemini; Cursor, Windsurf, Continue.dev, VS Code integrieren MCP
Nov. 2025: Spezifikation 2025-11-25 (OAuth-Autorisierung, Elicitation)
Dez. 2025: MCP an die Agentic AI Foundation (Linux Foundation) uebergeben, mitbegruendet von Anthropic, Block und OpenAI
2026: Enterprise-Adoption (Salesforce); grosse Revision hin zu einem Stateless-Core (Erweiterungen MCP Apps und Tasks)
Weiterfuehrende Ressourcen
- RAG-Agenten und Orchestrierung: Der uebergeordnete Leitfaden zu Agenten
- Small Language Models fuer RAG: SLMs und MCP kombinieren
- RAG Observability: Monitoring von MCP-Aufrufen
- RAG Guardrails: MCP-Tools absichern
- RAG und Notion: Beispiel einer MCP + RAG Integration
FAQ
Ersetzt MCP das Function Calling von OpenAI?
Nein, MCP und Function Calling loesen unterschiedliche, aber komplementaere Probleme. Function Calling ist anbieterspezifisch (OpenAI, Anthropic) und definiert, wie das LLM eine Funktion aufruft. MCP ist ein Kommunikationsstandard zwischen Client und Tool-Servern, unabhaengig vom LLM. Sie koennen MCP mit Function Calling darunter verwenden. Der Vorteil von MCP ist die Interoperabilitaet: Ein MCP-Server funktioniert mit allen kompatiblen Clients.
Kann ich MCP mit GPT-4o oder anderen nicht-Anthropic LLMs verwenden?
Ja. MCP ist ein offenes Protokoll, keine Claude-exklusive Funktion. Clients wie Cursor und Continue.dev verwenden MCP mit GPT-4o, Gemini und anderen Modellen. Die clientseitige Implementierung uebersetzt MCP-Tools in native Function Calls des verwendeten LLM. Die Integration ist allerdings am natuerlichsten mit Claude Desktop.
Wie lange dauert es, einen MCP-Server zu bauen?
Ein einfacher MCP-Server (2-3 Tools) kann in 1-2 Stunden mit FastMCP oder dem offiziellen Python-SDK gebaut werden. Ein komplexerer Server mit Resources, Prompts und erweiterter Fehlerbehandlung dauert 1-3 Tage. Die Lernkurve ist moderat, wenn Sie mit asynchronen Python-APIs vertraut sind.
Ist MCP sicher fuer den Produktionseinsatz?
MCP enthaelt Sicherheitsmechanismen: Prozessisolierung, Schema-Validierung und das Prinzip der geringsten Berechtigung. Die Sicherheit haengt jedoch weitgehend von Ihrer serverseitigen Implementierung ab. Validieren Sie immer Eingaben, implementieren Sie Rate Limiting und protokollieren Sie alle Aktionen. Fuer sensible Daten fuehren Sie MCP-Server in einer isolierten Umgebung aus (Docker, VM).
Unterstuetzt Ailog das MCP-Protokoll?
Ailog arbeitet aktiv an der MCP-Integration. Die RAG-API von Ailog kann bereits als MCP-Server exponiert werden, sodass Claude Desktop, Cursor oder jeder kompatible Client Ihre Ailog-Wissensbasis direkt abfragen kann. Dies eroeffnet Workflows, bei denen Ihr KI-Assistent in Ihren Ailog-Daten suchen kann, ohne seine gewohnte Oberflaeche zu verlassen.
Tags
Verwandte Artikel
RAG-Agenten: Orchestrierung von Multi-Agenten-Systemen
Konzipieren Sie RAG-basierte Multi-Agenten-Systeme: Orchestrierung, Spezialisierung, Zusammenarbeit und Fehlerbehandlung für komplexe Assistenten.
Konversationelles RAG: Gedächtnis und Kontext über mehrere Sitzungen
Implementieren Sie ein RAG mit konversationellem Gedächtnis: Verwaltung des Kontexts, Verlauf über mehrere Sitzungen und Personalisierung der Antworten.
Agentic RAG 2025: Aufbau autonomer KI-Agenten (Kompletter Leitfaden)
Kompletter Agentic RAG-Leitfaden: Architektur, Design Patterns, autonome Agenten mit dynamischem Retrieval, Multi-Tool-Orchestrierung. Mit Beispielen LangGraph und CrewAI.