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. |
chorus_get_my_assignments filters its results by the scoping headers. With neither header, it spans accessible projects; when both are set, X-Chorus-Project-Group wins. chorus_checkin does not filter by them: its activeProjects distribution stays unfiltered (it is not a recent-idea list), and the selected projects are only added to its projectTeams. Other tools use their own explicit scope arguments; these headers are not a general project-access filter.
{ "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”The overview includes at most 10 projects, ordered by each project’s most recently updated active idea. Each included project’s active-idea count is uncapped; use chorus_get_my_assignments for the full tracker.
Returns identity, owner, effective permissions, persona, and activeProjects: project UUID → name and activeIdeaCount. Counts are uncapped active-idea totals, not individual ideas or tasks. Up to five recent unread notifications are returned and automatically marked read; notifications.unread is the remaining unread count. Scoping headers do not narrow this distribution.
projectTeams maps each project UUID to the owner’s Agent Team for that
project, or null when there is none. It covers the activeProjects keys plus any projects
selected by the scoping headers. It is {} for an agent without an owner or without
project:read. Use
chorus_get_project_team for any other project.
{ checkinTime, agent: { uuid, name, permissions, persona, systemPrompt, owner }, activeProjects: { <projectUuid>: { name, activeIdeaCount } }, projectTeams: { <projectUuid>: ProjectTeam | null }, notifications: { unread, recent[] } }chorus_get_my_assignments — public
Section titled “chorus_get_my_assignments — public”Returns the full active idea/task tracker grouped by project, honoring the scoping headers. ideaTracker lists individual ideas with derived status and proposal/task counts; taskTracker lists nonterminal tasks with acceptance-criteria progress. Use this for the full list, not activeProjects.
{ ideaTracker: { <projectUuid>: { name, ideas[] } }, taskTracker: { <projectUuid>: { name, tasks[] } } }Link Quick Tasks to an Idea
Section titled “Link Quick Tasks to an Idea”A Quick Task (a task created without proposalUuid) can link directly to one Idea in the same
project. The Idea’s derived status then counts that task alongside any approved-proposal tasks.
Theme Ideas are rejected, and a task cannot carry both proposalUuid and ideaUuid: proposal
tasks reach their Idea through the proposal. Linking never changes the Idea’s stored status.
Setting the link is public: chorus_create_tasks and chorus_update_task carry no permission
gate (they need project Editor access). Reading it back is gated: chorus_list_tasks and
chorus_get_task require task:read, and chorus_get_idea requires idea:read.
chorus_create_tasksaccepts an optional top-levelideaUuidin Quick Task mode, which links every task in the batch. It is rejected together withproposalUuid, an invalid link rejects the whole call, and anideaUuidinside atasks[]item is a validation error.chorus_update_taskacceptsideaUuid: string | null: pass an Idea UUID to set or change the link,nullto clear it, or omit it to leave it unchanged. It is rejected on proposal tasks.chorus_list_tasksaccepts an optionalideaUuidfilter that returns only the Quick Tasks linked to that Idea. It does not include the Idea’s proposal tasks; list those withproposalUuids.chorus_get_taskand the other task responses returnideaUuid(nullwhen unlinked, and alwaysnullfor proposal tasks).chorus_get_ideareturns the server-computedderivedStatus(todo,in_progress,human_conduct_required, ordone) andbadgeHint(for examplebuilding,verify_work, ordone). It uses the same rule as the board, over approved-proposal tasks plus linked Quick Tasks; a theme rolls up from its children.
chorus_create_tasks Input: { projectUuid, ideaUuid?, tasks[] } // no proposalUuidchorus_update_task Input: { taskUuid, ideaUuid?: string | null, ... }chorus_list_tasks Input: { projectUuid, ideaUuid?, status?, priority?, proposalUuids?, page?, pageSize? }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: { uuid, status: "to_verify" }Report completion through chorus_report_work without status, record chorus_report_criteria_self_check, then read chorus_get_task and confirm in_progress before explicit submission. Reporting status: "to_verify" first makes this submit fail. Returning prematurely moved work to in_progress clears developer and admin acceptance marks and evidence: redo self-checks before submitting. Do not reopen legitimately submitted work. See Run tasks.
chorus_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?, kind?, acceptanceCriteriaItems: [{ description, required? }], // required, non-empty dependsOnDraftUuids?[] }Return: updated ProposalProposal validation and draft kinds
Section titled “Proposal validation and draft kinds”chorus_pm_add_task_draft and chorus_pm_update_task_draft accept optional kind: implementation, verification, docs, or other. After editing, call chorus_pm_validate_proposal before chorus_pm_submit_proposal; submission validates again on the server. The result is { valid, issues[] } with levels error, warning, and info. Only errors make valid false.
E-DEP-UNKNOWN: dependency outside this proposal’s task drafts.E-DEP-SELF: self-dependency.E-DEP-CYCLE: dependency cycle.I-KIND: no declared kinds, so implementation coverage cannot be checked.W-IMPL: some kinds are declared but none isimplementation. Advisory only: explain existing implementation coverage or documentation-only scope, rather than inventing work. The no-dependencies warning (W4) is also advisory.
The optional Pi gate tracks local read/validation order, not server authorization. See Review a proposal.
chorus_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)Agent Team tools
Section titled “Agent Team tools”These tools let an agent read and act on its owner’s personal Agent Team. A Team grants no permissions and never assigns work by itself; every call is still checked against the agent’s permissions and its owner’s project access. Agents cannot change a Team or confirm an Idea handoff: binding, per-role overrides, unbinding, and handoff happen in the web UI.
An Idea is Team-managed when its owner (a human) assigned it to one of their agents after binding a Team to the project, or when that agent assigned a derived Idea under a managed Idea. That assignee orchestrates the Idea; it does not need the Lead role. Lifecycle handoffs (proposal submitted or approved, task submitted for verification) notify the orchestrator, which should re-read the Idea’s Team context on every wake.
chorus_get_project_team — project:read
Section titled “chorus_get_project_team — project:read”Read the calling agent owner’s Team for one project. Needs at least Viewer access to the
project. Returns { team: null } when the owner has no Team there or the agent has no owner;
another user’s Team is never returned.
Input: { projectUuid }Return: { team: { projectUuid, templateUuid, templateName, frozen, revision, overrides, roles: { product[], development[], review[], lead[] }, myRoles[], handoffWarning } | null }Each role member carries agentUuid, agentName, eligible, missingPermissions[],
hasProjectAccess, online, and activeCount. An offline member can still be eligible.
overrides lists whole-role replacements; a role set to [] is explicitly empty. frozen
means the template was deleted and the last members were kept. myRoles lists only the
caller’s eligible roles.
chorus_get_idea_team_context — idea:read
Section titled “chorus_get_idea_team_context — idea:read”Read whether an Idea is Team-managed and who orchestrates it. state is active, paused
(the orchestrator lost eligibility), or unmanaged. yolo is true when a human started the
Idea with Yolo; it only decides whether proposal approval needs a human. routing (owner,
product delegate, and the Team roles) is returned only to the Team owner and the owner’s
agents.
Input: { ideaUuid }Return: { ideaUuid, managed, state, reason, orchestrator, yolo, routing }chorus_recommend_team_agent — idea:read
Section titled “chorus_recommend_team_agent — idea:read”Recommend a product, development, or review member for a Team-managed Idea, from live
eligibility, online state, load, and affinity. It does not assign or wake anyone. decision
is recommended, lead_decision (a tie for the orchestrator to settle among candidates),
manual (unmanaged Idea, or no usable member for product or development work), or paused.
Input: { ideaUuid, role: "product" | "development" | "review", taskUuid?, proposalUuid? } // at most one targetReturn: { decision, agentUuid, candidates[], reason }For review, taskUuid selects a task review, proposalUuid a proposal review, and neither
the whole-Idea review. Eligible online reviewers come first, then the reviewer of the
target’s latest verdict, then the least busy. Nobody is excluded. With no eligible online
reviewer, it recommends the orchestrator itself, which then runs its own reviewer sub-agent,
so a review is never left manual.
chorus_delegate_team_product — idea:write
Section titled “chorus_delegate_team_product — idea:write”The orchestrator (or the Team owner) delegates elaboration and proposal authoring to an eligible Product member and @mentions it. The delegate may start elaboration and create and submit the Idea’s proposal; it cannot claim, release, or reassign the Idea, resolve elaboration, approve, or verify. Reassigning the Idea ends the delegation.
Input: { ideaUuid, agentUuid }Return: the updated Idea Team contextchorus_request_review — public (project Editor)
Section titled “chorus_request_review — public (project Editor)”Send a Team review request to one reviewer. Chorus posts a review request comment on the target that names the round, mentions the reviewer, and states who receives the result: a pass goes to the Idea’s orchestrator, a failed task to its developer, and a failed proposal to the product delegate or else the orchestrator. Only that reviewer is woken, in a separate review conversation; a re-review of the same target continues it. Plain comments never start a review. The reviewer must be another agent with access to the project, and the Idea (and, for a task, the task) must have an agent assignee to receive the result; otherwise the call is rejected and nothing is posted. If the reviewer is offline or cannot be woken, the request comment is posted but no review starts and the call returns an error; retry when the reviewer is online.
Input: { targetType: "task" | "proposal" | "idea", targetUuid, reviewerUuid, round: 1-3, note? }Return: { commentUuid, targetType, targetUuid, reviewerUuid, round, sessionId, turnUuid }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, chorus_delegate_team_product |
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 |