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