-
Notifications
You must be signed in to change notification settings - Fork 1
Troubleshooting
Logs go to stderr. Bump verbosity with LOG_LEVEL=debug (or trace) to see
discovery, token, and bridge activity. Secrets are redacted automatically.
The proxy prints the authorize URL to stderr — copy it and open it manually. On a remote host, also forward the callback port. See Remote Hosts (SSH Port Forwarding).
The redirect URI the proxy uses (http://127.0.0.1:53682/callback by default,
or your redirectUri / callbackPort override) must be registered exactly
with your IdP. Register the loopback form, and keep the port in sync with
OAUTH2_CALLBACK_PORT.
The interactive flow waits callbackTimeoutSeconds (default 300) for you to
finish. Increase it, or check that the callback port is reachable (firewall, or
a broken SSH forward).
The merged configuration failed zod validation, or a required field is missing,
or token prefetch failed. Read the stderr message — it names the offending
field. Common causes: missing clientId/tokenUrl, a non-integer port or
timeout, or malformed OAUTH2_EXTRA_PARAMS JSON. See Configuration.
A non-loopback http:// URL was supplied or discovered. Switch to https://,
use a loopback SSH tunnel, or (trusted local testing only) set
ALLOW_INSECURE_HTTP=true. See Security.
Confirm the upstream serves /.well-known/oauth-protected-resource. If not,
disable discovery (DISCOVERY_ENABLED=false) and set oauth2.tokenUrl (and
oauth2.authorizationUrl for interactive login) explicitly. See Discovery.
The proxy invalidates the token and retries once on a 401. Persistent 401s
usually mean wrong scope/audience, an expired or revoked grant, or a
client not authorized for the resource. Check the upstream's auth requirements.
Raise upstream.timeoutMs (UPSTREAM_TIMEOUT_MS) above your MCP client's
tool-call timeout. The default is 5 minutes.
Server-initiated notifications require the long-lived server stream. Ensure
upstream.openServerStream is true and that the upstream supports a
GET text/event-stream channel. The proxy disables the stream if the upstream
answers 404/405. See Bridge Internals.
Delete the encrypted cache file in the token cache directory (see
OAuth2 Grants and Tokens for paths) or point OAUTH2_TOKEN_CACHE_DIR
elsewhere, then relaunch to trigger a fresh interactive login.
Does it support multiple upstreams at once? No — one proxy process targets one upstream. Run multiple proxy instances for multiple upstreams.
Does it do per-user delegation / multi-tenant auth?
No. It acts as a single configured OAuth2 client. For end-user identity, use the
authorization_code grant so the token represents the logged-in user.
Can it inject my own Authorization header from the client?
No. The proxy owns the upstream Authorization header. See Security.
Is the refresh-token cache safe? It's AES-256-GCM encrypted at rest, but the key lives beside it for non-interactive relaunch. It protects against casual exposure, not an attacker with access to your user account. See Security.
Still stuck? Open an issue at
github.com/ChengleiYuan/mcp-oauth2-proxy/issues
with LOG_LEVEL=debug output (secrets are redacted).
GitHub repo · npm package · Licensed under MIT
Overview
Guides
- Getting Started
- Configuration
- OAuth2 Grants and Tokens
- Discovery
- Security
- Remote Hosts (SSH Port Forwarding)
- Troubleshooting
Internals