From 556f689fcd79241a93d09feef57ef4c4c99c1a88 Mon Sep 17 00:00:00 2001 From: stxkxs Date: Fri, 22 May 2026 08:28:59 -0700 Subject: [PATCH] feat: add the mcp-tunnel addon as an opt-in catalog template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mcp-tunnel exposes a private, in-cluster MCP server to Claude Managed Agents over an outbound-only tunnel — no inbound ports, no public exposure. It wraps Anthropic's MCP tunnels Helm chart (oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel): a single Deployment running cloudflared (the outbound tunnel agent) and the routing proxy (inner-TLS termination, upstream-IP validation, hostname routing to the in-cluster MCP server). The addon ships as an opt-in template — addons/networking/mcp-tunnel/ holds a values scaffold (a Workload-Identity-Federation-mode default with tunnel-id / federation-rule / route placeholders), the per-env value files, and a README activation guide. It is deliberately not wired into applicationsets/addons-networking.yaml: the nanohype factory runs no private MCP server, so deploying it would only produce a broken setup Job. The README documents the path to enable it — request research- preview access, create a tunnel in the Console, set up authentication, fill the placeholders, and paste the ApplicationSet entry. --- addons/networking/mcp-tunnel/README.md | 57 +++++++++++++++++++ addons/networking/mcp-tunnel/values-dev.yaml | 2 + .../mcp-tunnel/values-production.yaml | 2 + .../networking/mcp-tunnel/values-staging.yaml | 2 + addons/networking/mcp-tunnel/values.yaml | 32 +++++++++++ 5 files changed, 95 insertions(+) create mode 100644 addons/networking/mcp-tunnel/README.md create mode 100644 addons/networking/mcp-tunnel/values-dev.yaml create mode 100644 addons/networking/mcp-tunnel/values-production.yaml create mode 100644 addons/networking/mcp-tunnel/values-staging.yaml create mode 100644 addons/networking/mcp-tunnel/values.yaml diff --git a/addons/networking/mcp-tunnel/README.md b/addons/networking/mcp-tunnel/README.md new file mode 100644 index 0000000..11212fa --- /dev/null +++ b/addons/networking/mcp-tunnel/README.md @@ -0,0 +1,57 @@ +# mcp-tunnel + +Exposes a private, in-cluster MCP server to Claude Managed Agents over an +outbound-only tunnel — no inbound ports, no public exposure. It wraps +Anthropic's [MCP tunnels](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview) +Helm chart: a single Deployment running `cloudflared` (the outbound tunnel +agent) and the routing proxy (terminates inner TLS, validates upstream IPs, +routes by hostname to the in-cluster MCP server). + +## Opt-in + +This addon is **not** wired into an ApplicationSet. The nanohype factory +runs no private MCP server, so it ships as a template — the factory itself +does not deploy it. Enable it only if you have a private MCP server to +expose. + +MCP tunnels is an Anthropic **research preview** — +[request access](https://claude.com/form/claude-managed-agents) first. + +## Enable it + +1. **Create a tunnel** in the Claude Console + ([Create a tunnel](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/console#create-a-tunnel)). + Record the tunnel id (`tnl_…`) and the tunnel domain. + +2. **Set up authentication.** Two modes: + - **Workload Identity Federation** — the default in `values.yaml`. Register + the cluster's OIDC issuer and create a federation rule scoped to + `org:manage_tunnels`; the chart's setup Job mints the tunnel token and + manages the certificate. See + [Use WIF with Kubernetes](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes). + - **Manual** — set `setup.enabled: false`, generate a CA + server + certificate, register the CA in the Console, and create the + `mcp-tunnel-token` and `mcp-tunnel-cert` Secrets. See + [Deploy with Helm](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/deploy-helm). + +3. **Fill in `values.yaml`** — replace the `tnl_…` / `fdrl_…` / + organization-id placeholders, and add a `gateway.config.routes` entry for + each MCP server you expose. + +4. **Wire it into ArgoCD** — add this entry to the `list` generator in + `applicationsets/addons-networking.yaml`: + + ```yaml + - appName: mcp-tunnel + namespace: mcp-tunnel + chartRepo: oci://us-docker.pkg.dev/anthropic-public-registry/charts + chart: mcp-tunnel + chartVersion: "1.0.0" + path: addons/networking/mcp-tunnel + syncWave: "1" + ``` + +Once the tunnel is active, each routed server is reachable from Claude at +`https://./` — pass that URL to a Managed +Agents session or the MCP connector. fab registers tunneled servers through +its `FAB_MCP_TUNNEL` env knob (see fab's `src/mcp.ts`). diff --git a/addons/networking/mcp-tunnel/values-dev.yaml b/addons/networking/mcp-tunnel/values-dev.yaml new file mode 100644 index 0000000..55581b3 --- /dev/null +++ b/addons/networking/mcp-tunnel/values-dev.yaml @@ -0,0 +1,2 @@ +# mcp-tunnel — no dev-specific overrides. See values.yaml and README.md. +{} diff --git a/addons/networking/mcp-tunnel/values-production.yaml b/addons/networking/mcp-tunnel/values-production.yaml new file mode 100644 index 0000000..aacf65e --- /dev/null +++ b/addons/networking/mcp-tunnel/values-production.yaml @@ -0,0 +1,2 @@ +# mcp-tunnel — no production-specific overrides. See values.yaml and README.md. +{} diff --git a/addons/networking/mcp-tunnel/values-staging.yaml b/addons/networking/mcp-tunnel/values-staging.yaml new file mode 100644 index 0000000..85aefc7 --- /dev/null +++ b/addons/networking/mcp-tunnel/values-staging.yaml @@ -0,0 +1,2 @@ +# mcp-tunnel — no staging-specific overrides. See values.yaml and README.md. +{} diff --git a/addons/networking/mcp-tunnel/values.yaml b/addons/networking/mcp-tunnel/values.yaml new file mode 100644 index 0000000..6e4c01c --- /dev/null +++ b/addons/networking/mcp-tunnel/values.yaml @@ -0,0 +1,32 @@ +# MCP-tunnel addon — values overlay for the Anthropic mcp-tunnel chart +# (oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel). +# +# OPT-IN TEMPLATE — this addon is intentionally not wired into an +# ApplicationSet. See README.md to enable it. Every REPLACE_ME below must +# be filled with values from your own tunnel before it will deploy. + +# Programmatic setup via Workload Identity Federation: the chart's setup +# Job mints the tunnel token, generates and registers the CA, and a +# CronJob renews the server certificate. EKS is an OIDC provider, so WIF +# is the k8s-native path. For manual credentials, see README.md. +setup: + enabled: true + +api: + wif: + # The tunnel id and federation rule id from the Claude Console, and + # your Anthropic organization id. + tunnelId: "tnl_REPLACE_ME" + federationRuleId: "fdrl_REPLACE_ME" + organizationId: "00000000-0000-0000-0000-000000000000" + # Uncomment when the tunnel lives in a non-default workspace. + # workspaceId: "wrkspc_REPLACE_ME" + +gateway: + config: + # Map each subdomain to an in-cluster MCP server as scheme://host:port + # (no path — the proxy forwards the request path untouched). Claude + # reaches the server at .. + routes: {} + # routes: + # docs: http://docs-mcp.example-ns.svc.cluster.local:8080