Tools

manage__* tools

The account-management tools on the MCP surface — API keys, agents, connected accounts, environments, session, remote MCP servers, and approval waits — with arguments and who may call each.

Every caller sees the manage__* tools in tools/list, except manage__approval_wait, which is listed only where Smart Approvals is available to the organization, and the three manage__connectors_* tools, which are listed only where connect requests are available to it. They are the control plane of an organization: keys, agents, connected accounts and their shares, environments, connect requests, the active session, remote MCP registrations, and approval waits. Two rules apply to all of them:

  • Never wallet-gated. A billing hold or spend cap does not stop key management — an organization on hold must still be able to revoke or rotate.
  • Most need a signed-in member. Called with any API key, the session-gated tools return HTTP 200 with isError: true and code jwt_session_required. The manage__remote_* family is the exception and is permission-gated instead; the three manage__connectors_* tools are open to agents; and manage__approval_wait answers only for the caller's own approval requests. See Authentication.

Amounts are always credits (1,000 credits = $1), and money fields on the wire are decimal strings such as "1234.567".

Permissions

An organization power is a permission, named by a slug. Your role holds them: an admin holds every one, a member none, and a custom role exactly the ones attached to it in your identity provider. The tools below name the slug they check.

SlugWhat it lets you do
members:manageInvite people, change a member's role, remove a member.
org:settingsRename the organization; change its analytics setting.
billing:manageSubscribe, top up, manage payment methods and invoices.
connections:orgOrganization integrations, org OAuth clients, remote MCP servers, org-wide accounts someone else connected, and approval requests on an org-wide account.
keys:orgSee and manage every API key in the organization.
agents:manageManage agents you do not own.
agents:transferGive an agent to another owner.
approvals:policyWrite the organization's approval policy and settings.
activity:orgSee every member's activity and approval cards.
memory:reviewMerge or reject proposals on any memory.

A key can carry permissions too, and never more than the token that minted it — its ceiling. A key holds its list only while the member it acts as still holds each slug, so a demoted admin's key loses the power on its next request. A key minted through an MCP sign-in carries none, and an agent's key never carries one.

API keys

Session-gated. You see your own keys and the keys of agents you own; with keys:org you see every key in the organization. can_manage on each row says whether the caller may revoke, rotate, or update it.

ToolArgumentsEffect
manage__keys_createname, spend_limit_credits? (whole credits, > 0), expires_at? (ISO 8601), permissions? (slugs; omit for none), environment? (one of your environments, by name or env_… id)Mints an sk-cs- key that acts as the caller. Without permissions the key makes tool calls under its connection grants only. A slug you do not hold answers ceiling_exceeded and names it; through an MCP sign-in every slug does, so mint such a key from a signed-in session: the dashboard's key dialog, cs keys create --permission <slug>, or POST /api-keys. An unknown slug answers unknown_permission. With environment, the key reaches only that environment's accounts, for its whole life (rotation keeps it). In a session that runs inside an environment, the key is always bound to it, and naming another answers environment_mismatch. The plaintext is returned once. Unknown fields are rejected rather than ignored.
manage__keys_list—Active keys visible to the caller, each with created_by_user_id, can_manage, permissions, spend_limit_credits, period_used_credits, usage_period (YYYY-MM), and lifetime used_credits.
manage__keys_revokeidPermanently revokes a key. Keys outside the caller's scope answer "API key not found".
manage__keys_rotateidReplaces the secret; name, permissions, cap, and the current month's usage are preserved, so rotation cannot reset a budget. Rotating a key that carries permissions counts as minting them: a slug you could not hand on answers ceiling_exceeded, and the old secret stays live.
manage__keys_updateid, name?, spend_limit_credits? (null removes the cap), expires_at? (null removes the expiry)Omit a field to leave it unchanged. Raising the cap above the month's usage unblocks the key; lowering it below blocks it on the next request.

Agents

Session-gated. Any member may create an agent and becomes its owner; the owner or a holder of agents:manage manages it; giving it to another owner takes agents:transfer. An agent never holds a permission, and can never call these tools to widen its own reach. See Authentication for what an agent principal is.

ToolArgumentsEffect
manage__agents_createnameCreates an agent principal; the caller becomes its owner.
manage__agents_list—Every agent in the organization: id (agent_…), name, owner_user_id, status (active, suspended, retired), active_key_count, can_manage.
manage__agents_updateid, name?, status? (active, suspended), owner_user_id?Rename, suspend or resume (reversible kill switch — every key of a suspended agent stops resolving), or transfer ownership (agents:transfer; the new owner must be a member).
manage__agents_retireidTerminal: revokes every active key and sets retired. The record stays for attribution. Use agents_update with suspended for a reversible stop.
manage__agents_key_createagent_id, name, spend_limit_credits?, expires_at?, environment? (one of the agent's environments)Mints an sk-csa- key that authenticates as the agent. The owner or a holder of agents:manage only. Not available inside an environment (environment_active). The plaintext is returned once. The key carries no permissions; naming any answers agent_key_permissions.

Connected accounts

Session-gated. The alias is the value connector tools take as their account argument when more than one account is connected — see Connectors. connector takes the value accounts_list reports.

ToolArgumentsEffect
manage__accounts_list—Every connected account visible to the caller, including accounts other members shared with you: connector (the connector id; a custom server your organization added is org__<slug>, the prefix its tools use), alias, identity (email or handle from provider metadata), member_scope (true = a member's private account, false = org-wide), access (owner = yours, org = org-wide, granted = another member's account shared with you). Inside an environment, only its accounts, each with environment_tools (the tools allowed on it there; null = every tool).
manage__accounts_renameconnector, current_alias, new_aliasRenames one of your own accounts; the alias must stay unique for that connector in your scope. Shared accounts are not renamable here.
manage__accounts_removeconnector, aliasDisconnects the account: deletes the credential and revokes the upstream token where the provider supports it. A private account by its member; a shared one by whoever connected it or a holder of connections:org.
manage__accounts_shareconnector, alias, grantee (a member user_…, an agent agent_…, or the org org_…), tools? (tool names as tools/list publishes them, such as github__list_issues; omit or null for every tool)Lets the grantee call the connector's tools under a member's private account; a call outside tools answers tool_not_granted. A share made directly to the grantee outranks one made to the org. The account's owner is never limited, and an org-wide account is already open to everyone in the organization, so its shares limit nothing. Your private account is yours to share; an org-wide one, its creator's or a connections:org holder's. Sharing with the same grantee again replaces its tool list. Remote MCP accounts, and personal accounts of a connector with an organization-level integration (Slack, Linear), cannot be shared.
manage__accounts_unshareconnector, alias, granteeRemoves that one share. The grantee keeps access if the account is org-wide or is still shared with the whole organization. Same authorization as accounts_share.

Environments

Session-gated. An environment is a named subset of your accounts — or of an agent's you manage — each with an optional tool list. A session that uses its mcp_url (https://api.corespeed.io/mcp/env/<name>), or a key bound to it, reaches only those accounts. An environment only narrows: it never adds an account, and an account someone stops sharing with you drops out of it. The three edits are not available from a session that itself runs inside an environment (environment_active): an environment is set by a person, and the model working in one cannot widen it. The same holds for manage__agents_key_create and the manage__remote_add, remote_refresh and remote_remove writes; manage__remote_list lists only the servers the environment holds an account of.

ToolArgumentsEffect
manage__environments_list—Your environments and those of agents you manage (every agent's, with agents:manage): id, name, owner_id, owner_kind (member or agent), mcp_url, entry_count, key_count (active keys bound to it).
manage__environments_createname (1–63 lowercase letters, digits or inner hyphens), owner_id? (an agent you manage), entries?Creates the environment, and fills it when entries is given — both or neither. Each entry is { connection_id, tools? }: an account the owner can use, and the tool names allowed on it, as tools/list publishes them (omit or null for every tool).
manage__environments_updateid, name?, entries?Renames it (its mcp_url follows; bound keys stay bound) and/or replaces every entry. entries: [] empties it.
manage__environments_deleteidDeletes it. Refused with environment_in_use while an active key is bound to it: a key without its environment would reach every account. Revoke those keys first.

Connect requests

Not session-gated: an API key may call these, because their whole audience is agents. They let an agent ask a person to connect an account, without the agent ever seeing a consent screen or a key. Listed only where connect requests are available to the organization; they are rolling out gradually.

ToolArgumentsEffect
manage__connectors_searchquery? (words: a product name or what you need), category? (one kind, such as docs or crm), limit? (1–25, default 10)Finds connectors in the catalog you can use or connect: each with id, name, category, a short description, tools (count), status for you (connected, needs_reauth, not_connected), the accounts you can use, and connect (oauth, api_key) when it can be connected. With neither query nor category, it lists what you can use now. Inside an environment, only its accounts count.
manage__connectors_connectconnector (the id the catalog lists, such as notion), reason? (one plain-text sentence, ≤ 300 characters, shown to the person), another_account?Returns connect_url, a link to the connector's page in the dashboard, and a request_id. Give the link to the person. They open it signed in to CoreSpeed and connect there; the page shows who asked and the reason. The link does nothing on its own and expires after an hour. Asking again for the same connector returns the same open request. With an agent key, the agent's owner completes it and shares the account with the agent on the same page. When you can already use an account of the connector, it answers with those accounts instead, unless another_account is true. Refused inside an environment (environment_active: ask the user to add the account to it instead), for Slack or Linear from an agent key (connector_not_shareable: an agent reaches those through the organization integration), and when five requests are already open (connect_request_limit).
manage__connectors_waitrequest_idWaits until you can use the new account, then returns its alias. Holds up to ten minutes per call (with progress notifications when the client sends a progress token), then answers status: "pending"; call it again with the same id. Reload tools/list afterwards to see the connector's tools. Answers only for requests the caller made.

Session

Session-gated.

ToolArgumentsEffect
manage__whoami—The caller's user id, active organization id, and organization name (orgName, null if unresolved); principal (member or agent), role, permissions (the slugs you hold here), credential (session, mcp_oauth or api_key), ceiling (the most a key you mint may carry — empty for an MCP sign-in), and the environment the session runs in (environment: id, name, entries, connections; null when none). role, permissions and ceiling are null when they cannot be read right now.
manage__switch_org—Revokes this agent's authorization so the next browser sign-in re-prompts organization selection, where the user picks. Not instant: tokens already issued keep working in the current organization until they expire. The agent cannot choose the organization.

Remote MCP servers

Not session-gated: an API key may call these. remote_list is open to any member; the three writes need connections:org and answer admin_required otherwise. A key holds it only when it was minted with it and its member still holds it. A billing hold does not block the writes; a suspended organization is refused before any tool runs. Registered servers surface as org__<slug>__<tool>; the concepts are on Remote MCP servers.

ToolArgumentsEffect
manage__remote_addslug (kebab-case, ≤ 32 chars, unique in the org), url (https, no IP literals or internal hosts; a query string may configure but never carry a credential), auth_mode (oauth, static_bearer, none), display_name?, token? (for static_bearer), client_id? / client_secret? (for oauth when the server offers no dynamic registration), headers? (static upstream headers, values encrypted and never returned; authorization is rejected)Registers the server. For static_bearer and none it also takes the first tools/list snapshot; for oauth it runs RFC 9728 discovery and registers a client, after which members authorize in the dashboard. Calls to remote tools are free but hold-gated. Pass secrets from the environment, never from a conversation.
manage__remote_list—Each registration with url, auth_mode, tool count, and snapshot freshness. Tool metadata is upstream-self-described and unverified.
manage__remote_refreshslugRe-fetches the tools/list snapshot and recomputes schema hashes. One refresh per connector per 60 seconds.
manage__remote_removeslug, expected_status? (dcr_pending), expected_registration_id?Deregisters the connector, then best-effort deletes its dynamically registered upstream OAuth client. To clear a dcr_pending reservation, pass both optional fields from remote_list so a stale request cannot delete a registration that has since activated.

Approvals

Not session-gated: an API key may call it, because the agent whose call is waiting is its caller. Listed only where Smart Approvals is available to the organization; the concepts are on Approvals.

ToolArgumentsEffect
manage__approval_waitapproval_idWaits for the human decision on a call that came back "Approval required", then returns that call's own result, or an error saying it was denied or expired. Answers only for the caller's own approval requests in this organization. A client that times out while the request is still waiting calls it again with the same id to keep waiting. Once an earlier wait has run the approved call, a later wait does not run it again: it answers that the call already ran (or is running), and the result went to the wait that ran it; Activity records the outcome.

Error shapes

A refused manage__* call is a tool result, never an HTTP failure. Most carry their code in structuredContent.error:

HTTP 200, isError
{
  "content": [
    { "type": "text", "text": "Registering, refreshing, or removing remote MCP connectors needs the connections:org permission (an API key holds it only when it was minted with it)." }
  ],
  "structuredContent": { "error": { "code": "admin_required", "permission": "connections:org" } },
  "isError": true
}

The session gate keeps the envelope as JSON in the text, with no structuredContent:

HTTP 200, isError — session gate
{
  "content": [
    {
      "type": "text",
      "text": "{\"error\":{\"type\":\"forbidden\",\"message\":\"This operation requires a human session, not an API key.\",\"code\":\"jwt_session_required\"}}"
    }
  ],
  "isError": true
}

Codes you will meet most: jwt_session_required (an API key on a session-gated tool), admin_required (a remote write without connections:org), ceiling_exceeded (a key asked for a permission its minter cannot hand on), and no_active_org (CoreSpeed could not link a workspace to this sign-in just now; retry). Every code is listed in Errors & status codes.