Skip to main content
Glama

Agentic MCP Itinerary — PoC

Ein MCP-Server, der intern einen LLM-Agenten (Gemini Flash + LangGraph) ausführt und mehrere Downstream-MCP-Server orchestriert. Der Client (Claude Desktop, ChatGPT) sieht eine saubere Schnittstelle mit persistentem Zustand zwischen den Iterationen.

Konzept

Claude Desktop / ChatGPT
        │
        │  MCP (HTTP/SSE + OAuth 2.1)
        ▼
┌─────────────────────────────────────┐
│         travel-agent (este repo)    │
│  FastMCP server + LangGraph agent   │
│                                     │
│  ┌──────┐  ┌────────┐  ┌──────────┐│
│  │Vuelos│  │Hoteles │  │Actividad.││  ← MCP mocks STDIO
│  └──────┘  └────────┘  └──────────┘│
└─────────────────────────────────────┘

Warum ist das anders? Kein Unternehmen bietet bisher einen "vertikalen Agenten, der als MCP-Server verpackt ist" an. Dieser PoC demonstriert das Muster: Der Client sieht nur 4-5 saubere Tools, aber dahinter arbeitet ein Agent mit Gedächtnis, parallelem Fan-out und persistentem Zustand.


Related MCP server: ts-travel-mcp-server

Stack

Komponente

Technologie

Exponierter MCP-Server

FastMCP 3.1.1 (streamable-http)

Interner Agent

LangGraph (StateGraph + paralleler Fan-out)

LLM-Modell

Gemini Flash (gemini-2.0-flash)

Auth

OAuth 2.1 Authorization Code Flow + JWT HS256

Checkpointing

MemorySaver (im Arbeitsspeicher, ausreichend für PoC)

Downstream MCP

Offizielles MCP SDK (mcp.client.stdio)

Mocks

3 FastMCP-Server STDIO (Flüge, Hotels, Aktivitäten)

Deploy

Railway (RAILPACK + pyproject.toml)


Exponierte Tools (Öffentliche API)

Tool

Parameter

Beschreibung

create_itinerary

requirements: str

Erstellt einen vollständigen Entwurf (Flüge + Hotel + Aktivitäten parallel)

refine_itinerary

itinerary_id: str, change_request: str

Verfeinert einen bestehenden Entwurf

get_itinerary

itinerary_id: str

Ruft den aktuellen Zustand ab

list_itineraries

Listet alle aktiven Reisepläne auf

confirm_itinerary

itinerary_id: str

Bestätigt und generiert einen confirmation_code


Deploy auf Railway

URLs

Railway-IDs

  • Projekt: e50da57f-ee0b-47a3-81a3-55556fe6de0d

  • Service: 09065312-ac84-4876-b9c9-dd5d6439f1d4

  • Umgebung: 09b3f0c9-e5ad-4f61-b351-275bbcffd5ad

Erforderliche Umgebungsvariablen

Variable

Beschreibung

GEMINI_API_KEY

API-Key von Google Gemini

MCP_USERNAME

Benutzername für den OAuth-Login

MCP_PASSWORD

Passwort für den OAuth-Login

MCP_JWT_SECRET

Geheimnis zum Signieren von JWTs (generiert mit secrets.token_urlsafe(32))

MCP_BASE_URL

Öffentliche URL des Servers (zum Erstellen von Redirect-URIs)


Auth: OAuth 2.1 Authorization Code Flow

Vollständiger Ablauf

1. Claude Desktop detecta el MCP server
2. Descubre /.well-known/oauth-authorization-server
3. Redirige al usuario a /authorize
4. El servidor redirige a /oauth/authorize (form de login HTML)
5. Usuario introduce user/pass → POST /oauth/authorize
6. Servidor valida credenciales (MCP_USERNAME / MCP_PASSWORD)
7. Emite auth code → redirect a Claude Desktop
8. Claude Desktop intercambia code → JWT en /token
9. JWT usado como Bearer en todas las llamadas MCP

Implementierung

  • server/auth.py: SimpleOAuthProvider (erweitert OAuthProvider von FastMCP)

  • JWT HS256, 1h Gültigkeit

  • Auth-Codes: 5 Min. Gültigkeit

  • PKCE (S256) unterstützt

  • /health bleibt öffentlich ohne Auth


Claude Desktop konfigurieren

Bearbeite ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "travel-agent": {
      "type": "http",
      "url": "https://travel-agent-production-c1c4.up.railway.app/mcp"
    }
  }
}

Ohne headers — Claude Desktop verwaltet den OAuth-Flow automatisch. Beim ersten Mal wird der Browser für den Login geöffnet.


Lokale Entwicklung

Voraussetzungen

pip install -e ".[dev]"

Server starten

PYTHONPATH=server MCP_USERNAME=alexguerra MCP_PASSWORD=tu_pass \
  MCP_JWT_SECRET=dev_secret python3 server/main.py

Smoke-Test

PYTHONPATH=server python3 tests/smoke_test.py

Syntax prüfen

PYTHONPATH=server python3 -m py_compile server/main.py server/auth.py server/agent.py

Projektstruktur

agentic-mcp-itinerary/
├── server/
│   ├── main.py          # FastMCP server (4 tools + OAuth + /health)
│   ├── auth.py          # SimpleOAuthProvider (OAuth 2.1 + JWT)
│   ├── agent.py         # LangGraph graph con fan-out paralelo
│   ├── state.py         # ItineraryState TypedDict + checkpointer
│   └── tools/
│       ├── flights.py   # Cliente MCP → mock vuelos
│       ├── hotels.py    # Cliente MCP → mock hoteles
│       └── activities.py # Cliente MCP → mock actividades
├── mocks/
│   ├── flights_mcp.py   # Mock server vuelos (FastMCP STDIO)
│   ├── hotels_mcp.py    # Mock server hoteles (FastMCP STDIO)
│   └── activities_mcp.py # Mock server actividades (FastMCP STDIO)
├── tests/
│   └── smoke_test.py    # Test end-to-end básico
├── docs/
│   └── OAUTH_PLAN.md    # Spec del OAuth (referencia de diseño)
├── pyproject.toml       # Deps para RAILPACK
├── railway.toml         # Builder=RAILPACK, startCommand
└── claude_desktop_config.json  # Config para Claude Desktop (sin Bearer manual)

Historie der wichtigsten Entscheidungen

Entscheidung

Verworfenes Alternativkonzept

Grund

RAILPACK + pyproject.toml

nixpacks

nixpacks schlägt bei pip innerhalb einer unveränderlichen Umgebung fehl

OAuth 2.1 Authorization Code

Statischer Bearer-Token

Claude Desktop verwaltet OAuth nativ; produktionsnäher

JWT HS256 im Speicher

Token-Datenbank

PoC — kein persistenter Zustand zwischen Neustarts

FastMCP 3.1.1 OAuthProvider

Manuelle Auth mit Starlette

FastMCP integriert den Flow mit dem MCP-Transport

MemorySaver

SQLite/Redis

Ausreichend für lokalen PoC; einfache Migration zu SqliteSaver

Gemini Flash

Claude Haiku

Codex hatte einen Konflikt bei den Anmeldedaten mit Anthropic


Nächste Schritte (nach dem PoC)

  • [ ] Test in Claude Desktop — vollständigen OAuth-Flow verifizieren

  • [ ] Echte PersistenzSqliteSaver oder Postgres für den Zustand zwischen Neustarts

  • [ ] Echte Downstream-MCPs — Mocks durch echte APIs ersetzen (Amadeus, Booking, etc.)

  • [ ] Multi-User — Benutzerdatenbank anstelle von Umgebungsvariablen

  • [ ] Rate Limiting — pro JWT-Token

  • [ ] Telemetrie — LangSmith oder Ähnliches zur Nachverfolgung des internen Agenten

Related MCP Connectors

Related MCP Servers