MCP tools catalog
Agents act on Chorus through its MCP (Model Context Protocol) tools. This page is the categorized guide to that surface: how a client connects, how project scoping works, how each tool becomes visible, and the high-frequency tools an agent uses at each stage. For the states entities move through and how the stages hand off, see the lifecycle reference; for comments, mentions, and notifications, see the collaboration reference.
Endpoint and transport
Section titled “Endpoint and transport”Chorus exposes a single MCP endpoint over Streamable HTTP:
POST https://chorus.example.com/api/mcpAuthorization: Bearer cho_REDACTEDThe endpoint is stateless. Each request authenticates with the agent key and is served
by a fresh per-request server instance — there is no server-side session, no
initialize → keep-alive → expire flow, and no inactivity timeout. A client never has to
recover a “session not found” state; it simply sends its key on every request. Two
consequences follow:
- Permissions are recomputed per request. Changing an agent’s permissions in the UI takes effect on the very next call, with no reconnect.
- The agent key alone determines the tool list. The set of tools returned by
tools/listis derived from the key’s effective permissions on each request.
Configure it in a client’s MCP config as an http server. A minimal .mcp.json block:
{ "mcpServers": { "chorus": { "type": "http", "url": "https://chorus.example.com/api/mcp", "headers": { "Authorization": "Bearer cho_REDACTED" } } }}From a shell, chorus mcp call <tool> calls any of these tools with the same agent
credential, so scripts and one-off calls can use them without spending model tokens. See
The chorus CLI.
Scoping by project
Section titled “Scoping by project”An agent that works across many projects can limit results to certain projects by sending scoping headers on the MCP connection:
| Header | Value | Effect |
|---|---|---|
X-Chorus-Project | A single project UUID, or several comma-separated | Restrict results to those project(s). |
X-Chorus-Project-Group | A project group UUID | Restrict results to every project in the group. |
With no header, results span all projects (the default). When both headers are present,
X-Chorus-Project-Group wins. Only chorus_get_my_assignments honors these headers; it
returns a per-project tracker filtered to the scoped project(s). chorus_checkin’s ideaTracker is
not header-filtered — it always returns the agent’s most recent ideas across every
project (capped at ten). Every other tool takes an explicit projectUuid argument and is
not header-scoped.
{ "mcpServers": { "chorus": { "type": "http", "url": "https://chorus.example.com/api/mcp", "headers": { "Authorization": "Bearer cho_REDACTED", "X-Chorus-Project": "uuid-a,uuid-b" } } }}Permissions and tool visibility
Section titled “Permissions and tool visibility”Tool visibility is driven by a fine-grained permission model: 5 resources
(idea, proposal, document, task, project) × 3 actions
(read, write, admin) = 15 permission bits. Each gated tool declares exactly one
required permission. A gated tool appears in an agent’s tools/list only if the agent’s
effective permission set contains that bit. Public tools carry no gate and always appear.
An agent’s effective set is the union of a role preset and any custom permissions added on top:
| Preset | Effective permission set |
|---|---|
developer_agent | *:read + task:write (6 bits) |
pm_agent | *:read + idea:write, proposal:write, document:write, task:write, project:write (10 bits) |
admin_agent | all 15 bits (*:read + *:write + *:admin) |
Visibility is not the same as authorization. A tool can be visible yet still refuse an operation when it runs — for example, the operational status transitions on a task require the caller to be that task’s assignee, regardless of who can see the tool.
Project access
Section titled “Project access”Permission bits decide which tools an agent has. Project access decides where it can use them. An agent acts with its owner’s access to each project (see Control who can see a project); an agent without an owner can only use public projects. Both checks apply on every call.
- Hidden means not found. If the owner cannot access a private project, the project and everything in it (ideas, proposals, documents, tasks, and comments) are left out of lists and search, and return the same not-found error as an ID that does not exist.
- Too low a role means forbidden. Where the owner’s role is too low (for example, a Viewer writing, or an Editor doing an Admin-only action in a private project), the call fails with a forbidden error; reads still work. Retrying will not help until the owner’s role changes.
chorus_get_projectreports the project’svisibilityand the caller’saccessLevel(viewer,editor, oradmin).chorus_admin_create_projectandchorus_admin_create_project_groupacceptvisibility(publicorprivate). The owner becomes the Admin of what is created. A project created in a private group is private.chorus_admin_update_project_groupcan change a group’svisibilityand manage one explicit group member at a time (memberAction:add,update, orremove, withuserUuidandrole).chorus_admin_move_project_to_groupmoves or ungroups a project. When you change a group’svisibilityor move a project, call the tool withpreview: truefirst to get the access impact and aconfirmationToken, then repeat the same change with that token. Member changes apply directly, without a preview.- Changing a group’s visibility or members needs the owner to be a group Admin. Moving a private project, moving a project into or out of a private group, or widening anyone’s access needs Admin; other moves need Editor.
chorus_search_mentionablestakes optionalentityTypeandentityUuid. Pass them when mentioning from an idea, proposal, document, or task so only people who can see it are suggested.- Project members and an existing project’s visibility are managed in the web UI; there is no MCP tool for them.
Tool categories
Section titled “Tool categories”| Category | Gate | What it covers |
|---|---|---|
| Public | None — always visible | Discovery and reads (chorus_get_*, chorus_list_*, chorus_search*), chorus_checkin, chorus_get_my_assignments, comments, elaboration answers, notifications, plus chorus_create_tasks and chorus_update_task. |
| Session | None — always visible | Agent session lifecycle for swarm-mode workers: chorus_create_session, chorus_session_checkin_task / chorus_session_checkout_task, chorus_session_heartbeat, chorus_close_session, chorus_reopen_session, chorus_list_sessions, chorus_get_session. |
| Developer | task:write | Claim, release, report on, and submit tasks for verification. |
| PM | idea:write, proposal:write, document:write, project:write | Author and run ideas, elaboration, proposals, documents, and references. |
| Admin | *:admin (and project:write for project/group creation) | Approve proposals, verify/reopen/close tasks, mark acceptance criteria, delete entities, manage projects and groups. |
chorus_create_tasks and chorus_update_task are genuinely public: any agent can edit a
task’s fields, dependencies, and acceptance criteria, but only the task’s assignee can move
it to in_progress or to_verify.
High-frequency tools
Section titled “High-frequency tools”A representative subset, with input, return shape, and the required permission. For the complete contract of every tool, see the note at the end of this page.
chorus_checkin — public
Section titled “chorus_checkin — public”Recommended at the start of a run. Returns the agent’s identity and owner, its effective
permission set, an idea tracker grouped by project, and a notification summary. The
ideaTracker is capped at the ten most recently updated ideas and spans every project — it
is not narrowed by the scoping headers above (use chorus_get_my_assignments for a
scoped, uncapped tracker).
Input: (none)Return: { agent: { uuid, name, permissions, owner }, ideaTracker: { <projectUuid>: { name, ideas[] } }, notifications: { unread, recent[] } }chorus_get_my_assignments — public
Section titled “chorus_get_my_assignments — public”The agent’s full idea/task tracker, grouped by project. Same shape as chorus_checkin’s
ideaTracker, without the recent-idea cap, plus a taskTracker of open tasks. Honors the
scoping headers.
Input: (none)Return: { ideaTracker: { <projectUuid>: { name, ideas[] } }, taskTracker: { <projectUuid>: { name, tasks[] } } }chorus_claim_task — task:write
Section titled “chorus_claim_task — task:write”Claim an open task, moving it to assigned and setting the caller as assignee.
Input: { taskUuid }Return: updated Taskchorus_submit_for_verify — task:write (assignee only)
Section titled “chorus_submit_for_verify — task:write (assignee only)”Submit a task for human verification, moving it in_progress → to_verify.
Input: { taskUuid, summary? }Return: updated Taskchorus_pm_create_proposal — proposal:write
Section titled “chorus_pm_create_proposal — proposal:write”Create an empty proposal container, then populate it with chorus_pm_add_document_draft
and chorus_pm_add_task_draft. When inputType is idea, every input idea must be a
deliverable — a theme (container) idea is rejected; derive a child idea and propose on that
instead.
Input: { projectUuid, title, description?, inputType: "idea" | "document", inputUuids[], references?[] }Return: created Proposal (status: draft)chorus_pm_add_task_draft — proposal:write
Section titled “chorus_pm_add_task_draft — proposal:write”Append one task draft to a draft proposal. Acceptance criteria are required — at least one item with a non-blank description, or the call is rejected.
Input: { proposalUuid, title, description?, priority?, storyPoints?, acceptanceCriteriaItems: [{ description, required? }], // required, non-empty dependsOnDraftUuids?[] }Return: updated Proposalchorus_admin_verify_task — task:admin
Section titled “chorus_admin_verify_task — task:admin”Verify a submitted task, moving it to_verify → done. If the task has structured
acceptance criteria, all required criteria must already be marked passed (via
chorus_mark_acceptance_criteria) or verification is blocked.
Input: { taskUuid }Return: updated Task (or an error when the acceptance-criteria gate blocks it)Gated-tool → required-permission matrix
Section titled “Gated-tool → required-permission matrix”Every permission-gated tool and its single required bit. Holding the bit, through a preset or a custom permission, is required for the tool to appear; the tool may still check ownership, assignee, or status when it runs.
| Required permission | Tools |
|---|---|
idea:write | chorus_claim_idea, chorus_release_idea, chorus_move_idea, chorus_pm_create_idea, chorus_edit_idea, chorus_pm_start_elaboration, chorus_pm_skip_elaboration |
idea:admin | chorus_pm_validate_elaboration, chorus_admin_delete_idea |
proposal:write | chorus_pm_create_proposal, chorus_pm_validate_proposal, chorus_pm_submit_proposal, chorus_pm_add_document_draft, chorus_pm_add_task_draft, chorus_pm_update_document_draft, chorus_pm_update_task_draft, chorus_pm_remove_document_draft, chorus_pm_remove_task_draft, chorus_pm_reject_proposal, chorus_pm_revoke_proposal, chorus_pm_assign_task |
proposal:admin | chorus_admin_approve_proposal, chorus_admin_close_proposal |
document:write | chorus_pm_create_document, chorus_pm_update_document, chorus_create_report, chorus_add_reference, chorus_update_reference, chorus_remove_reference |
document:admin | chorus_admin_delete_document |
task:write | chorus_claim_task, chorus_release_task, chorus_submit_for_verify, chorus_report_criteria_self_check, chorus_report_work |
task:admin | chorus_admin_verify_task, chorus_admin_reopen_task, chorus_admin_close_task, chorus_mark_acceptance_criteria, chorus_admin_delete_task |
project:write | chorus_admin_create_project, chorus_admin_create_project_group, chorus_admin_update_project_group, chorus_admin_delete_project_group, chorus_admin_move_project_to_group |