MCP Remote vs. Lokal
Wann muss ein MCP-Server „remote” liegen, was bedeutet das technisch, und was muessen wir konkret umbauen wenn wir einen heute-lokalen MCP zu einem Remote-Service machen? Festgehalten am Beispiel ticketpay.
Zwei Transport-Modi
1. stdio. Der Client (Claude Desktop, Claude Code, Wrapper) spawnt den MCP als Subprocess. JSON-RPC ueber STDIN/STDOUT. Server lebt nur solange der Client lebt. Auth = „wer den Prozess starten kann, darf alles”.
2. Streamable HTTP (frueher SSE). Server ist HTTP-Daemon mit /mcp-Endpunkt. Session via Mcp-Session-Id-Header. Server-Push via SSE-Stream. Mehrere Clients gleichzeitig moeglich.
„Remote MCP” = Streamable HTTP + oeffentliche URL + TLS + OAuth davor.
Wann ist Remote zwingend
- Claude.ai Pro im Browser kann ausschliesslich Remote MCPs — Browser kann keine Subprocesses spawnen. Custom Connectors sind per Definition remote.
- Cloudflare Workers als Hosting → kein stdio moeglich (keine
subprocess.Popen(), keinfork()). Alle Subs muessen HTTP sein. - Mehrere Clients teilen einen MCP — z.B. drei Wrapper-Instanzen die alle TicketPay anbinden.
Claude Desktop und Claude Code koennen beides — lokal stdio reicht fuer Single-User-Setups.
TicketPay heute — zwei Realitaeten gleichzeitig
| Use-Case | Setup |
|---|---|
| (A) Marvin in Claude Code | stdio/HTTP auf 127.0.0.1:8766, API-Key in ~/source/mcps/mcp-ticketpay/.env.local, kein OAuth, Single-Tenant |
| (B) Andre in claude.ai Pro | Embedded als stdio-Sub im mcp-vf-hosted-Wrapper. Wrapper macht den Remote-Teil (OAuth via Scalekit, TLS via Cloudflare, ECS-Container). TicketPay-MCP selbst ist weiterhin dumm und stdio. |
Die Remote-Schale liegt einen Layer hoeher. Sub-MCPs bleiben simpel.
Wann muessten wir TicketPay selbst remote machen
- Migration zu Cloudflare Workers (Workers koennen stdio-Subs nicht spawnen)
- TicketPay als eigenstaendiger Connector in claude.ai (z.B. Kunde der nur TicketPay braucht, nicht das VF-Bundle)
- Mehrere Wrapper-Instanzen sollen einen zentralen TicketPay-MCP teilen statt jeder seinen eigenen Subprocess fork
Umbau-Liste — TicketPay als standalone Remote MCP
| # | Was | Heute | Remote-Variante |
|---|---|---|---|
| 1 | Transport | stdio + lokaler HTTP | nur Streamable HTTP, public bind |
| 2 | URL/TLS | 127.0.0.1:8766 | ticketpay.mcp.agenticventures.de mit Cert |
| 3 | Auth-Layer | API-Key in .env | OAuth davor (Scalekit oder CF Access), JWT-Validation pro Request |
| 4 | OAuth-Discovery | — | /.well-known/oauth-protected-resource, Resource-Identifier = exakte MCP-URL |
| 5 | API-Key-Quelle | Eine ENV-Variable | Per-User-Mapping: aus authentifiziertem Token → welcher TicketPay-Key. Storage: DB/Secrets-Manager/Durable Object. Server kennt beim Start keinen Key |
| 6 | Hosting | dein Mac via uv tool | ECS Express Container ODER Cloudflare Worker (dann komplette Reimpl., weil Python→TS) |
| 7 | Health-Endpoint | — | /health auth-frei fuer Loadbalancer (VF-Wrapper-Pattern kopieren) |
| 8 | Logging | print to stderr | strukturiertes JSON-Logging mit PII-Scrubbing (GuardMiddleware-Pattern aus VF-Wrapper) |
| 9 | Rate-Limit | — | Per-Subject Token-Bucket (Abuse-Schutz) |
| 10 | Secrets | .env.local | AWS Secrets Manager oder CF Secrets, niemals im Image |
| 11 | Stateless | stateful ok bei einer Instanz | bei Multi-Instance Session-Affinity oder externer Session-Store |
Code-Aufwand realistisch: 1-2 Tage. Klonen von mcp-vf-hosted als Template, create_proxy()-Liste reduzieren, Punkt 5 (Per-User-Key) ist die einzige echt neue Sache.
Default-Empfehlung: nicht machen
Solange wir das Mono-Wrapper-Pattern fahren (mcp-vf-hosted), muessen Sub-MCPs nicht remote sein. Der Wrapper loest Remote/OAuth/TLS einmal zentral, Sub-MCPs bleiben simple stdio-Tools die wir auch lokal in Claude Code nutzen koennen. Doppelter Use-Case ohne Doppelarbeit.
Trigger fuer Umbau: Wenn wir cloudflare-capability-map Option A ernsthaft verfolgen (MCP-Hosting auf Workers statt ECS), brauchen wir HTTP-native Subs. Dann waere der erste Schritt: TicketPay HTTP-Mode produktionstauglich machen (Punkte 7-10 aus der Tabelle), Auth weiterhin Sache des Wrappers lassen. Sub im Wrapper umstellen von StdioTransport auf StreamableHttpTransport — und sehen ob die Architektur traegt, bevor wir die Per-User-Auth-Story dranhaengen.
Related
- mcp-vf-hosted — Mono-Wrapper-Pattern, loest Remote-Teil zentral
- ticketpay — der konkrete MCP, am Beispiel erklaert
- cloudflare-capability-map — wann Workers Sinn machen
- mcp-hosting-aws-ecs-express — aktuelles Hosting (stdio-Subs in Container)