MCP Tool Surface
Agents talk to the SupaCloud platform through an MCP registry defined in
server/src/services/mcp/. Every tool belongs to exactly one tier; the tier
determines which allowlist entry unlocks it and which rate-limit bucket it
consumes.
Tiers and allowlist entries
Section titled “Tiers and allowlist entries”| Tier | Allowlist wildcard | Also granted by |
|---|---|---|
| Baseline | unconditional (always on) | supacloud.*, supacloud.full |
| Read | supacloud.read.* |
supacloud.full, exact name |
| Ops | supacloud.ops.* |
supacloud.full, exact name |
script.run carve-out |
supacloud.script.run |
supacloud.full, exact name |
| Scaffold | supacloud.scaffold.* |
supacloud.full, exact name |
| Deploy | supacloud.deploy.* |
supacloud.full, exact name |
supacloud.ops.* does not include script.run. Scripts can bind to
workspace resources and secrets at runtime, so the carve-out requires a
deliberate additional grant.
A profile-less task (workflow or auto-developer task with no
agent_profile_id) resolves to the read-only default surface
(supacloud.read.*). Ops and deploy tiers remain fail-closed unless an
explicit agent profile grants them (ADR 0033).
Any individual tool may also be granted by its exact name or by
supacloud.<tool-name>.
Baseline tools (N+4, always on)
Section titled “Baseline tools (N+4, always on)”Granted unconditionally to every authenticated agent session.
| Tool | Description |
|---|---|
delegate_subtask |
Delegate bounded work to another agent profile |
get_subtask_result |
Read the result of a delegated child task |
cancel_subtask |
Cancel a delegated child task |
memory.search |
Full-text search over workspace and project memories |
memory.get |
Read one memory by UUID |
memory.list_recent |
List recent workspace and project memories |
memory.propose_review |
Enqueue a pending memory review proposal (no immediate mutation) |
outcome.recent_for_profile |
Read recent outcome telemetry for this task’s agent profile |
Read tier — supacloud.read.*
Section titled “Read tier — supacloud.read.*”All tools are read-only and workspace-scoped from the task session.
Workspace and platform reads
Section titled “Workspace and platform reads”| Tool | Description |
|---|---|
workspace.info |
Active workspace metadata (slug, name, member count, budget remaining, plan tier) |
projects.list |
Projects visible in the workspace |
project.get |
Single project detail |
tasks.list_active |
Running and queued tasks in the workspace |
tasks.get |
Single task detail (cost, duration, last event) |
runners.status |
Runner availability and capacity |
schedules.list |
Active schedules in the workspace |
resources.list |
Configured resources — kind, name, status only; no connection strings or secrets |
apps.list |
Apps with deployment status and public URL |
app.get |
Single app detail |
workflows.list |
Defined workflows |
workflow.get |
Workflow detail including steps (flattened from workflow_nodes + workflow_edges) |
app.migration.list |
Pending and applied migrations for an app |
Run observation
Section titled “Run observation”Read-only run, board, and event tools. Runs are workspace-scoped first, so a run’s detail and events never leak across workspaces.
| Tool | Description |
|---|---|
run.list |
List recent top-level runs of every kind (agent/workflow/script/app), newest first, with optional status/kind/project/task/app narrowing |
run.get |
Read one run by id plus its flattened descendant run tree (workflow node runs and loop iterations) |
run.events |
Read a run’s event log, paginated by sequence number (after_sequence / limit / tail) |
Source reads (W7-3)
Section titled “Source reads (W7-3)”| Tool | Description |
|---|---|
app.files.list |
List app source files |
app.files.get |
Read one app source file (body capped at 64 KiB) |
script.get |
Read a script definition |
script.list |
List scripts in the workspace |
app.builds.list |
List build history for an app |
Issue reads (ADR 0033)
Section titled “Issue reads (ADR 0033)”Resolved from project.issue_tracker ?? project.git_provider — covers all
six sources (GitHub, GitLab, Bitbucket, Forgejo, Linear, Notion).
| Tool | Description |
|---|---|
issue.get |
Read a single issue by ID |
issue.list |
List open issues for the task’s project |
Conversation reads (#596)
Section titled “Conversation reads (#596)”Provider-agnostic support conversations (Chatwoot / Intercom). Addressed by an
explicit workspace resource name (the support channel) — there is no
project-level binding. Also granted by supacloud.conversation.*.
| Tool | Description |
|---|---|
conversation.get |
Read a single conversation by ID from a workspace resource |
conversation.list |
List open conversations for a workspace resource |
Ops tier — supacloud.ops.*
Section titled “Ops tier — supacloud.ops.*”Write tools; 10 calls per task. supacloud.ops.* does not include script.run.
| Tool | Description |
|---|---|
workflow.trigger |
Start a workflow run |
schedule.create |
Create a new schedule |
schedule.update |
Update an existing schedule |
schedule.pause |
Pause a schedule |
schedule.resume |
Resume a paused schedule |
repo_sync.trigger |
Trigger a repo sync push or pull |
issue.comment |
Post a comment on an issue (any of the six providers) |
issue.transition |
Transition an issue to a new state |
pr.create |
Create a pull request (git forge only) |
conversation.reply |
Post a customer-visible reply (or private note) into a conversation (#596; idempotency-keyed) |
conversation.assign |
Assign a conversation to an agent (#596) |
conversation.resolve |
Resolve (close) a conversation (#596; idempotency-keyed) |
conversation.handoff |
Hand a conversation off to another team (#596) |
script.run carve-out — supacloud.script.run
Section titled “script.run carve-out — supacloud.script.run”| Tool | Description |
|---|---|
script.run |
Execute a workspace script |
Counts against the ops rate-limit bucket (10/task). An optional
script_allowlist array on the agent profile further restricts which scripts
(by slug) may be called.
Scaffold tier — supacloud.scaffold.*
Section titled “Scaffold tier — supacloud.scaffold.*”Proposal and task-spawn tools. Proposals create a pending proposals row for
human review without mutating durable state; task-spawn tools launch a
follow-up agent task addressed at an App or Script scaffold.
| Tool | Description |
|---|---|
scaffold.script.propose |
Propose a new or updated script |
scaffold.app.propose |
Propose a new app |
scaffold.app.file_upsert.propose |
Propose an app file upsert |
scaffold.workflow.propose |
Propose a new workflow |
task.create_for_app_scaffold |
Spawn a follow-up agent task for an app scaffold |
task.create_for_script_scaffold |
Spawn a follow-up agent task for a script scaffold |
Deploy tier — supacloud.deploy.*
Section titled “Deploy tier — supacloud.deploy.*”Deployment lifecycle tools; 5 calls per task.
supacloud.ops.* does not include deploy tools.
In addition to the allowlist grant, the resolved task actor must hold workspace owner or admin permission — the same check the Deployment service applies for HTTP requests.
app.deploy and app.migration.apply require the two-step confirmation
protocol (see below).
| Tool | Description |
|---|---|
app.deploy |
Deploy an app to its public route |
app.undeploy |
Remove an app from its public route |
app.pause |
Set an app to maintenance mode |
app.resume |
Resume a paused app |
app.migration.apply |
Apply pending app migrations |
Rate limits
Section titled “Rate limits”Per-task caps
Section titled “Per-task caps”| Tier | Default | Config env var |
|---|---|---|
| Baseline + Read | 50 / task | AGENT_MCP_TOOL_RATE_LIMIT |
Ops (including script.run) |
10 / task | — |
| Scaffold | 10 / task | — |
| Deploy | 5 / task | — |
Workspace and profile caps
Section titled “Workspace and profile caps”Per-task limits are checked first; only if a call is within its per-task budget
is the workspace-daily / profile-hourly cap reservation attempted (the per-task
slot is refunded if the workspace/profile reservation fails). Counters are
derived from audit_events so they survive restarts.
| Scope | Tier | Default | Config env var |
|---|---|---|---|
| Workspace / day | Ops | 100 calls | AGENT_MCP_WORKSPACE_OPS_DAILY_LIMIT |
| Workspace / day | Deploy | 20 calls | AGENT_MCP_WORKSPACE_DEPLOY_DAILY_LIMIT |
| Workspace / day | Scaffold proposals | 10 calls | AGENT_MCP_WORKSPACE_PROPOSAL_DAILY_LIMIT |
| Workspace / day | Scaffold task-spawns | 3 calls | AGENT_MCP_WORKSPACE_TASK_SPAWN_DAILY_LIMIT |
| Profile / hour | Ops | 30 calls | AGENT_MCP_PROFILE_OPS_HOURLY_LIMIT |
| Profile / hour | Deploy | 10 calls | AGENT_MCP_PROFILE_DEPLOY_HOURLY_LIMIT |
| Profile / hour | Scaffold proposals | 10 calls | AGENT_MCP_PROFILE_PROPOSAL_HOURLY_LIMIT |
| Profile / hour | Scaffold task-spawns | 3 calls | AGENT_MCP_PROFILE_TASK_SPAWN_HOURLY_LIMIT |
Rate-limit exhaustion returns an HTTP 403 (AppError::Forbidden) error. The
per-task message names the tool (Rate limit exceeded for tool '<tool>'); the
workspace-daily and profile-hourly messages name the tier and report a
<used>/<limit> ratio (Workspace daily limit reached for this MCP tool tier (<used>/<limit>) / Profile hourly limit reached for this MCP tool tier (<used>/<limit>)).
Deploy confirmation protocol
Section titled “Deploy confirmation protocol”app.deploy and app.migration.apply use a stateless two-step confirmation
to prevent accidental deploys and stale retries.
Step 1 — request a summary. Call the tool without confirmation_token.
The server returns confirmation_required: true, a changes_summary, and a
confirmation_token (HMAC-SHA256, signed with SUPACLOUD_MCP_CONFIRMATION_SECRET,
carrying the input hash and a 5-minute expiry).
Step 2 — confirm. Call the tool again with the same inputs plus the
confirmation_token. The server verifies the signature, expiry, and that the
input hash matches the current arguments. An idempotency_key is required
when confirmation_token is present.
The HMAC key is a server-side secret set via SUPACLOUD_MCP_CONFIRMATION_SECRET
(minimum 32 bytes). When unset, confirmed deploy and migration-apply calls
fail closed. The key is never derived from task, user, workspace, or profile
credentials.
Idempotency keys for confirmed calls are stored in mcp_idempotency_keys
(scoped to task_id + tool_name + key) and cleaned up 24 hours after the
parent task reaches a terminal state.
Security properties
Section titled “Security properties”- No secret exposure.
resources.listreturns kind, name, and status only — never connection strings, passwords, or tokens. - No credential access. Agents cannot read or modify workspace credentials through MCP.
- Workspace isolation. All queries are scoped to the task’s workspace.
- Audit trail. Every tool call emits an
audit_eventsrow with task correlation ID, tool name, status, and error class.
Related
Section titled “Related”- ADR 0028 — Extended MCP agent surface
- ADR 0033 — Always-on baseline and read-only default surface
- Management API — M2M operator surface (distinct from agent MCP)