Skip to content

MCP tools

Served at POST /mcp when mcp.enabled is on. Each tool re-dispatches into the admin route it names, so it runs the console's own checks and writes the console's own audit entry. High-consequence tools require a second call confirming the specific operation.

Reads

whoami

The administrator this agent is acting as: their id, email, roles, and the projects they manage.

Route GET /admin/api/me

project_list

Every project a super-administrator can see, or just the projects the caller manages.

Route GET /admin/api/projects

project_get

One project: name, slug, managers, assigned user bucket, client ids, and CORS origins.

Route GET /admin/api/projects/:id

client_list

The OAuth clients registered in a project. Never returns a client secret.

Route GET /admin/api/projects/:id/clients

client_get

One OAuth client: redirect URIs, grant types, auth method, and other registered metadata. Never returns its secret — a secret is shown once at creation or rotation and is not readable afterwards.

Route GET /admin/api/projects/:id/clients/:clientId

admin_list

The administrator accounts of this instance, with their roles.

Route GET /admin/api/admins

admin_settings_read

The sign-in policy of the administrator bucket itself. `totpRequired` says whether signing in to the console also needs a one-time code from an authenticator app. The bucket's other settings are deliberately not exposed.

Route GET /admin/api/admins/settings

group_list

The groups this administrator belongs to. A group owns projects and user buckets, and belonging to it is what grants access to them.

Route GET /admin/api/groups

group_get

One group: its name, kind, and the administrators in it with their membership kind. A plain member may read this; only an owner may change it.

Route GET /admin/api/groups/:id

group_invitation_list

Pending invitations into a group. Never returns an invitation token — a token exists only in the mail it was sent in.

Route GET /admin/api/groups/:id/invitations

scope_get

The console's active group and the groups available to switch to. An agent has no console session: name a group per call instead of switching.

Route GET /admin/api/scope

bucket_list

The user buckets: every one for a super-administrator, otherwise those the caller manages. The reserved administrator bucket is never listed.

Route GET /admin/api/buckets

bucket_get

One user bucket: its name, roles, managers, and registration and verification settings.

Route GET /admin/api/buckets/:id

bucket_user_list

The end-user accounts held in one bucket.

Route GET /admin/api/buckets/:id/users

federation_provider_list

The upstream identity providers configured on a bucket. Never returns a provider client secret.

Route GET /admin/api/buckets/:id/federation

federation_identity_list

The upstream identities linked to one end-user account, by provider.

Route GET /admin/api/buckets/:id/users/:uid/identities

settings_get

The editable server settings, with the catalogue describing each one and its current value.

Route GET /admin/api/settings

smtp_settings_get

The outbound mail settings. The password is never returned, only whether one is set.

Route GET /admin/api/settings/smtp

sentry_settings_get

The Sentry integration settings. The ingestion credential is never returned, only whether one is set.

Route GET /admin/api/settings/sentry

jwks_list

The signing keys, each with its status, plus whether a restart is needed to apply pending changes. Public key material only — private components are never returned.

Route GET /admin/api/jwks

audit_list

The administrative audit trail for the groups this administrator belongs to, newest first, filterable by actor, action, target, surface and time window. A super administrator sees the whole instance, including actions that belong to no group. Filter `viaSurface=mcp` for actions taken through an agent. An entry means an authorized actor reached the point of applying a change, not that the change took effect.

Route GET /admin/api/audit

Input (query)
{
"type": "object",
"properties": {
"actor": {
"type": "string"
},
"action": {
"type": "string"
},
"targetType": {
"type": "string"
},
"targetId": {
"type": "string"
},
"targetScope": {
"type": "string"
},
"viaSurface": {
"type": "string"
},
"viaClientId": {
"type": "string"
},
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"page": {
"type": "string"
},
"pageSize": {
"type": "string"
}
}
}

error_list

Recorded internal server faults, newest first, one entry per distinct fault with an exact occurrence count. Filterable by error code, route, surface, status, client, actor and time window. Only defects are recorded — routine client rejections such as a bad grant or a wrong password never appear. A non-zero `dropped` means recording fell behind and the list is incomplete.

Route GET /admin/api/errors

Input (query)
{
"type": "object",
"properties": {
"errorCode": {
"type": "string"
},
"route": {
"type": "string"
},
"surface": {
"type": "string"
},
"status": {
"type": "string"
},
"clientId": {
"type": "string"
},
"actor": {
"type": "string"
},
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"limit": {
"type": "string"
},
"offset": {
"type": "string"
}
}
}

error_summary

How much is failing over a time window, broken down by error code and by endpoint, most frequent first. Counts sum occurrences rather than distinct faults, so one fault seen 900 times outranks nine seen once. Takes a window only — use error_list to filter by client, actor, status or surface.

Route GET /admin/api/errors/summary

Input (query)
{
"type": "object",
"properties": {
"from": {
"type": "string"
},
"to": {
"type": "string"
}
}
}

error_purge_preview

How many recorded faults, and how many occurrences, a purge with these filters would remove. Reads only — nothing is deleted. Available whether or not this deployment lets an agent perform the purge itself, because reading the consequence of a deletion is not destructive.

Route GET /admin/api/errors/purge-preview

Input (query)
{
"type": "object",
"properties": {
"errorCode": {
"type": "string"
},
"route": {
"type": "string"
},
"surface": {
"type": "string"
},
"status": {
"type": "string"
},
"clientId": {
"type": "string"
},
"actor": {
"type": "string"
},
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"limit": {
"type": "string"
},
"offset": {
"type": "string"
}
}
}

error_by_reference

Resolve the reference identifier a caller reported (it looks like err_XXXXXXXXXXXXXXXX) to the one fault it belongs to, and which occurrence it was. Answers not-found rather than an empty result, so a mistyped reference is distinguishable from a record that has aged out.

Route GET /admin/api/errors/reference/:reference

error_get

One recorded fault with its retained samples: where it arose, how often, when first and last seen. Samples are capped, so a very frequent fault keeps its earliest and its most recent occurrences while the count stays exact. No credential value is ever stored, so none can be read here.

Route GET /admin/api/errors/:id

Ordinary writes

project_create

Create a project: the container an instance groups OAuth clients into, with its own managers and CORS origins. A project has no user bucket until one is assigned.

Route POST /admin/api/projects · audit action project.create

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"type": "string"
},
"slug": {
"pattern": "^[a-z0-9-]+$",
"type": "string"
},
"corsOrigins": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"slug"
]
}

project_update

Change a project's name, managers, or CORS origins. An invalid origin refuses the whole list rather than applying part of it.

Route PATCH /admin/api/projects/:id · audit action project.update

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"type": "string"
},
"corsOrigins": {
"type": "array",
"items": {
"type": "string"
}
}
}
}

project_bucket_assign

Assign the user bucket whose accounts this project’s clients authenticate against.

Route PUT /admin/api/projects/:id/bucket · audit action project.bucket.assign

Input (body)
{
"type": "object",
"properties": {
"bucketId": {
"type": "string"
}
},
"required": [
"bucketId"
]
}

client_create

Register an OAuth client in a project. A confidential client’s generated secret is returned exactly once, here, and is never readable again.

Route POST /admin/api/projects/:id/clients · audit action client.create

Input (body)
{
"type": "object",
"properties": {
"clientName": {
"minLength": 1,
"type": "string"
},
"applicationType": {
"anyOf": [
{
"const": "web",
"type": "string"
},
{
"const": "native",
"type": "string"
}
]
},
"grantTypes": {
"minItems": 1,
"type": "array",
"items": {
"anyOf": [
{
"const": "authorization_code",
"type": "string"
},
{
"const": "refresh_token",
"type": "string"
},
{
"const": "client_credentials",
"type": "string"
},
{
"const": "urn:ietf:params:oauth:grant-type:device_code",
"type": "string"
},
{
"const": "urn:openid:params:grant-type:ciba",
"type": "string"
}
]
}
},
"redirectUris": {
"type": "array",
"items": {
"type": "string"
}
},
"postLogoutRedirectUris": {
"type": "array",
"items": {
"type": "string"
}
},
"tokenEndpointAuthMethod": {
"anyOf": [
{
"const": "none",
"type": "string"
},
{
"const": "client_secret_basic",
"type": "string"
},
{
"const": "client_secret_post",
"type": "string"
}
]
},
"scope": {
"type": "string"
},
"requireConsent": {
"type": "boolean"
},
"backchannelTokenDeliveryMode": {
"anyOf": [
{
"const": "poll",
"type": "string"
},
{
"const": "ping",
"type": "string"
}
]
},
"backchannelClientNotificationEndpoint": {
"type": "string"
},
"authorizationDetailsTypes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"grantTypes",
"tokenEndpointAuthMethod"
]
}

client_update

Change a client's registered metadata — redirect URIs, grant types, and the rest.

Route PATCH /admin/api/projects/:id/clients/:clientId · audit action client.update

Input (body)
{
"type": "object",
"properties": {
"clientName": {
"minLength": 1,
"type": "string"
},
"applicationType": {
"anyOf": [
{
"const": "web",
"type": "string"
},
{
"const": "native",
"type": "string"
}
]
},
"grantTypes": {
"minItems": 1,
"type": "array",
"items": {
"anyOf": [
{
"const": "authorization_code",
"type": "string"
},
{
"const": "refresh_token",
"type": "string"
},
{
"const": "client_credentials",
"type": "string"
},
{
"const": "urn:ietf:params:oauth:grant-type:device_code",
"type": "string"
},
{
"const": "urn:openid:params:grant-type:ciba",
"type": "string"
}
]
}
},
"redirectUris": {
"type": "array",
"items": {
"type": "string"
}
},
"postLogoutRedirectUris": {
"type": "array",
"items": {
"type": "string"
}
},
"tokenEndpointAuthMethod": {
"anyOf": [
{
"const": "none",
"type": "string"
},
{
"const": "client_secret_basic",
"type": "string"
},
{
"const": "client_secret_post",
"type": "string"
}
]
},
"scope": {
"type": "string"
},
"requireConsent": {
"type": "boolean"
},
"backchannelTokenDeliveryMode": {
"anyOf": [
{
"const": "poll",
"type": "string"
},
{
"const": "ping",
"type": "string"
}
]
},
"backchannelClientNotificationEndpoint": {
"type": "string"
},
"authorizationDetailsTypes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}

admin_settings_update

Require a one-time authenticator code for signing in to the administration console, on top of the password. Applies to every administrator; anyone without an authenticator sets one up at their next sign-in, so nobody is locked out. This also covers an agent obtaining a token interactively through the console's own client, so expect to supply a code.

Route PATCH /admin/api/admins/settings · audit action admin.settings.update

Input (body)
{
"additionalProperties": false,
"type": "object",
"properties": {
"totpRequired": {
"type": "boolean"
}
},
"required": [
"totpRequired"
]
}

admin_create

Create an administrator account.

Route POST /admin/api/admins · audit action admin.create

Input (body)
{
"type": "object",
"properties": {
"email": {
"format": "email",
"type": "string"
},
"password": {
"minLength": 12,
"type": "string"
},
"roles": {
"type": "array",
"items": {
"anyOf": [
{
"const": "super_admin",
"type": "string"
},
{
"const": "project_admin",
"type": "string"
}
]
}
}
},
"required": [
"email",
"password",
"roles"
]
}

admin_update

Change an administrator's roles or details.

Route PATCH /admin/api/admins/:id · audit action admin.update

Input (body)
{
"type": "object",
"properties": {
"roles": {
"type": "array",
"items": {
"anyOf": [
{
"const": "super_admin",
"type": "string"
},
{
"const": "project_admin",
"type": "string"
}
]
}
},
"active": {
"type": "boolean"
}
}
}

group_create

Create a group. The administrator this agent acts for becomes its first owner — a group with no owner would be unreachable the instant it existed.

Route POST /admin/api/groups · audit action group.create

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"maxLength": 100,
"type": "string"
}
},
"required": [
"name"
]
}

group_update

Rename a group, or clear the review flag the ownership migration set on it. Requires being an owner of that group, which is a membership kind rather than an instance role.

Route PATCH /admin/api/groups/:id · audit action group.update

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"maxLength": 100,
"type": "string"
},
"needsReview": {
"const": false,
"type": "boolean"
}
}
}

group_member_add

Add an existing administrator to a group as an owner or a plain member. This grants them everything the group owns, in one call. Owner-only.

Route POST /admin/api/groups/:id/members · audit action group.member.add

Input (body)
{
"type": "object",
"properties": {
"userId": {
"minLength": 1,
"type": "string"
},
"role": {
"anyOf": [
{
"const": "owner",
"type": "string"
},
{
"const": "member",
"type": "string"
}
]
}
},
"required": [
"userId",
"role"
]
}

group_member_update

Promote a member to owner or demote an owner to member. The last owner can be neither demoted nor removed. Owner-only.

Route PATCH /admin/api/groups/:id/members/:userId · audit action group.member.update

Input (body)
{
"type": "object",
"properties": {
"role": {
"anyOf": [
{
"const": "owner",
"type": "string"
},
{
"const": "member",
"type": "string"
}
]
}
},
"required": [
"role"
]
}

group_invite

Invite somebody into a group by email, as an owner or a plain member. Creates an administrator account for them when they accept, if the address has none. Owner-only.

Route POST /admin/api/groups/:id/invitations · audit action invitation.create

Input (body)
{
"type": "object",
"properties": {
"email": {
"format": "email",
"maxLength": 320,
"type": "string"
},
"role": {
"anyOf": [
{
"const": "owner",
"type": "string"
},
{
"const": "member",
"type": "string"
}
]
}
},
"required": [
"email",
"role"
]
}

group_invitation_revoke

Withdraw a pending invitation before it is accepted. Owner-only.

Route DELETE /admin/api/groups/:id/invitations/:inviteId · audit action invitation.revoke

bucket_create

Create a user bucket. A bucket cannot be created unreachable: at creation it has no providers, so password login cannot be switched off. `totpRequired` makes a password sign-in also require a one-time code from an authenticator app; it governs password sign-in only and never gates a federated one.

Route POST /admin/api/buckets · audit action bucket.create

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"type": "string"
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"passwordLogin": {
"type": "boolean"
},
"registrationOpen": {
"type": "boolean"
},
"emailVerificationRequired": {
"type": "boolean"
},
"verificationMethod": {
"anyOf": [
{
"const": "link",
"type": "string"
},
{
"const": "code",
"type": "string"
}
]
},
"totpRequired": {
"type": "boolean"
}
},
"required": [
"name"
]
}

bucket_update

Change a bucket's name, roles, managers, or its registration, verification and second-factor settings. Editing the bucket entity needs manager access to the bucket itself, not merely to a project it backs. `totpRequired` governs password sign-in only — it is accepted but inert while `passwordLogin` is off, and it never gates a federated sign-in, so it is not a way to secure a bucket that signs in through an upstream provider.

Route PATCH /admin/api/buckets/:id · audit action bucket.update

Input (body)
{
"type": "object",
"properties": {
"name": {
"minLength": 1,
"type": "string"
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"passwordLogin": {
"type": "boolean"
},
"registrationOpen": {
"type": "boolean"
},
"emailVerificationRequired": {
"type": "boolean"
},
"verificationMethod": {
"anyOf": [
{
"const": "link",
"type": "string"
},
{
"const": "code",
"type": "string"
}
]
},
"totpRequired": {
"type": "boolean"
}
}
}

bucket_user_create

Create an end-user account in a bucket.

Route POST /admin/api/buckets/:id/users · audit action enduser.create

Input (body)
{
"type": "object",
"properties": {
"email": {
"minLength": 3,
"type": "string"
},
"password": {
"minLength": 8,
"type": "string"
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"email",
"password"
]
}

bucket_user_update

Change an end-user's email, roles, active state, or claims. Deactivating is a sign-in decision, not a deletion.

Route PATCH /admin/api/buckets/:id/users/:uid · audit action enduser.update

Input (body)
{
"type": "object",
"properties": {
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"active": {
"type": "boolean"
}
}
}

bucket_user_totp_clear

Clear an end-user's authenticator enrolment. Their existing authenticator stops working at once and their sessions end; they set a new one up at their next sign-in. Use when someone has lost the device holding their codes. Their password, grants and tokens are untouched.

Route DELETE /admin/api/buckets/:id/users/:uid/totp · audit action enduser.totp.clear

federation_provider_create

Configure an upstream identity provider on a bucket. Available whether or not federation is switched on, so a provider can be prepared first.

Route POST /admin/api/buckets/:id/federation · audit action federation.provider.create

Input (body)
{
"type": "object",
"properties": {
"id": {
"minLength": 1,
"maxLength": 32,
"type": "string"
},
"displayName": {
"minLength": 1,
"type": "string"
},
"issuer": {
"minLength": 1,
"type": "string"
},
"clientId": {
"minLength": 1,
"type": "string"
},
"clientSecret": {
"minLength": 1,
"type": "string"
},
"enabled": {
"type": "boolean"
},
"scopes": {
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"emailTrusted": {
"type": "boolean"
},
"provisioning": {
"anyOf": [
{
"const": "jit",
"type": "string"
},
{
"const": "existing_only",
"type": "string"
}
]
},
"allowedEmailDomains": {
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"emailClaim": {
"minLength": 1,
"type": "string"
}
},
"required": [
"id",
"displayName",
"issuer",
"clientId",
"clientSecret"
]
}

federation_provider_update

Change an upstream provider's configuration, or enable/disable it.

Route PATCH /admin/api/buckets/:id/federation/:providerId · audit action federation.provider.update

Input (body)
{
"type": "object",
"properties": {
"displayName": {
"minLength": 1,
"type": "string"
},
"issuer": {
"minLength": 1,
"type": "string"
},
"clientId": {
"minLength": 1,
"type": "string"
},
"clientSecret": {
"minLength": 1,
"type": "string"
},
"enabled": {
"type": "boolean"
},
"scopes": {
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"emailTrusted": {
"type": "boolean"
},
"provisioning": {
"anyOf": [
{
"const": "jit",
"type": "string"
},
{
"const": "existing_only",
"type": "string"
}
]
},
"allowedEmailDomains": {
"type": "array",
"items": {
"minLength": 1,
"type": "string"
}
},
"emailClaim": {
"minLength": 1,
"type": "string"
}
}
}

High-consequence writes (two-call confirmation)

client_secret_rotate

Issue a new secret for a confidential client and invalidate the old one. The new secret is returned exactly once. Anything still using the old secret stops working immediately.

Route POST /admin/api/projects/:id/clients/:clientId/secret · audit action client.secret.rotate

client_delete

Permanently delete an OAuth client and revoke what was issued to it. Irreversible.

Route DELETE /admin/api/projects/:id/clients/:clientId · audit action client.delete

admin_deactivate

Deactivate an administrator: the account is kept but can no longer sign in. Refused for the last active super-administrator.

Route DELETE /admin/api/admins/:id · audit action admin.deactivate

group_member_remove

Remove an administrator from a group. They lose access to every project, bucket and end-user the group owns, on their very next request. The last owner cannot be removed. Owner-only.

Route DELETE /admin/api/groups/:id/members/:userId · audit action group.member.remove

bucket_user_password_reset

Replace an end-user's password. The previous one is unrecoverable and the account holder is not asked.

Route POST /admin/api/buckets/:id/users/:uid/password · audit action enduser.password.reset

Input (body)
{
"type": "object",
"properties": {
"password": {
"minLength": 8,
"type": "string"
}
},
"required": [
"password"
]
}

bucket_user_delete

Permanently delete an end-user account and everything issued to it. Irreversible.

Route DELETE /admin/api/buckets/:id/users/:uid · audit action enduser.delete

federation_provider_delete

Remove an upstream identity provider from a bucket. Deliberately available even with federation switched off, so a deployment can delete a provider it no longer trusts. Users who signed in only through it lose that route in.

Route DELETE /admin/api/buckets/:id/federation/:providerId · audit action federation.provider.delete

federation_identity_delete

Sever one end-user's link to one upstream provider. The account survives; only the link is removed.

Route DELETE /admin/api/buckets/:id/users/:uid/identities/:providerId · audit action federation.identity.delete

jwks_generate

Generate a new RSA signing key. Takes effect for signing only after a restart; the key is published immediately so verifiers can pick it up first.

Route POST /admin/api/jwks · audit action jwks.generate

Input (body)
{
"type": "object",
"properties": {
"alg": {
"anyOf": [
{
"const": "RS256",
"type": "string"
},
{
"const": "RS384",
"type": "string"
},
{
"const": "RS512",
"type": "string"
}
]
}
}
}

jwks_delete

Delete a signing key. Refused if it would leave no signing key. Tokens already signed with it stop verifying once it is gone.

Route DELETE /admin/api/jwks/:kid · audit action jwks.delete

settings_update

Change server settings. The merged configuration is validated first, so a combination the server would refuse at boot is refused here instead of taking the instance down on restart. Most changes apply only after a restart, and the result says so.

Route PUT /admin/api/settings · audit action settings.update

Input (body)
{
"type": "object",
"patternProperties": {
"^(.*)$": {}
}
}

smtp_settings_update

Change the outbound mail settings. The password is write-only: it can be set but never read back.

Route PUT /admin/api/settings/smtp · audit action smtp.settings.update

Input (body)
{
"type": "object",
"properties": {
"host": {
"type": "string"
},
"port": {
"multipleOf": 1,
"type": "number"
},
"secure": {
"type": "boolean"
},
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"fromName": {
"type": "string"
},
"fromEmail": {
"type": "string"
}
},
"required": [
"host",
"port",
"secure",
"username",
"password",
"fromName",
"fromEmail"
]
}

sentry_settings_update

Change where recorded faults are reported. The ingestion credential is write-only: it can be set but never read back, and sending the mask keeps the stored one. Enabling this requires the error store, because the outbound event is built from the internal record. Applies after a restart.

Route PUT /admin/api/settings/sentry · audit action sentry.settings.update

Input (body)
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"dsn": {
"type": "string"
}
},
"required": [
"enabled",
"dsn"
]
}