vault
For developersSign in

For developers

What your assistant needs to call a person’s vault: one endpoint, standard OAuth 2.1 discovery, and three ways to register a client.

The endpoint
https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com

This address is the same for every person and is not a secret. Authorization is carried entirely by the bearer token you send with each call, never by the URL. The host above is a staging environment placeholder — expect a different, stable host at general availability.

How a client discovers how to authenticate
The endpoint is an OAuth 2.1 protected resource. It refuses every unauthenticated call, and the refusal itself carries the next step.
  1. POST the endpoint with no token. It returns 401 with a WWW-Authenticate header pointing at the protected-resource metadata (shown below).
  2. GET https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com/.well-known/oauth-protected-resource returns authorization_servers, which names the authorization server — here, the same host.
  3. GET https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com/.well-known/oauth-authorization-server returns the authorization server’s metadata, including client_id_metadata_document_supported: true, the grant types it accepts, and the endpoints to use for the next step.
  4. Register a client with CIMD or DCR (below).
  5. Run the standard OAuth 2.1 authorization-code + PKCE flow. The person sees a Frontegg-hosted login and consent screen, then your client receives an access token scoped to that person.
  6. Call tools with Authorization: Bearer <access_token> on every request — the transport is stateless POST-only JSON-RPC, so there is no session to hold open between calls.
unauthenticated request
POST https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com/ HTTP/1.1
(no Authorization header)

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com/.well-known/oauth-protected-resource"
Client ID Metadata Documents — the preferred path

Our authorization server advertises client_id_metadata_document_supported: true, and it is live today. A Client ID Metadata Document (CIMD) needs no registration handshake with us at all: your client_id is itself an HTTPS URL, and that URL is the metadata document.

mcp-client.json (example CIMD document)
{
  "client_id": "https://muse.ai/.well-known/mcp-client.json",
  "client_name": "Muse AI",
  "redirect_uris": [
    "https://muse.ai/oauth/callback"
  ],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "none"
}

Serve that document over HTTPS at the exact URL you use as client_id. Required fields: client_id (must equal the document’s own URL), client_name, redirect_uris, grant_types, and token_endpoint_auth_method.

Dynamic Client Registration — by invitation

DCR also exists, at https://x9rilcl1ridha36n9ty02.stg.frontegg.com/oauth/dcr/register, but every redirect domain must be allowlisted before a registration from it is accepted. CIMD needs no permission from us; DCR does. Email partners@agen.co with the redirect URI(s) you need added, and we will confirm once your domain is on the list.

No browser — server-to-server clients

A client that never runs in a browser can use a pre-registered client instead: the person issues you a client_id and client_secret from their vault, and you exchange them at the token endpoint using grant_type=client_credentials (client_secret_basic or client_secret_post). The access token you get back is scoped to that one person and is short-lived — measured at five minutes on staging. Never send the client secret itself on an MCP call; only the access token you exchanged it for.

client_credentials exchange
curl -X POST https://x9rilcl1ridha36n9ty02.mcp-gw.stg.frontegg.com/token \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -d grant_type=client_credentials

# -> { "access_token": "...", "token_type": "Bearer", "expires_in": 300 }
# Send that short-lived access token as the Bearer on every MCP call.
# Never send $CLIENT_SECRET itself on an MCP call.
What your client will see: tools appear only for services the person has connected and switched on. A vault with nothing switched on returns an empty tool list — that is a configuration state on the person’s side, not an error in your integration.