Origin MCP Servers
An Origin MCP is the upstream MCP server the gateway proxies to. It's the real thing — a remote MCP server hosted by Linear, Stripe, GitHub, Grafana, your own internal service, or any other provider — that exposes tools, prompts, and resources over MCP's Streamable HTTP transport.
The gateway's job is to sit in front of one or more Origins, handle the client-facing auth and policy, then forward each call upstream. Every Virtual MCP server you publish through the gateway points at exactly one Origin — one upstream MCP server per route — and exposes a curated subset of that upstream's tools. Without an Origin, a Virtual MCP has nothing to call.
Origin vs. Virtual MCP
The two concepts are easy to confuse. The split is deliberate:
| Origin MCP | Virtual MCP | |
|---|---|---|
| Who configures it | Gateway operator | Gateway operator |
| Who connects to it | The gateway (server-to-server) | AI clients (Claude, Cursor, ChatGPT, etc.) |
| What it points at | A real upstream MCP server URL | A curated subset of one Origin's tools |
| Auth surface | Upstream provider's OAuth, API keys, or no auth | Gateway-issued OAuth bearer tokens |
| URL | The provider's URL (e.g., https://mcp.linear.app/mcp) | ${deploymentUrl}/v1/mcp/{slug} |
See Virtual MCP Servers for the client-facing side.
Configure in the portal
Open Origin MCP in the Zuplo Portal. When the project has no origins yet, the empty state reads "Let's add your first MCP" with an Add Origin MCP button. Once at least one origin exists, the same button appears in the top-right.
Add an Origin
-
Click Add Origin MCP.
-
In the Create Origin MCP dialog, fill in the fields:
Field Required Notes Name Yes A short label shown in the origins list and tool picker. Description No A one-line summary of what this origin provides. Origin URL Yes The upstream MCP server URL, e.g. https://mcp.linear.app/mcp. -
Click Create.
The new origin appears in the list. The gateway calls the upstream's
tools/list to fetch the tools the origin exposes; once they load, the card's
"N Tools available" badge updates.
Click the badge to open the Tools available dialog, which lists each tool the upstream advertises with its name and description.
Edit or delete an Origin
On any origin card:
- The Copy URL button copies the upstream URL.
- The overflow menu has:
- Edit — reopens the form with the existing values.
- Delete — removes the origin. Tools that came from this origin are removed from any Virtual MCP that referenced them.
- The Reload Tools menu item is a placeholder in the current release and is disabled. Reloads happen automatically; there is no manual button yet.
Authenticated upstreams
Many upstream MCP servers require authentication — most commonly OAuth or an API key on every request. The portal form on the Origin dialog has fields for an API Key and Manual Headers, but these fields are not yet persisted on submit. Only the Name, Description, and Origin URL are saved.
Until upstream auth is wired through the portal, configure authenticated upstreams in code. Two patterns cover most cases:
Pattern 1: API key in a header
Use a standard Zuplo header policy on the route. The gateway adds the header on its way to the upstream, and the client never sees the key.
Code
Code
The route uses McpProxyHandler for the forwarding, an OAuth policy for the
client-facing auth, and set-upstream-api-key-inbound to attach the API key
before the request goes upstream. The $env(...) reference reads the value from
the project's environment variables — never check raw keys into source control.
For arbitrary header values (not necessarily API keys), use
set-headers-inbound instead.
Pattern 2: Per-user OAuth to the upstream
When the upstream provider supports OAuth and you want each end user to connect
with their own identity, use the mcp-token-exchange-inbound policy. The
gateway runs the upstream OAuth flow on behalf of the user, stores the resulting
tokens encrypted, and injects an Authorization: Bearer header on every request
to the upstream.
Code
Code
When a client makes its first call to /mcp/linear-v1 without a stored upstream
connection, the gateway returns a JSON-RPC connect-required error with a URL the
user opens in a browser to complete the upstream OAuth dance. After the user
authorizes, the gateway stores the tokens and the same call succeeds. See the
mcp-token-exchange-inbound policy reference for the full lifecycle, including
per-user vs. shared OAuth, scope handling, and the clientRegistration modes.
Tool discovery
The gateway calls the upstream's tools/list to populate the Tools
available view in the portal. The list refreshes on its own schedule.
If a tool you expect doesn't show up:
- Confirm the upstream exposes it. Some MCP servers gate certain tools
behind authentication state, scopes, or admin-only features. A
tools/listfrom an unauthenticated context returns less than atools/listfrom an authenticated one. - Confirm the Origin URL is reachable. A misconfigured URL or a network block returns no tools. The browser error page details which gateway error fired and the underlying upstream response.
- Confirm the upstream returns valid MCP. If the upstream returns HTML or a non-MCP JSON response, the gateway treats it as a failure rather than pretending it succeeded with zero tools.
What an Origin is not
A few common misreadings:
- An Origin is not a route in the gateway's OpenAPI. Routes are exposed by
Virtual MCPs (
/mcp/{slug}); Origins are upstream targets. One Origin can back many Virtual MCPs (for example, a read-only Linear route and a full-power Linear route), but each Virtual MCP points at exactly one Origin. - An Origin is not an auth boundary by itself. The gateway authenticates inbound traffic at the Virtual MCP route; the Origin describes where to forward authenticated requests. Use route policies to add upstream auth.
- An Origin doesn't host MCP tools. It points at a server that does. The tool definitions, input schemas, and execution all live in the upstream.
Code-configured origins
When configuring the gateway entirely in code (no portal), the Origin is expressed by two things in the route definition:
- The
rewritePatternonMcpProxyHandler.options, which is the upstream URL. - The inbound policies that handle upstream credentials and any request transformation.
Once the route is in routes.oas.json and the gateway deploys, the upstream is
reachable through the route's path. There's no portal-managed Origin record in
this mode — the route itself is the configuration.
If you started in the portal and want to move to code-config, copy the upstream
URL from the Origin card into the rewritePattern of the new route, recreate
the upstream auth policy, and remove the portal Origin once the code route is
live. See Virtual MCP Servers
for the full route shape — one route per upstream, each with its own
token-exchange or API-key policy.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| "N Tools available" is 0 after a few seconds | Upstream is unreachable, returns HTML, or rejects unauthenticated tools/list. Verify the URL and any upstream auth. |
| Connect-required popup loops | Upstream OAuth client registration is failing. Set explicit scopes or switch to clientRegistration: { mode: "manual" }. |
| Headers from the portal form vanish | Portal headers/API key fields are not persisted today. Move upstream auth to a code-config policy. |
| A tool name changed upstream | Tools are matched by name throughout the system. Update any references in Virtual MCP tool selections or capability filter allow-lists. |
For deeper auth debugging, the gateway's browser error page surfaces the gateway error code and request ID along with the raw upstream HTML when relevant. Include those in any support request.
Reference
- Virtual MCP Servers — how to select tools from Origins and expose them to clients.
- Capability Filtering — narrow what an Origin exposes downstream.
mcp-token-exchange-inbound— per-user OAuth to upstream MCP servers.set-upstream-api-key-inboundandset-headers-inbound— set upstream credentials when the provider uses API keys or static headers.McpProxyHandler— the route handler that does the forwarding.