Ratel Docs
Manage

OAuth upstreams

Authorize remote MCP servers, inspect token status, and recover from expired credentials.

HTTP and SSE upstreams can authorize through Ratel Local's loopback OAuth 2.1 and PKCE flow. mcp add starts the flow when the server requires it.

ratel-mcp mcp add --scope user stripe \
  https://mcp.stripe.com --transport http

Tokens persist at ~/.ratel/oauth/<name>.json. They are reused across host sessions.

Ratel Local creates the directory with mode 0700 and token files with mode 0600 where the operating system supports those permissions. Treat the files as secrets.

For an upstream without dynamic client registration, provide its client details:

ratel-mcp mcp add --scope user private-api \
  https://mcp.example.com --transport http \
  --client-id "$OAUTH_CLIENT_ID" \
  --client-secret "$OAUTH_CLIENT_SECRET" \
  --oauth-scope "mcp:tools"

Use --callback-port when the provider requires a fixed loopback redirect port.

Static client secrets are configuration

--client-secret is stored as plain text in Ratel config and can appear in config backups. Restrict access to those files and prefer dynamic client registration when the provider supports it.

Check or renew authorization

ratel-mcp mcp auth stripe
ratel-mcp mcp auth
ratel-mcp mcp auth --check
ratel-mcp mcp list

mcp auth <name> tries a refresh token before opening a browser. Without a name, it authorizes every upstream currently marked as needing authentication. --check reports status from locally stored token metadata without contacting the provider.

mcp list shows one of these values for each entry:

StatusMeaning
okAn access token exists and its recorded expiry has not passed; this is not a live provider check
expiredThe recorded access-token expiry has passed
needs authStart or repeat the authorization flow
unsupportedDynamic client registration was rejected; a configured static client may still work
n/aAuthentication does not apply

At startup, Ratel Local checks stored tokens for HTTP and SSE upstreams. It refreshes a token within 60 seconds of expiry. A failed refresh clears the stored tokens so the next authorization starts cleanly.

An access-token-only file cannot be refreshed at startup, even while its recorded access token is still fresh. Ratel Local marks that upstream as needing authentication. Run ratel-mcp mcp auth <name> to establish a complete token set.

If dynamic client registration is unsupported, add the upstream again with --client-id and, when required, --client-secret. A named mcp auth attempt waits up to five minutes for the loopback callback after opening the browser.

Recover from a 401

A live upstream 401 returns a structured needs_auth error from invoke_tool. The response includes a recovery hint and the upstream name when Ratel Local can infer it.

The host can then call Ratel Local's auth capability tool. Pass an upstream name to authorize one server or omit it to handle every server that needs authentication.

The tool returns a row per upstream with authorized, skipped, failed, or unsupported. Failed rows include the message in reason instead of becoming MCP protocol errors.

The tool description lists the upstreams that currently need authentication. The model can see what to repair before it calls the tool.

If a 401 persists:

  1. Run ratel-mcp mcp auth --check and then ratel-mcp mcp auth <name>.
  2. Confirm the configured OAuth scopes and static client details match the provider.
  3. Restart the Ratel Local gateway, then start a new host session so it reconnects.
  4. Inspect local telemetry for authorization and upstream errors.

The shared capability result contract lives on Progressive disclosure. OAuth lifecycle events use the vocabulary on Telemetry.

Use the browser UI

The Browser UI can start the same upstream authorization flow. It remains bound to loopback and requires the session token in its launch URL.

Next steps

On this page