MCP tools
Every tool the OS's MCP server offers, generated from the tool catalog.
Generated from the MCP tool catalog (apps/mcp/src/tool-catalog.ts). Do not edit by hand.
os.list_runs
List the enterprise's runs, newest first, one page at a time. Each run carries its status, task (id, name, slug), the member it runs as, its input, and when it was created, started and finished. The response is { data, total, page, limit, pages }.
| Argument | Type | Required | Description |
|---|---|---|---|
status |
string, one of pending, queued, running, waiting_on_gate, waiting_on_run, paused_spend, succeeded, failed, cancelled, skipped_overlap, blocked |
no | Only runs in this status. |
taskId |
string | no | Only runs of this task. |
live |
boolean | no | true for only runs still in progress: not finished, and not blocked or paused on spend. |
page |
integer, at least 1 | no | The page to read, from 1. Defaults to 1. |
limit |
integer, 1 to 200 | no | Runs per page, up to 200. Defaults to 25. |
- Method:
GET - Path:
/v1/runs - Scope:
runs:read
os.get_run
One run's status, why it stopped (blockedReason, when it is blocked), task id and input, and its last eight events. Not found for another enterprise's run.
| Argument | Type | Required | Description |
|---|---|---|---|
runId |
string | yes | The run id. |
- Method:
GET - Path:
/v1/runs/:runId/os-tool - Scope:
runs:read
os.list_blockers
What is stopping work right now, as the Blockers page shows it: failed runs not yet cleared (one page, with failedTotal counting them all), stalled, blocked and spend-paused runs, stopped pipelines, missing model tiers, exhausted LLM capacity, task definition problems, and teams with no lead, no metric or an overdue retro. Read-only: nothing is retried or cleared. Waiting gates are not here; use os.list_open_gates.
| Argument | Type | Required | Description |
|---|---|---|---|
failedPage |
integer, at least 1 | no | The page of failed runs to read, from 1. Defaults to 1. A page past the last reads the last. |
pageSize |
integer, 1 to 100 | no | Failed runs per page, up to 100. Defaults to 100 in a run, and to 20 over the API. |
- Method:
GET - Path:
/v1/blockers - Scope:
blockers:read
os.list_open_gates
Every gate waiting on a decision, oldest first: the run and task it belongs to, the tool call it holds (toolName, payload), its summary when the run wrote one, who owns the decision, when it times out, and whether the run can be sent back with changes requested. Read-only: deciding a gate is not a tool here.
No arguments.
- Method:
GET - Path:
/v1/gates?status=waiting - Scope:
gates:read
os.kpi_board
The enterprise's KPI board, as HQ shows it: every company KPI the owner has signed off and each team's key KPI with its light (red off target, amber at risk, green on target), its trend (up, down, flat), when it was last read, the cadence it is read on, and whether that reading is overdue. A KPI nobody has read yet has no light (rag is null): it is never read and overdue, not green. A KPI still waiting for sign-off is not on the board. A team that has set no key KPI is named with none rather than left out. The response is { enterprise, teams }. Read-only: recording a reading is not a tool here.
No arguments.
- Method:
GET - Path:
/v1/enterprise/kpis - Scope:
enterprise:read
kpi.record_reading
Record one reading of a KPI by hand: the value, when it was taken, and who or what took it. Every reading is kept — correcting a wrong one means recording a new reading, never editing or deleting the old one — so a KPI history shows how it got to where it is. The light and the trend are read off the readings, so recording one is what moves them. A KPI nobody has signed off takes no reading: it is refused with 409 kpi_not_signed_off.
| Argument | Type | Required | Description |
|---|---|---|---|
kpiId |
string | yes | The KPI the reading belongs to. |
value |
number | yes | The number read, in the KPI's own unit. |
takenAt |
string | yes | When the reading was taken, as an ISO 8601 timestamp, e.g. 2026-01-08T00:00:00Z. |
recordedBy |
string | yes | Who or what took the reading: a member id, or the agent or tool that read it. |
- Method:
POST - Path:
/v1/kpis/:kpiId/readings - Scope:
kpis:write
kpi.list_readings
One KPI's readings, newest first: the value, when it was taken and who or what took it. This is the whole history behind the KPI's light and its trend, including any reading a later one corrected.
| Argument | Type | Required | Description |
|---|---|---|---|
kpiId |
string | yes | The KPI whose readings to list. |
- Method:
GET - Path:
/v1/kpis/:kpiId/readings - Scope:
kpis:read
os.get_enterprise_kpis
The company's KPI targets as set: unit, target and direction, AMBER band, cadence and source. A KPI waiting for a target has targetValue null.
No arguments.
- Method:
GET - Path:
/v1/enterprise/kpi-targets - Scope:
enterprise:read
os.set_enterprise_kpis
Replace the company's complete KPI target list. A target needs its unit, direction, cadence and source; a no-target KPI is accepted. Uses the same validation as the portal.
| Argument | Type | Required | Description |
|---|---|---|---|
kpis |
array of objects | yes | The complete KPI target list. Every item is validated by the API. |
- Method:
PATCH - Path:
/v1/enterprise/kpi-targets - Scope:
enterprise:write
os.get_team_kpis
A team's own KPI targets as set, including which one is its key KPI. This is the target list, not the role and task KPI tree.
| Argument | Type | Required | Description |
|---|---|---|---|
teamId |
string | yes | The team whose KPI targets are read. |
- Method:
GET - Path:
/v1/teams/:teamId/kpi-targets - Scope:
teams:read
os.set_team_kpis
Replace a team's complete KPI target list. Two key KPIs are refused; a list with none marked is stored with no key KPI. Uses the same validation as the portal.
| Argument | Type | Required | Description |
|---|---|---|---|
teamId |
string | yes | The team whose KPI targets are replaced. |
kpis |
array of objects | yes | The complete KPI target list. Every item is validated by the API. |
- Method:
PATCH - Path:
/v1/teams/:teamId/kpi-targets - Scope:
teams:write
role.list_kpis
A role's KPIs, oldest first: each one's target, direction, AMBER band, cadence, source, the team KPI it serves (servesName names it; served is false for one that serves none), whether a person has signed it off, its light and trend (null until it is signed off) and its readings. Not found for a role in another enterprise.
| Argument | Type | Required | Description |
|---|---|---|---|
roleId |
string | yes | The role whose KPIs to list. |
- Method:
GET - Path:
/v1/roles/:roleId/kpis - Scope:
roles:read
role.define_kpi
Propose a KPI on a role, with the same fields as a KPI on any other layer. It waits for a person to sign it off, and until then draws no light and takes no reading. A KPI may serve only a KPI of the role’s own team (400 role_kpi_serves_other_team otherwise); leave servesKpiId out for one that serves none. The response is the role's KPIs after the change.
| Argument | Type | Required | Description |
|---|---|---|---|
roleId |
string | yes | The role the KPI belongs to. |
name |
string | yes | What is measured, up to 200 characters. |
targetValue |
number | no | The target, in the KPI’s own unit. Set it with targetDirection, or leave both out for no target. |
targetDirection |
string, one of at_least, at_most |
no | at_least when higher is better, at_most when lower is better. |
amberBand |
number, at least 0 | no | How far past the target still reads AMBER rather than RED. |
onTargetWorseningRule |
boolean | no | true to read AMBER when on target but worse than the reading before. |
cadenceMinutes |
integer, at least 1 | no | How often it is read, in minutes; a reading older than this is overdue. |
servesKpiId |
string | no | The KPI of the role’s own team this one serves. |
sourceKind |
string, one of task, person |
no | Where readings come from: task (a task records them) or person (entered by hand). |
sourceRef |
string | no | The task id, or the person’s human-user id, sourceKind names. |
- Method:
POST - Path:
/v1/roles/:roleId/kpis - Scope:
roles:write
role.edit_kpi
Change a role KPI's fields; the ones left out keep their value. A KPI a person has signed off is changed only by a person, so this is refused with 403 kpi_signed_off_person_only for it. The response is the role's KPIs after the change.
| Argument | Type | Required | Description |
|---|---|---|---|
roleId |
string | yes | The role the KPI belongs to. |
name |
string | no | What is measured, up to 200 characters. |
targetValue |
number | no | The target, in the KPI’s own unit. Set it with targetDirection, or leave both out for no target. |
targetDirection |
string, one of at_least, at_most |
no | at_least when higher is better, at_most when lower is better. |
amberBand |
number, at least 0 | no | How far past the target still reads AMBER rather than RED. |
onTargetWorseningRule |
boolean | no | true to read AMBER when on target but worse than the reading before. |
cadenceMinutes |
integer, at least 1 | no | How often it is read, in minutes; a reading older than this is overdue. |
servesKpiId |
string | no | The KPI of the role’s own team this one serves. |
sourceKind |
string, one of task, person |
no | Where readings come from: task (a task records them) or person (entered by hand). |
sourceRef |
string | no | The task id, or the person’s human-user id, sourceKind names. |
kpiId |
string | yes | The KPI to change. |
- Method:
PATCH - Path:
/v1/roles/:roleId/kpis/:kpiId - Scope:
roles:write
os.list_built_in_tools
List every built-in tool a run can call: its name, a one-line summary, and its effect (read or write). A task may declare a built-in tool (os., workspace., memory., web.) only from this list: saving a task that names any other is refused, as a tool that does not exist (tool_unknown) or one only the CEO chat offers (tool_not_run_callable). A row with gate is a tool a task may hold only if it also declares a CEO gate on the tool gate names: saving it without that gate is refused (gate_required_for_tool). Vendor tools are not here: os.list_tool_bindings lists what the enterprise has bound. Takes no arguments.
No arguments.
- Method:
GET - Path:
/v1/tools/built-in?callable=run - Scope:
tools:read
os.chat_list
List chat threads, most recently active first: each thread’s id, its state (idle, replying or closed), and its last message. In a run these are the threads of the member doing the run, and memberId is ignored. Over the API they are every thread of the enterprise, or only one member’s when you pass memberId. No message bodies beyond the last: read a thread with os.chat_read. A conversation opened for one job, such as designing a task, is never listed.
| Argument | Type | Required | Description |
|---|---|---|---|
memberId |
string | no | Over the API: only threads with this member. A run always lists its own member’s. |
- Method:
GET - Path:
/v1/chats - Scope:
chats:read
os.chat_read
Read one chat thread: its messages, oldest first, each with who wrote it. Pass id from os.chat_list, and optionally limit to read only the newest messages (up to 200). In a run you get what was said (people’s messages and the member’s), the newest 50 unless you pass limit, and reading does not mark the thread read. Over the API you get every row, tool calls included, and reading marks the thread read, as opening it in the portal does.
| Argument | Type | Required | Description |
|---|---|---|---|
id |
string | yes | A thread id from os.chat_list |
limit |
integer, 1 to 200 | no | Only the newest messages, up to 200. In a run it defaults to 50; over the API, to all of them. |
- Method:
GET - Path:
/v1/chats/:id - Scope:
chats:read
os.chat_write
Write one message in a chat thread, as yourself. Pass content: plain text, shown as written with line breaks kept and no formatting. In a run you write as the member doing the run, for the enterprise’s people to read: it shows as unread until someone opens the thread, nobody replies to the run, and the run carries on. Leave id out to write in the member’s open thread (one is opened if there is none), or pass id from os.chat_list. At most 4000 characters in a run. For a question you need answered, use os.ask_ceo. Over the API, id is required, you write as the person or token calling, and the member replies: the response is the thread with that reply in it. Sends no mail and opens no gate. A repeat writes the message again.
| Argument | Type | Required | Description |
|---|---|---|---|
id |
string | yes | The thread, from os.chat_list. A run may leave it out to write in its member’s open thread. Required over the API. |
content |
string | yes | The message, as plain text |
- Method:
POST - Path:
/v1/chats/:id/messages - Scope:
chats:write
os.chat_open
Open a new, empty chat thread with a member, and get its id to write in with os.chat_write. Pass memberId. Nothing is said and nothing is spent until a message is written. A run cannot call it: a run’s os.chat_write opens its member’s thread when there is none.
| Argument | Type | Required | Description |
|---|---|---|---|
memberId |
string | yes | The member to talk to |
- Method:
POST - Path:
/v1/chats - Scope:
chats:write
os.list_enterprise_kpis
List every KPI of the enterprise, whatever layer owns it and whether or not it has been signed off, ordered by name then id. Each row carries its id (the kpiId the readings tools take), name, owner (layer and id), source (kind and ref), target (value, direction, AMBER band, on-target-worsening rule), cadence, current light, whether it is overdue, when it was signed off (null while it waits for sign-off, when it takes no reading), and its latest reading. The light is null when the KPI has no target or no reading yet. No arguments. Never another enterprise's KPIs.
No arguments.
- Method:
GET - Path:
/v1/kpis - Scope:
kpis:read