Upstream Authentication
Two separate questions get conflated in MCP setups. How does the client authenticate to the gateway? (Your Waxell OAuth session or an API key — covered in the Quickstart.) How does the gateway authenticate to each upstream? That's this page, and it's per-upstream — the auth_mode on the upstream row.
MCP OAuth (mcp_oauth_dcr) — the zero-credential default
Most modern vendor MCP servers (Notion, Linear, Calendly, Stripe, Monday, 100+ in the catalog) implement the MCP authorization spec. For these, nobody ever touches a vendor developer console:
- Discovery — the gateway asks the server itself how to authenticate: the server's 401 response points at its protected-resource metadata (RFC 9728), which names its authorization server, whose metadata (RFC 8414) provides the authorize, token, and registration endpoints.
- Dynamic client registration — the gateway registers itself as an OAuth client programmatically (RFC 7591), preferring a public client secured by PKCE. Happens once per tenant, on the first connect.
- Per-user authorization — each user does a standard consent dance (authorization code + PKCE, with the token bound to the specific MCP server via RFC 8707
resource). - Silent refresh — tokens refresh automatically for the life of the grant, including providers that rotate refresh tokens.
Discovery results and the registered client are cached on your tenant's upstream row; everyone after the first user goes straight to the consent screen. This is what the Auto OAuth badge means in the catalog, and it works for any spec-compliant server you add as a custom upstream.
A few servers speak MCP OAuth but don't offer dynamic registration (DocuSign, PagerDuty, Smartsheet, the Google Cloud services). Same mode, one extra step: an admin registers an OAuth app with the vendor once and stores the client credentials on the upstream — the discovery and per-user flows are unchanged.
Open (no_auth)
Some servers are simply public — Microsoft Learn, PubMed, AWS Marketplace, Open Targets. The gateway sends no Authorization header at all to these (forwarding a stray token to a third party would leak it). Why route an open server through the gateway? Because the caller still authenticates to Waxell, and policy, rate limits, and audit still apply. Open upstream ≠ ungoverned upstream.
Classic per-user OAuth (oauth_per_user)
The traditional flow for providers without MCP-spec auth: an admin registers an OAuth app with the vendor (or uses Waxell's platform-registered app where available), pastes the client ID and secret on the catalog entry or upstream row, and users connect individually. Per-provider protocol quirks (token endpoint auth style, body encoding, scope separators, PKCE) are handled by a built-in dialect engine that discovers, learns, and remembers each provider's dialect.
The rest of the modes
| Mode | What it does | Use when |
|---|---|---|
tenant_api_key | One tenant-wide key, resolved from the Waxell secret store at call time — the key itself never sits on the gateway | Vendor offers API keys, per-user identity not needed |
shared_service_account / byo_token_env | A token the gateway holds (secret store or environment variable) | Internal servers, legacy setups |
forward_caller_token | Passes the caller's own Waxell bearer through | Upstream shares Waxell's auth (e.g. Waxell's own MCPs) |
Credential precedence
When multiple credentials could apply, the gateway resolves: tenant's own (BYO) credentials → Waxell platform credentials → environment fallback. Per-user grants are always stored encrypted at rest and scoped to (user, upstream) — revocable individually from the Connections page.