Skip to content

Commit 98b0cd9

Browse files
vfanelleshubcodesclaudegithub-actions[bot]
authored
Add Warp Pipes doc and Early Access sidebar section (#1033)
* docs(deployment): add Warp Tunnels guide Add a Warp Tunnels page under Guides → Deployment & hosting covering how a self-hosted Arcade Engine connects external AI clients to private MCP servers: internal connectivity via ssrf_allowlist, multi-network deployments, and external access through a reverse proxy (cloudflared, ngrok, nginx). Includes three hand-crafted SVG architecture diagrams, gateway auth modes, required proxy headers, client compatibility, and known limitations. Wires the page into deployment-hosting/_meta.tsx and links it from the hosting overview. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Rebrand Warp Tunnels guide to Warp Pipes - Rename route /guides/deployment-hosting/warp-tunnels -> /warp-pipes - Update nav label and parent guide link to "Warp Pipes" - Lead with the managed Warp Pipes service, then BYO reverse proxy - Purge Engine/Coordinator/platform terminology in favor of "runtime" - Replace outdated diagrams with new self-contained SVGs (managed forwarding, internal MCP servers, multi-runtime, BYO reverse proxy); add the previously-missing warp-pipes.svg No redirect added per request: the old /warp-tunnels path is retired and no "warp-tunnels" reference remains in the repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add Early Access section to Guides sidebar * Add Early Access _meta.tsx with Warp Pipes and Registry Early Access links * 🤖 Regenerate LLMs.txt * Merge main into docs/warp-tunnels: resolve llms.txt conflict * Fix llms.txt header to match main for clean merge * Remove Early Access from Guides sidebar * Add Early Access section to Resources sidebar * Add resources/early-access/_meta.tsx with Warp Pipes and Arcade Registry links * Remove guides/early-access — moved to resources/early-access * Hide registry-early-access from Resources sidebar (now under Early Access) * Hide warp-pipes from Deployment & hosting sidebar (now under Early Access) * Hide warp-pipes from Deployment & hosting sidebar * Fix formatting in early-access _meta.tsx --------- Co-authored-by: Shub <125150494+shubcodes@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 5373899 commit 98b0cd9

10 files changed

Lines changed: 523 additions & 0 deletions

File tree

app/en/guides/deployment-hosting/_meta.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ const meta: MetaRecord = {
1717
"on-prem": {
1818
title: "On-premises MCP servers",
1919
},
20+
"warp-pipes": {
21+
title: "Warp Pipes",
22+
display: "hidden",
23+
},
2024
"configure-engine": {
2125
title: "Configure Arcade's engine",
2226
},

app/en/guides/deployment-hosting/page.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Visit [https://api.arcade.dev](https://api.arcade.dev) for current pricing detai
4949

5050
Fully on-premise deployments of the Arcade platform are available! Arcade can be deployed on Kubernetes via our Helm chart and Docker images as part of our enterprise offering. [Contact us to learn more](/resources/contact-us).
5151

52+
To connect a self-hosted Arcade runtime to MCP servers inside your private network, and to reach it from external AI clients without opening inbound ports, see [Warp Pipes](/guides/deployment-hosting/warp-pipes).
53+
5254
The requirements for deploying Arcade on-premise are:
5355

5456
- Kubernetes cluster (1.30+) (We have tested this helm chart on AKS, GKE, and EKS).
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
---
2+
title: "Warp Pipes"
3+
description: "Connect external AI clients to your private Arcade runtime. Warp Pipes is the managed connection; the runtime governs every call. Includes the bring-your-own reverse proxy path you can use today."
4+
---
5+
6+
import Image from "next/image";
7+
import { Callout, Steps, Tabs } from "nextra/components";
8+
9+
# Warp Pipes
10+
11+
Connecting AI agents to private tools is two problems. The first is **networking**: your internal MCP servers and services aren't reachable from the public internet, by design. The second is **governance**: a tunnel only moves bytes, so authentication, per-user credentials, access scoping, and audit are a separate problem that the tunnel products leave to you.
12+
13+
The Arcade runtime already solves governance. **Warp Pipes** is a managed service that solves the networking — Arcade hands you a public MCP URL and forwards traffic to your private runtime, so you don't run the connection yourself.
14+
15+
<Callout type="info">
16+
**Warp Pipes is in early access.** [Request access](https://www.arcade.dev/contact) to have Arcade manage the connection from your AI clients to your runtime. You can also connect clients today with your own reverse proxy — see [Bring your own reverse proxy](#bring-your-own-reverse-proxy).
17+
</Callout>
18+
19+
<GuideOverview>
20+
<GuideOverview.Outcomes>
21+
22+
Connect external AI clients to private MCP servers through a self-hosted Arcade runtime, while keeping your internal services off the public internet and your firewall closed to inbound traffic.
23+
24+
</GuideOverview.Outcomes>
25+
26+
<GuideOverview.Prerequisites>
27+
28+
- A [self-hosted Arcade runtime](/guides/deployment-hosting/on-prem)
29+
- Access to your [engine.yaml configuration](/guides/deployment-hosting/configure-engine)
30+
- The private hostnames or IP ranges of your internal MCP servers
31+
32+
</GuideOverview.Prerequisites>
33+
34+
<GuideOverview.YouWillLearn>
35+
36+
- How Warp Pipes manages the connection from AI clients to your runtime
37+
- How the runtime reaches internal MCP servers without inbound ports
38+
- How to allowlist internal addresses and register MCP servers in `engine.yaml`
39+
- How to connect external clients today with your own reverse proxy
40+
41+
</GuideOverview.YouWillLearn>
42+
</GuideOverview>
43+
44+
## How Warp Pipes works
45+
46+
Your Arcade runtime runs as an MCP server inside your private network, on port `9099` by default, and it never faces the internet. You run the **Warp Pipes connector** alongside it; the connector makes one outbound connection to Arcade. Arcade gives you a public MCP URL and forwards every request down that connection to your runtime.
47+
48+
What Warp Pipes adds, and only this:
49+
50+
- A **public MCP URL** hosted by Arcade that any AI client connects to.
51+
- **Managed forwarding** from that URL to your internal runtime.
52+
- An **outbound connector** in your network that holds the connection open. Nothing inbound is exposed.
53+
54+
Everything behind the connector is the runtime you already have. Warp Pipes does not re-implement authentication, credentials, governance, or audit. It connects clients to the runtime that already does them.
55+
56+
<Image
57+
alt="Warp Pipes: external AI clients connect to a public MCP URL hosted by Arcade. Arcade forwards traffic down an outbound connection held open by the Warp Pipes connector inside the private network, to the Arcade runtime, which governs the call and reaches internal MCP servers. No inbound ports are opened."
58+
className="mt-4 h-auto w-full rounded-lg border border-border"
59+
src="/images/warp-pipes/warp-pipes.svg"
60+
width={1080}
61+
height={360}
62+
unoptimized
63+
/>
64+
65+
## How the runtime works
66+
67+
Two concepts shape every deployment, with or without Warp Pipes:
68+
69+
- **Gateways** are named paths on the runtime (`/mcp/{slug}`). Each gateway has its own auth mode, tool allow-list, and access rules, so an AI client connecting to `/mcp/finance` sees only finance tools. You create gateways in the [Arcade dashboard](/guides/mcp-gateways), not in `engine.yaml`.
70+
- **Identity and access** — users, organizations, API keys, RBAC, and OAuth — is managed in Arcade. The runtime makes outbound-only calls to it; it never dials the runtime. Multiple runtimes can share one Arcade account.
71+
72+
## Gateway auth modes
73+
74+
Each gateway uses one of three auth modes. The mode determines what the AI client sends and which clients can connect.
75+
76+
| Dashboard name | Config value | What the client sends | Works with the Anthropic Messages API? |
77+
| --- | --- | --- | --- |
78+
| Arcade Auth | `arcade_oauth` | Bearer JWT issued by Arcade OAuth | Yes |
79+
| User Source | `user_source` | Bearer JWT from your identity provider | Yes |
80+
| Arcade Headers | `arcade_header` | Bearer token plus an `Arcade-User-ID` header | No. The Anthropic connector can't send custom headers |
81+
82+
For Claude, through the Messages API or managed agents, use **Arcade Auth** or **User Source**. See [MCP Gateways](/guides/mcp-gateways) for how to choose a mode and [User Sources](/guides/user-sources) for connecting your own identity provider.
83+
84+
## Connect to internal MCP servers
85+
86+
Your internal MCP servers live at private hostnames or IP addresses. Configure the `ssrf_allowlist` in `engine.yaml` to tell the runtime which internal addresses it's permitted to call, then register each MCP server URI as a worker.
87+
88+
The runtime calls these servers directly over your private network, by their internal addresses. No inbound ports, and no tunnel, are required.
89+
90+
<Image
91+
alt="A single Arcade runtime and its internal MCP servers share one private network. AI clients connect to scoped /mcp gateways, the ssrf_allowlist gates which internal addresses the runtime reaches, and the runtime makes outbound-only calls to Arcade for identity and access."
92+
className="mt-4 h-auto w-full rounded-lg border border-border"
93+
src="/images/warp-pipes/scenario-1.svg"
94+
width={1080}
95+
height={480}
96+
unoptimized
97+
/>
98+
99+
Add the allowlist and workers to the `tools.directors` section of `engine.yaml`:
100+
101+
```yaml filename="engine.yaml"
102+
tools:
103+
directors:
104+
- id: default
105+
ssrf_allowlist:
106+
- "*.corp.internal" # any subdomain
107+
- "10.10.0.0/16" # IP range
108+
workers:
109+
- id: bloomberg
110+
enabled: true
111+
http:
112+
uri: "http://bloomberg.corp.internal:8000"
113+
secret: "${env:BLOOMBERG_SECRET}"
114+
- id: sap
115+
enabled: true
116+
http:
117+
uri: "http://sap.corp.internal:8080"
118+
secret: "${env:SAP_SECRET}"
119+
- id: github-enterprise
120+
enabled: true
121+
http:
122+
uri: "http://github.corp.internal"
123+
secret: "${env:GITHUB_SECRET}"
124+
```
125+
126+
For the rest of the `tools.directors` and worker options, see [runtime configuration](/guides/deployment-hosting/configure-engine#tools-configuration).
127+
128+
### Allowlist entry types
129+
130+
| Type | Example | Evaluated | Matches |
131+
| --- | --- | --- | --- |
132+
| Exact host | `https://host.corp:8080` | Before DNS | Scheme, host, and port exactly |
133+
| Wildcard | `*.corp.internal` | Before DNS | Any matching subdomain |
134+
| CIDR | `10.10.0.0/16` | After DNS resolution | IPs in the range |
135+
136+
Keep these rules in mind when you write allowlist entries:
137+
138+
- URIs must use `http://` or `https://`. The runtime rejects other schemes at startup.
139+
- A wildcard such as `*.corp.internal` does not match the bare apex `corp.internal`. Add the apex separately if the runtime needs to reach it.
140+
- CIDR entries match against the resolved IP. For split-horizon DNS, where a hostname resolves to different IPs inside and outside the network, use exact-host or wildcard entries instead.
141+
- Malformed entries cause the runtime to fail at startup.
142+
143+
### Configure the allowlist with Helm
144+
145+
If you deploy the runtime with the Arcade Helm chart, set the allowlist with `--set`:
146+
147+
```bash
148+
helm upgrade arcade monorepo/deploy/charts/arcade/ \
149+
--set engine.ssrfAllowlist[0]="*.corp.internal" \
150+
--set engine.ssrfAllowlist[1]="10.10.0.0/16"
151+
```
152+
153+
### Verify the connection
154+
155+
Use the worker test endpoint in the Arcade dashboard. A successful test confirms the allowlist entry is correct and that the runtime has a network path to the MCP server.
156+
157+
## Deploy across multiple networks
158+
159+
For multiple business units or regions, deploy a separate runtime per network. Each runtime has its own `ssrf_allowlist` scoped to the servers in that network, and all runtimes share one Arcade account for identity and access.
160+
161+
<Image
162+
alt="Finance, Engineering, and EU each run their own Arcade runtime in their own private network with its own ssrf_allowlist. All three make outbound-only calls to one Arcade account, and cross-network access is blocked because the other networks' addresses aren't in each allowlist."
163+
className="mt-4 h-auto w-full rounded-lg border border-border"
164+
src="/images/warp-pipes/scenario-2.svg"
165+
width={1080}
166+
height={400}
167+
unoptimized
168+
/>
169+
170+
A typical topology assigns one runtime to each network:
171+
172+
| Deployment | Network | `ssrf_allowlist` | MCP servers |
173+
| --- | --- | --- | --- |
174+
| `finance-nyc` | NYC datacenter | `10.10.0.0/16`, `*.finance.corp.internal` | Bloomberg, SAP, Workday |
175+
| `engineering-use1` | AWS `us-east-1` | `10.20.0.0/16`, `*.eng.corp.internal` | GitHub Enterprise, Jira |
176+
| `eu-euw1` | AWS `eu-west-1` | `10.30.0.0/16`, `*.eu.corp.internal` | EU APIs, GDPR-scoped data |
177+
178+
This topology gives you:
179+
180+
- **Network isolation** — each runtime can only reach the hosts and ranges in its own allowlist. The finance runtime can't dial `10.20.x.x` even if it receives a URI pointing there.
181+
- **Data residency** — the EU runtime's tool traffic never leaves eu-west-1, and credentials in its vault stay in-region.
182+
- **Credential isolation** — each runtime holds its own credential vault. A compromise of one runtime exposes no credentials from the others.
183+
- **Shared identity** — all runtimes make outbound calls to the same Arcade account for auth and RBAC. The data planes are independent; identity and access are shared.
184+
185+
Connect each runtime out with its own Warp Pipes URL, or front each with your own reverse proxy.
186+
187+
## Bring your own reverse proxy
188+
189+
Warp Pipes manages the connection for you. If you'd rather run the networking hop yourself — or you already operate a reverse proxy or API gateway you trust — Arcade has always worked behind one.
190+
191+
Run a reverse proxy inside your network. It makes one outbound connection, so no inbound ports are needed. External clients connect to the proxy's public hostname, and the proxy forwards traffic to the runtime internally.
192+
193+
<Image
194+
alt="External AI clients on the public internet reach the private Arcade runtime through a reverse proxy (cloudflared, ngrok, or nginx) running inside the network. The proxy makes one outbound connection, so no inbound ports are opened; everything behind it is the same governed runtime."
195+
className="mt-4 h-auto w-full rounded-lg border border-border"
196+
src="/images/warp-pipes/scenario-3.svg"
197+
width={1080}
198+
height={240}
199+
unoptimized
200+
/>
201+
202+
All AI clients see the same RFC 9728 OAuth interface regardless of which proxy you use. The runtime, the governance, and the security model are identical whether the connection is managed by Warp Pipes or by your own cloudflared, ngrok, or nginx.
203+
204+
<Tabs items={["Cloudflare Tunnel", "ngrok", "nginx"]}>
205+
<Tabs.Tab>
206+
207+
[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) runs `cloudflared` inside your network and exposes the runtime on a public hostname.
208+
209+
```yaml filename="config.yaml"
210+
tunnel: <tunnel-id>
211+
credentials-file: /etc/cloudflared/credentials.json
212+
ingress:
213+
- hostname: arcade.yourdomain.com
214+
service: http://arcade:9099
215+
- service: http_status:404
216+
```
217+
218+
```bash
219+
cloudflared tunnel run
220+
```
221+
222+
External clients connect to `https://arcade.yourdomain.com/mcp/{gateway-slug}`.
223+
224+
</Tabs.Tab>
225+
<Tabs.Tab>
226+
227+
[ngrok](https://ngrok.com) forwards a public domain to the runtime's port with a single command:
228+
229+
```bash
230+
ngrok http 9099 --domain arcade.your-org.ngrok.app
231+
```
232+
233+
External clients connect to `https://arcade.your-org.ngrok.app/mcp/{gateway-slug}`.
234+
235+
</Tabs.Tab>
236+
<Tabs.Tab>
237+
238+
nginx works as a straightforward reverse proxy. MCP uses streaming, so you must disable buffering.
239+
240+
```nginx filename="arcade.conf"
241+
server {
242+
listen 443 ssl;
243+
server_name arcade.yourdomain.com;
244+
245+
ssl_certificate /etc/ssl/certs/arcade.crt;
246+
ssl_certificate_key /etc/ssl/private/arcade.key;
247+
248+
location / {
249+
proxy_pass http://arcade:9099;
250+
251+
# Required for streaming
252+
proxy_buffering off;
253+
proxy_cache off;
254+
proxy_read_timeout 3600s;
255+
proxy_http_version 1.1;
256+
proxy_set_header Connection '';
257+
258+
# Required headers
259+
proxy_set_header Host $host;
260+
proxy_set_header X-Real-IP $remote_addr;
261+
proxy_set_header Authorization $http_authorization;
262+
proxy_set_header Mcp-Session-Id $http_mcp_session_id;
263+
proxy_set_header MCP-Protocol-Version $http_mcp_protocol_version;
264+
}
265+
}
266+
```
267+
268+
External clients connect to `https://arcade.yourdomain.com/mcp/{gateway-slug}`.
269+
270+
</Tabs.Tab>
271+
</Tabs>
272+
273+
### Required proxy headers
274+
275+
Whichever proxy you use, verify these headers pass through unchanged:
276+
277+
| Header | Purpose | What breaks if stripped |
278+
| --- | --- | --- |
279+
| `Authorization` | OAuth bearer token | Auth fails; the runtime returns `401` |
280+
| `Mcp-Session-Id` | Session continuity | Each request starts a new session |
281+
| `MCP-Protocol-Version` | Protocol negotiation | Connection errors with strict clients |
282+
283+
The path `/mcp/{slug}` must also pass through intact. The runtime routes by gateway slug from the path.
284+
285+
## Client compatibility
286+
287+
| Client | Connectivity | Auth mode |
288+
| --- | --- | --- |
289+
| Claude (Messages API or managed agents) | Warp Pipes or any proxy | Arcade Auth or User Source only |
290+
| Cursor, Cline, Claude Desktop | Warp Pipes or any proxy | All modes |
291+
| ChatGPT, OpenAI agents | Warp Pipes or any proxy | All modes |
292+
| Custom agents | Warp Pipes or any proxy | All modes |
293+
294+
## Known limitations
295+
296+
| Item | Notes |
297+
| --- | --- |
298+
| Arcade Headers with the Anthropic Messages API | Not compatible. The connector supports only `authorization_token`, with no custom headers. Use Arcade Auth or User Source. |
299+
| nginx buffering (bring-your-own proxy) | `proxy_buffering off` is required. Without it, nginx buffers streamed responses and clients never receive them. |
300+
| `Mcp-Session-Id` pass-through (bring-your-own proxy) | Verify your proxy forwards this header. Stripping it silently breaks session continuity for streamable HTTP clients. |
301+
| Wildcard apex mismatch | `*.corp.internal` does not match `corp.internal`. Register the apex separately if the runtime needs to reach it. |
302+
| CIDR with split-horizon DNS | CIDR entries match against the resolved IP. If a hostname resolves to different IPs inside and outside the network, use exact-host or wildcard entries instead. |
303+
304+
## Next steps
305+
306+
- [Configure the Arcade runtime](/guides/deployment-hosting/configure-engine) for the full `engine.yaml` reference
307+
- [Create an MCP Gateway](/guides/mcp-gateways) to scope tools and auth for each client
308+
- [Set up a User Source](/guides/user-sources) to authenticate end users with your own identity provider
309+
- [Connect your MCP client](/get-started/mcp-clients) to a gateway URL

app/en/resources/_meta.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export const meta: MetaRecord = {
2222
"contact-us": {
2323
title: "Contact",
2424
},
25+
"registry-early-access": {
26+
display: "hidden",
27+
},
28+
"early-access": {
29+
title: "Early Access",
30+
},
2531
};
2632

2733
export default meta;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { MetaRecord } from "nextra";
2+
3+
const meta: MetaRecord = {
4+
"warp-pipes": {
5+
title: "Warp Pipes",
6+
href: "/en/guides/deployment-hosting/warp-pipes",
7+
},
8+
registry: {
9+
title: "Arcade Registry",
10+
href: "/en/resources/registry-early-access",
11+
},
12+
};
13+
14+
export default meta;

0 commit comments

Comments
 (0)