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.

Restrictions​

MCP keys authenticate only through MCP. A direct Public API call with an MCP key answers 401; scripts and services use an API token or OAuth. MCP-only controls, such as tool allowlists and security-level confirmations, never apply to a direct call, so the key cannot be reused there.

The optional restriction field limits a key to one account and, optionally, to some of its apps, regions, and sandbox templates:

FieldRequiredDescription
accountIdYesThe only account the key can reach. You must be a member of it.
appIdsNoApps of that account the key can use. Omit for every app.
regionsNoRegions where the key can create sandboxes. Omit for every region.
templateIdsNoSandbox templates the key can use. Omit for every template.

A restricted key can call only the Agent Sandboxes and sandbox template tools; every other tool answers 403. A sandbox, template, region, or accountId outside the restriction answers 403. An app-restricted key must pass appId when it lists sandboxes, can use but not change account-wide templates, and can create templates only for its apps. A key with templateIds cannot create templates.

The key still acts as its owner: every request also needs the owner's own account permissions, so a key can never do more than its owner.

Create a restricted sandbox key:

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "sandbox-agent",
"enabledScopes": [
"quave:read",
"quave:write:config",
"quave:write:deploy",
"quave:write:dangerous"
],
"securityLevel": "balanced",
"sessionDuration": 1800,
"restriction": {
"accountId": "ACCOUNT_ID",
"appIds": ["APP_ID"],
"regions": ["us-5"]
},
"returnSecret": true
}' \
https://api.quave.cloud/api/public/v1/mcp-key

On update, omit restriction to keep the stored value or send "restriction": null to remove it. Metadata responses include restriction. The dashboard MCP page keeps it when you edit a key there.

Limit accounts​

By default an MCP key reaches every account its owner is a member of. Set limitAccounts: true with allowedAccountIds to limit the key to chosen accounts. In the dashboard this is the Limit accounts switch on the MCP key form.

FieldDescription
limitAccountstrue limits the key. On update, false removes the limit and omitting it keeps the stored value.
allowedAccountIdsAccounts the key can reach. Required with limitAccounts: true. You must be a member of each one.

The limit is enforced on every MCP tool call:

  • A call that names, or resolves to, any other account answers 403. This covers accountId, appId, appEnvId, the current account, and resources such as alerts, credentials or backups that belong to another account.
  • list-accounts returns only the allowed accounts.
  • The key never uses its owner's internal Quave roles, so it acts only as a member of the allowed accounts.
  • get-user-token and create-account answer 403, because their results would not be limited. Personal LLM provider keys and AI subscriptions also answer 403, because they are outside every account.
  • Agent automations and agent profiles can use only MCP keys limited to the same or fewer accounts. Automations whose key reaches further are hidden.
  • A limited key can see and manage only keys limited to the same or fewer accounts. It can create keys only with limitAccounts: true and accounts within its own limit, and it cannot remove a limit.

When the owner loses membership of an allowed account, that account is removed from the key. A key left without accounts is disabled and stays limited; it never becomes a key for every account. Choose an account again before enabling it.

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

If the key also has a restriction, its accountId must be one of the allowedAccountIds.

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, enabledTools, limitAccounts, and allowedAccountIds. 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

Set or clear the default MCP key​

A user has at most one default MCP key. Setting a new default clears the previous one. A disabled key cannot be the default; disabling or deleting the default key clears it. A new web agent chat preselects this key when the chat was not opened from an automation run that still has its own enabled key.

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "keyId": "MCP_KEY_ID", "isDefault": true }' \
https://api.quave.cloud/api/public/v1/mcp-key/default

Send "isDefault": false to clear the default without choosing another key.

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'