Skip to main content

MCP Keys API

The MCP Keys API manages the same user-owned MCP keys shown on the dashboard MCP page. Keys support two server-enforced authorization modes:

  • SCOPES grants the tools covered by enabledScopes. This is the legacy behavior and remains the default.
  • TOOLS grants only the tool names stored in enabledTools.

Tool groups are presentation metadata only. The API stores explicit tool names, not group grants, so a tool added to a group later is not automatically granted to an existing key.

Security and validation

  • Regular user tokens can manage keys owned by the authenticated user, matching the dashboard behavior.
  • MCP callers must be authorized for the specific MCP key-management tool they call. In scope mode this comes from quave:manage:mcp-keys; in tool mode the management tool itself must be selected.
  • Deleting MCP keys still carries both the MCP-key-management and dangerous-operation requirements.
  • Returning or revealing raw key plaintext still carries the secret-read requirement and emits a secret-decrypt audit event for reveal.
  • Account, app, and environment permissions, admin checks, confirmations, previews, MFA, and audit logging continue to apply in both modes.
  • Tool mode rejects an empty allowlist and unknown tool names, and normalizes duplicate names.
  • Send only the active grant field. enabledTools requires explicit authorizationMode: TOOLS, while tool mode rejects enabledScopes instead of silently interpreting either payload as a scope-mode key.
  • Tool-mode records persist enabledScopes: []. This inactive legacy field makes a rollback to a pre-tool-aware server fail closed instead of broadening the key to read access.
  • Omit enabledScopes from tool-mode create/update requests. Pre-tool-aware app instances reject the missing legacy field during a rolling deploy instead of silently creating a scope-mode read key.
  • Name, authorization, security-level, and session-duration validation is shared with dashboard methods.

For a tool-mode request, Quave ONE derives only the scopes declared by the current selected tool. Every unconditional requiredScopes entry and every declared secondaryScopes entry for that tool is available to that request. This means selecting a tool authorizes its complete declared parameter surface, including optional secret-returning behavior where documented. The derived scopes do not authorize any other unselected tool, and the normal secret/admin/audit protections still run.

Backward compatibility

Records with a missing or unrecognized authorizationMode are treated as SCOPES. Migration 156 marks those records as SCOPES without changing enabledScopes, key IDs or secrets, enabled state, security level, session duration, timestamps, or any other field. It does not create enabledTools, so existing keys keep the same discovery and execution behavior and require no reconfiguration.

Delegating keys from an MCP key

A calling MCP key can list or manage only keys with the same or less effective access:

  • SCOPES to SCOPES: the target scopes must be a subset of the caller scopes.
  • SCOPES to TOOLS: every scope declared by every selected target tool must be available to the caller.
  • TOOLS to TOOLS: the target allowlist must be a subset of the caller allowlist.
  • TOOLS to SCOPES: denied. A finite allowlist cannot safely grant a scope whose effective tool set may grow when new tools ship.

The same comparison applies when changing a key's authorization mode. An MCP caller cannot reveal, rotate, toggle, or delete a target key outside its effective access.

List and get MCP keys

curl -H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/mcp-keys'
curl -H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/mcp-key?keyId=MCP_KEY_ID'

Metadata responses include authorizationMode, enabledScopes, and enabledTools. Raw key plaintext is never included.

Create a scope-mode key

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "automation-read",
"authorizationMode": "SCOPES",
"enabledScopes": ["quave:read"],
"securityLevel": "balanced",
"sessionDuration": 1800,
"returnSecret": true
}' \
https://api.quave.cloud/api/public/v1/mcp-key

Omitting authorizationMode preserves the legacy SCOPES default. quave:read is always included in a scope-mode key.

Create a tool-mode key

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "health-check",
"authorizationMode": "TOOLS",
"enabledTools": [
"get-current-account",
"list-apps",
"get-account-observability-summary"
],
"securityLevel": "balanced",
"sessionDuration": 1800,
"returnSecret": true
}' \
https://api.quave.cloud/api/public/v1/mcp-key

Only the explicit names in enabledTools are discoverable and callable. New tools remain denied until the key is updated. If returnSecret is true and authorized, the response includes rawKey once; store it immediately.

Update or toggle an MCP key

Send the full authorization configuration when updating. Changing modes is validated with the same delegation rules as creation.

curl -X PATCH \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"keyId": "MCP_KEY_ID",
"enabled": true,
"authorizationMode": "TOOLS",
"enabledTools": ["list-apps", "list-app-envs"],
"securityLevel": "strict",
"sessionDuration": 900
}' \
https://api.quave.cloud/api/public/v1/mcp-key
curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "keyId": "MCP_KEY_ID", "enabled": false }' \
https://api.quave.cloud/api/public/v1/mcp-key/toggle

Regenerate, reveal, or delete

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "keyId": "MCP_KEY_ID", "name": "automation-read-2", "returnSecret": true }' \
https://api.quave.cloud/api/public/v1/mcp-key/regenerate
curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/mcp-key/reveal?keyId=MCP_KEY_ID'
curl -X DELETE \
-H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/mcp-key?keyId=MCP_KEY_ID'