FastMCP Server + LangChain MCP-Integration in der Praxis

FastMCP + LangChain: MCP-Server in 15 Zeilen, langchain-mcp-adapters für LangGraph-Agents, Production-Hardening mit Auth, Rate-Limits und Audit-Trail. Code aus Pexon-Projekten.

8 Aug.. 2026 | AI

Inhaltsverzeichnis

Phillip Pham | 11 Min. Lesezeit | 08.06.2026


TL;DR

FastMCP LangChain Integration ist 2026 der pragmatischste Weg, MCP-Server produktiv zu bauen und in Agent-Pipelines einzubinden. FastMCP reduziert den MCP-Server-Boilerplate um 80%, langchain-mcp-adapters macht aus den Tools eine LangChain-/LangGraph-kompatible Tool-Liste. Pexon Consulting setzt diese Kombination bei Mittelständlern produktiv ein — der Blog zeigt Setup, Production-Hardening und die Stolpersteine, die Standard-Tutorials übersehen.

Aufgabe Vanilla MCP Python SDK FastMCP
Hello-World-Server ~80 Zeilen ~15 Zeilen
Tool-Definition manuelles JSON-Schema Type-Hint-Inferenz
Async + Sync Mix manuell wrappen nativ unterstützt
Resource + Prompt Support manuell registriert Decorator
LangChain-Integration Custom Adapter nötig langchain-mcp-adapters direkt

Warum FastMCP statt Vanilla-MCP-SDK

Wer 2025 die ersten MCP-Server gebaut hat, kennt den Schmerz: Das offizielle MCP Python SDK ist sauber, aber verbose. Für jedes Tool musst du JSON-Schema-Definitionen schreiben, Async-Handler registrieren, Server-Lifecycle managen. Bei drei Tools machbar, bei dreißig nervig. FastMCP wurde Anfang 2025 als Community-Antwort darauf gestartet und ist seit Q3 2025 das De-Facto-Framework für produktive MCP-Server in Python.

Was FastMCP konkret abnimmt: JSON-Schema-Inferenz aus Python-Type-Hints (Pydantic im Hintergrund), automatische Async-Sync-Brücke, eingebaute Transport-Modi (stdio, streamable HTTP, SSE), saubere Resource- und Prompt-Definition über Decorator. Was Anthropic später teilweise ins offizielle SDK gezogen hat, aber FastMCP bleibt vorne weg bei Developer-Experience.

Hier der direkte Vergleich. Vanilla-Style Hello-World:

import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

server = Server("crm-server")

@server.list_tools()
async def list_tools():
    return [Tool(
        name="search_customers",
        description="Suche Kunden im CRM",
        inputSchema={
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"]
        }
    )]

@server.call_tool()
async def call_tool(name, args):
    if name == "search_customers":
        results = await crm_search(args["query"])
        return [TextContent(type="text", text=str(results))]

Gleicher Server mit FastMCP:

from fastmcp import FastMCP

mcp = FastMCP("crm-server")

@mcp.tool
def search_customers(query: str) -> list[dict]:
    """Suche Kunden im CRM nach Name oder E-Mail."""
    return crm_search(query)

if __name__ == "__main__":
    mcp.run()

15 Zeilen statt 80. JSON-Schema wird aus dem Type-Hint query: str und dem Return-Type abgeleitet, die Tool-Beschreibung kommt aus dem Docstring (den der LLM ohnehin sieht). Bei einem Pilotkunden mit 22 Tools haben wir die Migration vom Vanilla-SDK zu FastMCP in einem halben Tag durchgezogen — Codezeilen pro Tool sind von 35-50 auf 4-8 gefallen, Tests blieben alle grün.


FastMCP Server: Minimal-Setup für Production

Der Pexon-Standard für produktive FastMCP-Server hat ein paar Komponenten, die im Hello-World fehlen. Hier der Minimal-Stack, den wir in jedes Kundenprojekt einbauen.

from fastmcp import FastMCP
from fastmcp.exceptions import ToolError
import structlog

log = structlog.get_logger()

mcp = FastMCP(
    "crm-server",
    instructions="""
    Dieser Server liefert Lese- und Schreibzugriff auf das interne CRM.
    Tools: search_customers, get_customer_details, create_note.
    Schreibende Tools brauchen role=vertrieb oder role=service.
    """,
)

@mcp.tool
def search_customers(
    query: str,
    limit: int = 10,
) -> list[dict]:
    """Volltext-Suche im CRM. Liefert max 'limit' Treffer."""
    if not query.strip():
        raise ToolError("query darf nicht leer sein")
    log.info("crm.search", query=query, limit=limit)
    return crm_search(query, limit=limit)

@mcp.tool
def get_customer_details(customer_id: str) -> dict:
    """Holt vollständige Kunden-Details."""
    log.info("crm.get_details", customer_id=customer_id)
    customer = crm_get(customer_id)
    if not customer:
        raise ToolError(f"Kunde {customer_id} nicht gefunden")
    return customer

@mcp.resource("crm://schema")
def crm_schema() -> str:
    """Datenmodell des CRM als JSON-Schema."""
    return open("schemas/crm_schema.json").read()

if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=8000)

Was hier neu ist gegenüber Hello-World: Erstens instructions als Server-weite Beschreibung — der LLM bekommt damit Kontext, wann er den Server überhaupt aufrufen soll. Zweitens ToolError für saubere Fehler-Propagation — das Modell sieht die Fehlermeldung im nächsten Turn und kann sinnvoll reagieren. Drittens structlog als strukturiertes Logging — bei produktiven Setups Pflicht, weil normales print() keine Audit-Trail-Qualität hat. Viertens @mcp.resource für statische Daten wie Schemas — der LLM kann die Resource lesen, ohne dass sie als Tool im Loop erscheint. Fünftens transport="streamable-http" statt stdio, weil HTTP für Multi-Client-Setups und Remote-Aufrufe nötig ist.


LangChain-MCP-Adapter: Tools in die Agent-Pipeline holen

Wenn der Server steht, geht es um die Konsumenten-Seite. langchain-mcp-adapters ist das offizielle Paket, das MCP-Tools zu LangChain-kompatiblen Tools macht. Damit funktionieren sie sofort in jedem LangChain-Agent, LangGraph-Graph oder LCEL-Chain.

from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "crm": {
        "url": "http://crm-server.intern:8000/mcp",
        "transport": "streamable_http",
    },
    "erp": {
        "url": "http://erp-server.intern:8001/mcp",
        "transport": "streamable_http",
    },
    "kalender": {
        "command": "python",
        "args": ["-m", "kalender_mcp"],
        "transport": "stdio",
    },
})

tools = await client.get_tools()

Was hier passiert: Der MultiServerMCPClient verbindet sich mit drei MCP-Servern parallel — zwei über HTTP-Endpoints (CRM und ERP), einer als lokaler Subprozess (Kalender). get_tools() lädt die Tool-Liste aller drei Server und liefert sie als einheitliche LangChain-Tool-Liste. Der Name jedes Tools bekommt automatisch einen Server-Prefix (z.B. crm__search_customers), damit Tools aus verschiedenen Servern nicht kollidieren.

Praktischer Stolperstein, den wir oft sehen: Wenn deine Tools dynamisch Auth-Token brauchen (User-spezifisch statt Service-Account), musst du den Token-Pass durch eigene Header-Logik machen. MultiServerMCPClient unterstützt das über headers={"Authorization": f"Bearer {token}"} pro Server-Konfiguration. Wir bauen das standardmäßig in einen kleinen Token-Refresh-Wrapper ein, der gegen das Unternehmens-IdP (Keycloak oder Entra ID) regelmäßig nachholt.


LangGraph + FastMCP für Production-Agents

Hier kommt der Workflow zusammen. LangGraph als Orchestrator, FastMCP als Tool-Lieferant, dazwischen der Adapter. Das ist das Setup, das wir bei Pexon in den meisten produktiven Agent-Projekten 2026 einsetzen.

from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.postgres import PostgresSaver
from langchain_anthropic import ChatAnthropic
from langchain_mcp_adapters.client import MultiServerMCPClient

async def build_agent():
    client = MultiServerMCPClient({
        "crm": {"url": "http://crm.intern:8000/mcp", "transport": "streamable_http"},
        "erp": {"url": "http://erp.intern:8001/mcp", "transport": "streamable_http"},
    })
    tools = await client.get_tools()

    model = ChatAnthropic(
        model="claude-sonnet-4-6",
        temperature=0.0,
    )

    checkpointer = PostgresSaver.from_conn_string(
        "postgresql://agent_state:***@pg.intern:5432/agents"
    )

    graph = create_react_agent(
        model=model,
        tools=tools,
        checkpointer=checkpointer,
        prompt="""
        Du bist ein interner Service-Assistent. Nutze CRM- und ERP-Tools,
        um Mitarbeiter-Anfragen zu beantworten. Bei Schreib-Aktionen
        IMMER User-Bestätigung einholen.
        """,
    )

    return graph

Was hier zusammenwirkt: ChatAnthropic als LLM (über Bedrock konfigurierbar via base_url), die MCP-Tools aus CRM und ERP als verfügbarer Tool-Pool, ein Postgres-Checkpointer für State-Persistierung über mehrere Conversation-Turns, der create_react_agent als fertiger ReAct-Loop. In ca. 25 Zeilen Code steht ein Production-fähiger Agent, der zwei interne Systeme über MCP anspricht. Das war 2024 ein dreiwöchiges Engineering-Projekt — 2026 ist es ein halber Tag, wenn die MCP-Server stehen.

Was wir Kunden zu diesem Pattern immer mitgeben: Setze temperature=0.0 für Tool-Use-Loops. Höhere Werte führen bei aktuellen Modellen zwar zu kreativeren Outputs, aber bei Tool-Calls steigt die Halluzinations-Rate (falsche Parameter-Werte, nicht-existente Tools). Der Score-Unterschied auf BFCL v4 zwischen Temperature 0.0 und 0.7 ist bei den meisten Modellen rund 4-8 Prozentpunkte zugunsten von 0.0. Bei produktiven Agents ist Determinismus mehr wert als Kreativität.


Production-Hardening: Auth, Rate-Limits, Audit-Trail

Drei Komponenten, die wir Kundenprojekten standardmäßig hinzufügen — und die in den Tutorials konsequent fehlen.

Auth zentral über IdP. FastMCP unterstützt seit Version 2.3 native Auth-Middleware, die Bearer-Tokens validiert und User-Identity in den Tool-Context durchreicht. Wir konfigurieren das gegen Keycloak oder Entra ID, sodass der Tool-Handler weiß, welcher Mensch gerade aufruft — relevant für Permission-Checks innerhalb des Tools und für sauberen Audit-Trail.

from fastmcp.auth import BearerTokenAuth

auth = BearerTokenAuth(
    jwks_url="https://idp.example.com/.well-known/jwks.json",
    issuer="https://idp.example.com/realms/pexon",
    audience="mcp-crm-server",
)

mcp = FastMCP("crm-server", auth=auth)

@mcp.tool
def get_customer_details(customer_id: str, ctx: Context) -> dict:
    user_email = ctx.auth.claims.get("email")
    if not user_has_permission(user_email, "crm.read"):
        raise ToolError(f"User {user_email} hat keine Lese-Berechtigung")
    return crm_get(customer_id)

Rate-Limits pro User. Wir bauen das mit Redis-basiertem Token-Bucket — pro User-Identity 60 Tool-Calls pro Minute als Default, anpassbar pro Tool. Schützt vor Loop-Disastern, in denen ein Agent in eine Schleife läuft und das Backend-System überlastet.

Audit-Trail in Postgres oder Loki. Jeder Tool-Call landet als Log-Entry mit User, Tool, Parameter-Hash, Antwort-Hash, Latenz, Cost und Timestamp. Bei einem Vorfall hast du die volle Trail — wer hat wann was mit welchem Ergebnis aufgerufen. Mehr zum konsolidierten Audit-Pattern in unserem Universal MCP Client Blog.


Pexon-Patterns aus Kundenprojekten

Drei Lessons-Learned, die uns 2025/2026 in 12+ MCP-Projekten begegnet sind und die wir Kunden ungefragt mitgeben.

Lesson 1: Ein MCP-Server pro Domäne, nicht pro System. Wir hatten anfangs einen MCP-Server pro Backend-System gebaut — CRM-Server, ERP-Server, Ticket-Server, Wiki-Server. Das endete bei einem Kunden in 14 Servern, die alle separat deployed und überwacht werden mussten. Heute bauen wir nach Domänen: „Customer-Domain“ deckt CRM und Ticket ab, „Operations-Domain“ ERP und Lager, „Knowledge-Domain“ Wiki und SharePoint. Bei drei bis fünf Servern bleibt der Operations-Aufwand handhabbar.

Lesson 2: Schreib-Tools immer mit Confirmation. Lesetools sind unkritisch, Schreibtools sind gefährlich. Wir bauen Schreib-Tools standardmäßig mit einem Bestätigungs-Parameter — der Agent muss explizit confirmed=True setzen, was bedeutet, dass der User die Aktion vorher gesehen und genehmigt hat. Im Frontend implementieren wir das als Inline-Confirmation-Card. Verhindert die häufigste Klasse von Agent-Bugs: schreibende Aktionen ohne menschliche Zustimmung.

Lesson 3: Tool-Beschreibungen sind Production-Critical. Der Docstring deines @mcp.tool ist nicht Dokumentation für Menschen — er ist der Prompt für den LLM, der entscheidet, ob das Tool aufgerufen wird. Vage Docstrings führen zu falscher Tool-Wahl. Wir review-en Docstrings explizit auf Klarheit, mit Eingabe-Beispielen und klarer Abgrenzung zu ähnlichen Tools. Bei einem Kunden hat allein die Verbesserung der Docstrings die Tool-Treffer-Quote von 78% auf 91% erhöht — ohne Code-Änderung am Server.


Häufig gestellte Fragen

FastMCP ist Community-Projekt — wie stabil ist es?

FastMCP wurde 2025 von Jeremiah Lowin gestartet und ist seit Q3 2025 das De-Facto-Framework. Anthropic hat einige FastMCP-Patterns ins offizielle SDK übernommen, FastMCP entwickelt eigenständig weiter. Production-Use bei mehreren US-Vendors und in unseren 12+ Pexon-Projekten — Stabilität ist auf SemVer-Niveau seit Version 2.0. Wir empfehlen FastMCP 2.x für neue Projekte ohne Bedenken.

Funktioniert das auch ohne LangGraph, nur mit Claude Agent SDK oder OpenAI Agents SDK?

Ja. FastMCP-Server sind MCP-Standard-konform — jeder MCP-Client kann sie konsumieren. Claude Agent SDK hat MCP-First-Class-Integration, OpenAI Agents SDK seit März 2025. LangGraph plus langchain-mcp-adapters ist nur ein Pfad. Wir wählen je nach Projekt — bei reinem Anthropic-Setup oft direkt Claude Agent SDK ohne LangGraph dazwischen. Vergleich der SDKs im Claude Agent SDK vs OpenAI Agents SDK vs LangGraph Post.

Wie debugge ich MCP-Server in der Entwicklung?

FastMCP bringt einen Inspector mit — fastmcp inspect crm_server.py startet eine Web-UI, in der du Tools einzeln aufrufen, Request-/Response-Logs sehen und das Schema verifizieren kannst. Für komplexere Debugging-Szenarien ist mcp-inspector von Anthropic die Standardwahl — funktioniert mit jedem MCP-Server, nicht nur FastMCP.

Was ist mit Authentifizierung bei stdio-Transport?

Stdio-MCP-Server laufen typisch als lokaler Subprozess des Clients — Auth ist implizit über den Prozess-Kontext gegeben. Für Remote-Auth nutzen wir streamable HTTP mit Bearer-Tokens. FastMCP unterstützt beide Transport-Modi nativ.

Wie verbinde ich FastMCP mit ChatGPT Enterprise oder Microsoft Copilot Studio?

ChatGPT Enterprise unterstützt MCP-Connectors seit März 2025. Copilot Studio seit Q4 2025. Beide nehmen den Server über die jeweilige Custom-Connector-Definition entgegen — Setup typisch 30-60 Minuten plus Auth-Brücke. Für komplexere Multi-Server-Setups in Copilot Studio empfehlen wir den Universal MCP Client als Aggregator dazwischen.


Nächster Schritt

Wenn dein Team gerade MCP-Server für interne Systeme baut oder evaluiert: Wir machen einen 45-Minuten-Architektur-Call. Du beschreibst die Backend-Systeme, die du anbinden willst, und den Chatbot-Stack — wir skizzieren FastMCP-Server-Struktur, Auth-Konzept und Festpreis-Sprint, wenn nötig.


Verwandte Themen


Microsoft Fabric. Bilder Blogtemplate Whitepaper

Claude Code im Unternehmen

  • Praxis-Guide für IT-Leiter – mit konkreten Einblicken zu Kosten, Sicherheit und Rollout von Claude Code im Unternehmen.

Beratungsgespräch

Sichern Sie sich Ihre kostenfreie Erstberatung

Analyse Ihres individuellen Cloud- oder KI-Bedarfs
Erste Empfehlungen zu Umsetzungsstrategien
Transparente Einblicke in unsere Methoden, Technologien & Referenzen