DevOps & Platform Eng

Caddy-mcp: Secure Private MCP Tunnels via QUIC

Exposing internal services often means wrestling with firewalls and NAT. Caddy-mcp offers a clever way to tunnel private MCP servers securely, entirely over QUIC, with fine-grained access control.

{# Always render the hero — falls back to the theme OG image when article.image_url is empty (e.g. after the audit's repair_hero_images cleared a blocked Unsplash hot-link). Without this fallback, evergreens with cleared image_url render no hero at all → the JSON-LD ImageObject loses its visual counterpart and LCP attrs go missing. #}
Diagram showing the architecture of caddy-mcp, illustrating the flow from a private MCP server through a rift client and a public Caddy instance over QUIC.

Key Takeaways

  • Caddy-mcp allows private MCP servers to be exposed securely over QUIC without opening inbound ports.
  • It offers 'Transparent' and 'Aware' modes for tunneling, with the latter providing granular control over tools and resources via JSON-RPC inspection.
  • The plugin implements per-user ACLs and structured audit logging for enhanced security and accountability.
  • While in beta and limited to single instances, it represents a promising pattern for secure, outbound-initiated remote access to development services.

The hum of servers isn’t always confined to a gleaming data center; sometimes, it’s tucked away in a corner office, a developer’s home lab, or a securely isolated private network. Making those services accessible, however, traditionally means opening ports, wrestling with VPNs, or exposing them to the vagaries of the public internet – a persistent headache for anyone prioritizing security and minimal attack surface.

Here’s the thing: the Caddy web server, already a darling for its ease of use and automatic HTTPS, has a new trick up its sleeve. A plugin called caddy-<a href="/tag/mcp/">mcp</a> promises to radically simplify how we expose services like MCP (presumably a development or tool-chain coordination protocol, given the context) that live behind strict network perimeters.

The Problem: Reaching Inward

Imagine a scenario where your critical development tools, perhaps a local instance of a sophisticated code analysis engine or a specialized prompt server for AI models, are running on a machine isolated from the internet. You need to access them from your main workstation, but your firewall is ironclad, and opening inbound ports feels like an invitation to trouble. Traditional solutions might involve setting up a VPN – a whole separate infrastructure to manage – or using a third-party service that acts as a proxy, introducing another potential point of failure or compromise.

caddy-mcp sidesteps all of that. It flips the script: instead of the outside world dialing in, the private server dials out to a Caddy instance exposed to the internet. This outbound-only connection, leveraging the modern QUIC protocol (the same one underpinning HTTP/3), is the core of its elegance.

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.

That’s the promise, and it’s a powerful one. The architecture diagram provided lays it out starkly: a public-facing Caddy instance acts as the gateway. It terminates TLS, handles routing, and crucially, employs middleware. The caddy-mcp plugin itself listens on a specific QUIC port (4443 in the example) and manages the connection. A rift client, running on the private network, initiates the outbound QUIC connection, specifying --protocol mcp. This tunnel then feeds directly into the local MCP server, typically running on localhost:9090.

How It Works: Tunneling with Intelligence

Caddy’s reverse proxy directive is where the magic truly happens. The plugin offers two primary modes for handling the MCP traffic flowing through the tunnel:

Transparent Mode: This is the most straightforward. Caddy essentially acts as a dumb pipe, forwarding bytes back and forth without inspecting them. The MCP server itself is responsible for managing its sessions, authentication, and all other protocol-level details. It’s simple, performant, and places the entire burden of security at the server’s doorstep.

Aware Mode: This is where caddy-mcp gets really interesting. Here, Caddy doesn’t just forward bytes; it parses the JSON-RPC requests coming from the MCP server. This allows for sophisticated policy enforcement before the request even reaches its intended destination. The example provided showcases this beautifully:

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/*"
  }
}

This configuration demonstrates a granular control system. You can specify which tools (like read_file or execute_command) are permitted or denied for a given tunnel. You can also restrict access to specific resources, such as files within a /repo/* path. Denied calls are met with a JSON-RPC error, neatly preventing unauthorized actions.

Furthermore, the plugin supports per-user ACLs managed via a policy file. The effective permissions are a combination of the tunnel’s configuration and the specific user’s policies, creating a strong, layered security model. And for accountability, every interaction is logged in a structured audit trail, recording the token, user, tool, resource, the decision made (allow/deny), and the latency of the operation. This level of observability is often a missing piece in remote access solutions.

The Broader Implications: Beyond MCP

While the plugin is specifically named caddy-mcp and tailored for MCP-like protocols, the underlying architectural shift it represents is significant. This outbound-only tunneling, combined with intelligent protocol awareness at the edge (Caddy itself), is a powerful pattern. It’s akin to the early days of ngrok or Cloudflare Tunnel, but with a focus on application-layer intelligence rather than just basic port forwarding.

I’d argue this is the direction development infrastructure is headed. As teams distribute and hybrid work becomes the norm, the perimeter is dissolving. Securing access to internal tools and services without the overhead of traditional VPNs or complex network configurations is paramount. The ability for an internal service to “phone home” securely and be exposed intelligently via a trusted edge proxy is a compelling model.

However, it’s crucial to acknowledge the current limitations. The project states it’s in beta, with a single Caddy instance and no high-availability (HA) setup. This means it’s ideal for personal use or small teams where the availability of the Caddy instance isn’t a mission-critical concern. Scaling this to enterprise levels will require further development, likely involving clustered Caddy deployments or integration with other HA solutions.

Still, for developers seeking a secure, low-overhead way to expose private MCP services, caddy-mcp represents a genuinely innovative approach. It embodies a modern, security-first philosophy that prioritizes minimizing attack vectors while maximizing usability and control.

Why Does This Matter for Developers?

This isn’t just about making a specific protocol available. It’s about a fundamental shift in how we think about secure remote access to development environments and tools. The caddy-mcp plugin offers a practical demonstration of how intelligent edge proxies can secure access to services without requiring inbound firewall rules, thus shrinking the attack surface considerably. For developers working with sensitive internal services, or for those managing distributed development teams, this pattern could significantly simplify secure access management.

What’s Next for caddy-mcp?

The project is currently in beta, focusing on single-instance deployments. Future iterations will likely address high-availability, broader protocol support beyond MCP, and potentially more sophisticated policy engines. The core concept, however – outbound QUIC tunneling with intelligent protocol awareness at the edge – is sound and holds promise for wider adoption in secure development infrastructure.


🧬 Related Insights

Frequently Asked Questions

What does MCP stand for in caddy-mcp? While the original content doesn’t explicitly define MCP, it’s implied to be a protocol for interacting with development tools, resources, or prompts, likely within a specific workflow or platform.

Is this suitable for large enterprises? Currently, no. The project is in beta and designed for single Caddy instances, lacking high-availability. It’s best suited for personal use or small team environments.

Can caddy-mcp expose any service, not just MCP? The plugin is specifically designed to tunnel MCP-aware protocols. While the core tunneling mechanism could potentially be adapted, its current intelligent features are tailored to JSON-RPC-based protocols like MCP.

Alex Rivera
Written by

Developer tools reporter covering SDKs, APIs, frameworks, and the everyday tools engineers depend on.

Frequently asked questions

What does MCP stand for in `caddy-mcp`?
While the original content doesn't explicitly define MCP, it's implied to be a protocol for interacting with development tools, resources, or prompts, likely within a specific workflow or platform.
Is this suitable for large enterprises?
Currently, no. The project is in beta and designed for single Caddy instances, lacking high-availability. It's best suited for personal use or small team environments.
Can `caddy-mcp` expose any service, not just MCP?
The plugin is specifically designed to tunnel MCP-aware protocols. While the core tunneling mechanism could potentially be adapted, its current intelligent features are tailored to JSON-RPC-based protocols like MCP.

Worth sharing?

Get the best Developer Tools stories of the week in your inbox — no noise, no spam.

Originally reported by dev.to

Stay in the loop

The week's most important stories from DevTools Feed, delivered once a week.