Repository navigation
Upstream OAuth
When an upstream MCP server requires OAuth 2.0 authentication, vMCP can act as an OAuth client, automatically obtaining and presenting Bearer access tokens using the OAuth 2.0 Client Credentials Grant (RFC 6749 §4.4).
OAuth settings are configured per upstream under the auth block in the REST API, declarative configuration, or the Web UI (Upstreams page):
{
"slug": "crm-service",
"name": "CRM Service",
"url": "https://crm.internal.example.com/mcp",
"transport": "streamable_http",
"auth": {
"type": "oauth_client_credentials",
"tokenUrl": "https://auth.internal.example.com/oauth/token",
"clientId": "vmcp-gateway",
"clientSecret": "super-secret-key",
"scopes": ["crm.read", "crm.write"],
"audience": "https://crm.internal.example.com"
}
}| Field | Type | Description |
|---|---|---|
type |
string |
oauth_client_credentials or none (to disable OAuth) |
tokenUrl |
string | Absolute HTTP(S) URL of the authorization server's token endpoint |
clientId |
string | Client identifier issued by the identity provider |
clientSecret |
string |
Write-only. Encrypted at rest using AES-256-GCM (VMCP_SECRET_KEY). Never returned in API responses or export files. |
scopes |
string[] | Optional array of OAuth scopes requested in scope parameter |
audience |
string | Optional audience parameter sent to token endpoint (standard for Auth0, Keycloak, etc.) |
Caution
An upstream cannot have both OAuth client credentials and a static Authorization header configured. Attempting to save both produces an HTTP 422 validation error.
The gateway manages token acquisition transparently:
- Process-wide cache: All agent sessions and internal operations (tool discovery, health probes, connection tests) share one token cache per upstream configuration.
- Singleflight concurrency: Multiple simultaneous requests wait on a single in-flight token fetch rather than hammering the identity provider.
-
Proactive refresh: Tokens are refreshed approximately 30–40 seconds before their
expires_indeadline with randomized jitter. -
Reactive 401 retry: If an upstream rejects a token with
HTTP 401 Unauthorized(e.g. revoked token), vMCP invalidates the cached token, requests a fresh token, and replays the request once.
vMCP isolates identity provider failures from upstream server health:
- Circuit breaker protection: If the OAuth token endpoint is unreachable or returns HTTP errors, the call fails immediately with an explicit error. Crucially, token acquisition failures do not count toward the upstream's circuit breaker, ensuring temporary IdP outages do not mark healthy upstream services as broken.
-
Secret masking: If an identity provider echoes the client secret in an error message, vMCP redacts it (
***) before logging or returning error responses.
In declarative exports (GET /api/v1/export), the auth block is exported without secrets:
upstreams:
- slug: crm-service
name: CRM Service
url: https://crm.internal.example.com/mcp
transport: streamable_http
auth:
type: oauth_client_credentials
tokenUrl: https://auth.internal.example.com/oauth/token
clientId: vmcp-gateway
scopes: [crm.read, crm.write]
audience: https://crm.internal.example.comWhen re-applying this document via POST /api/v1/apply, omitting clientSecret preserves the existing encrypted secret in the database.
vMCP is licensed under Apache-2.0. This wiki is generated from the docs/ folder of the repository: send documentation fixes as pull requests, not wiki edits.
- Getting started
- Guided setup and client connections
- Installation options
- Kubernetes quickstart
- Install a published release
- Upstreams
- Virtual servers
- Resources and prompts
- Agent keys and authentication
- OAuth for agents
- SSO and roles
- Tool policies
- PII masking
- Rate limits
- Audit log
- FAQ and troubleshooting