AnleitungExperte

MCP (Model Context Protocol): Der Standard der KI mit allen Tools verbindet

29. Juli 2026
22 Minuten Lesezeit
Ailog Team

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

PrimitiveBeschreibungBeispielKontrolliert durch
ResourcesDem LLM exponierte Daten (Lesen)Dateien, DBs, API-AntwortenAnwendung (Client)
ToolsAktionen die das LLM ausfuehren kannSuche, Schreiben, SendenModell (LLM)
PromptsWiederverwendbare VorlagenCodeanalyse, ZusammenfassungBenutzer

Das MCP-Oekosystem 2026

Client-Adoption

ClientMCP-SupportStatusAnmerkungen
Claude DesktopNativProduktionErster MCP-Client
CursorNativProduktionKI-IDE mit integriertem MCP
WindsurfNativProduktionKonkurrierende KI-IDE
VS Code (Copilot)PluginProduktionUeber MCP-Erweiterung
Continue.devNativProduktionOpen Source IDE
ZedNativBetaSchneller Editor
Claude CodeNativProduktionCLI mit MCP
ClineNativProduktionVS Code Agent

Populaere Community MCP-Server

ServerFunktion
mcp-server-githubRepos, Issues, PRs
mcp-server-filesystemDatei Lesen/Schreiben
mcp-server-postgresPostgreSQL-Abfragen
mcp-server-slackNachrichten, Kanaele
mcp-server-google-driveGoogle Drive Dateien
mcp-server-notionNotion-Seiten und Datenbanken
mcp-server-puppeteerWeb-Browsing
mcp-server-memoryPersistenter Speicher
mcp-server-brave-searchWebsuche
mcp-server-qdrantVektordatenbank

Einen MCP-Server fuer RAG bauen

RAG MCP-Server in Python

DEVELOPERpython
from 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)

DEVELOPERpython
from 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

KriteriumMCPOpenAI Function CallingLangChain ToolsCustom API
Offener StandardJa (Anthropic)Nein (proprietaer)Nein (Framework)Nein
InteroperabilitaetJeder MCP-ClientNur OpenAINur LangChainCustom
ArchitekturClient/ServerRequest/ResponseKetteREST/GraphQL
DiscoveryAutomatisch (list_tools)JSON SchemaDeklarativDokumentation
StreamingJa (SSE)JaJaMoeglich
StatefulJa (Sitzung)NeinJa (Memory)Moeglich
Resources (Daten)Ja (native Primitive)NeinNeinCustom
Prompt-VorlagenJa (native Primitive)NeinJa (PromptTemplate)Nein
SicherheitGranulaere KontrolleBegrenztBegrenztCustom
Oekosystem100+ ServerN/A500+ ToolsN/A
Setup-KomplexitaetMittelEinfachEinfachHoch

Wann was verwenden

AnwendungsfallEmpfohlene LoesungGrund
App mit einem LLM (OpenAI)Function CallingEinfacher, nativ
App mit mehreren LLMsMCPInteroperabler Standard
Schneller PrototypLangChain ToolsSchnelles Setup, grosses Oekosystem
IDE / Desktop-AppMCPFertiges Server-Oekosystem
Komplexe RAG-PipelineMCP + LangChainKombination der Staerken
Oeffentliche APICustom API + MCP WrapperMaximale 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

PrinzipBeschreibungImplementierung
Geringste BerechtigungJeder Server greift nur auf das Noetige zuGranulaere Berechtigungen pro Tool
BenutzereinwilligungBenutzer genehmigt sensible AktionenBestaetigung vor Schreiben/Senden
IsolationServer sind voneinander isoliertSeparate Prozesse, kein geteilter Speicher
AuditAlle Aktionen werden protokolliertLogging jedes Tool-Aufrufs
ValidierungEingaben werden serverseitig validiertJSON 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

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

RAGMCPModel Context ProtocolAnthropicToolsAgentenIntegrationAPI

Verwandte Artikel

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !