caddy-mcp is a Caddy plugin for exposing MCP servers that live on private networks. The private box dials out to Caddy over QUIC, Caddy serves it as a normal HTTPS endpoint. No inbound ports, no third party in the request path.
Public Internet
|
v
+--------------------+
| Caddy :443 | TLS, routing, middleware
| reverse_proxy |
+--------+-----------+
|
v
+--------------------+
| caddy-mcp plugin | QUIC listener :4443
| tunnel registry | token store
| policy engine | MCP-aware ACLs
| audit logger | structured logging
+--------+-----------+
|
| QUIC connection (TLS 1.3, multiplexed streams)
v
+--------------------+
| rift client | runs on private network
| --protocol mcp | dials out — no inbound ports
+--------+-----------+
|
v
+--------------------+
| MCP server | tools, resources, prompts
| localhost:9090 |
+--------------------+
The dial-out side runs rift with --protocol mcp.
Two modes per tunnel:
Transparent — Caddy forwards bytes untouched. The MCP server handles its own session and auth.
Aware — Caddy parses the JSON-RPC and enforces policy before anything reaches the upstream:
reverse_proxy mcp-tunnel {
transport mcp {
tunnel code-server
mode aware
allow_tools read_file list_files search
deny_tools execute_command shell_exec
allow_resources "file:///repo/*"
}
}
Denied calls get a JSON-RPC error back. There's per-user ACLs via a policy file (effective permissions are the intersection of tunnel and user ACLs), and a structured audit log of every call — token, user, tool, resource, decision, latency.
Status: beta, single Caddy instance, no HA. Works for personal and small-team setups.
Most of the details are in the repo: github.com/venkatkrishna07/caddy-mcp.
Top comments (0)