feat(caddy): expose MCP gateway at /mcp/* (bearer-gated) for tailnet clients#63
Merged
Conversation
… tailnet clients
Remote MCP clients (Cline/Cursor on other tailnet PCs) had no way to reach the
aggregated tool gateway: it's 127.0.0.1-only, on a network Caddy couldn't reach,
and has no auth of its own. One endpoint already aggregates all 8 servers
(n8n, comfyui, orchestration, searxng, blog-mcp, playwright, qdrant-rag,
codebase-memory), so a single bearer-gated route exposes everything.
- secrets/.env.sops: add MCP_GATEWAY_TOKEN (env-form, decrypts to runtime/.env).
- docker-compose.yml: add model... mcp-gateway to proxy-net so Caddy can reach it;
pass MCP_GATEWAY_TOKEN into caddy's env.
- auth/caddy/Caddyfile: /mcp /mcp/* bypass route — 401 unless the request carries
Authorization: Bearer {$MCP_GATEWAY_TOKEN}; passed through unstripped (gateway
serves /mcp) with flush_interval -1 for SSE/streamable-HTTP. Tailnet-only.
Validated live: POST /mcp without the token -> 401; with it -> 200 MCP initialize
from the Docker MCP Gateway. No secret value is committed (only the encrypted blob
and an env-var reference).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Remote MCP clients (Cline/Cursor on other tailnet PCs) couldn't reach the aggregated MCP gateway — it's
127.0.0.1-only, on a network Caddy couldn't reach, and has no auth of its own. The gateway already bundles all 8 servers (n8n, comfyui, orchestration, searxng, blog-mcp, playwright, qdrant-rag, codebase-memory), so one bearer-gated route exposes every tool through a single Cline entry.What
secrets/.env.sops— addMCP_GATEWAY_TOKEN(env-form →runtime/.env).docker-compose.yml—mcp-gatewayjoinsproxy-net;MCP_GATEWAY_TOKENpassed into Caddy's env.auth/caddy/Caddyfile—/mcp /mcp/*bypass route:401unlessAuthorization: Bearer {$MCP_GATEWAY_TOKEN}; passed through unstripped (gateway serves/mcp) withflush_interval -1for SSE/streamable-HTTP. Tailnet-only.Client config (Cline)
Validation (live)
POST /mcpwithout token →401.200MCPinitializefrom the Docker MCP Gateway (all 8 servers' tools).No secret value committed (encrypted blob + env-var reference only).
🤖 Generated with Claude Code