MCP tools
This is the agent surface — your agent's whole toolkit. The human surface is REST API. Onboarding story: onboard an agent member.
Blarass PM exposes a FastMCP streamable-HTTP server.
Connecting an MCP client
- Endpoint:
https://pm.blarass.com/mcp(also served viahttps://pm.blarass.com/v1/mcp— same service, two faces) - Transport: streamable HTTP (
initializehandshake, then session confirmed viamcp-session-idheader) - Auth: every request carries
Authorization: Bearer <member key>— resolves to a member (human/agent/app) the same way REST does
{
"mcpServers": {
"blarass-pm": {
"url": "https://pm.blarass.com/mcp",
"headers": { "Authorization": "Bearer <your-blarass-key>" }
}
}
}On connect the client sends the MCP initialize handshake. After that you can call any of the 21 tools below; the caller's roles and visibility apply to every result.
whoami is the fastest connection check:
{ "tool": "whoami", "arguments": {} }Worked session
One real sequence (placeholders for ids) — agent sets up a project end to end:
{ "tool": "whoami", "arguments": {} }
{ "tool": "create_project", "arguments": { "name": "Website Relaunch" } }
{ "tool": "create_milestone", "arguments": { "project_id": "…", "name": "Launch", "target_date": "2026-10-01" } }
{ "tool": "create_module", "arguments": { "milestone_id": "…", "name": "Design" } }
{ "tool": "create_task", "arguments": { "project_id": "…", "milestone_id": "…", "module_id": "…", "title": "Pick hero design", "status": "todo" } }
{ "tool": "create_task", "arguments": { "project_id": "…", "title": "Deploy staging", "status": "todo" } }
{ "tool": "add_task_blocker", "arguments": { "task_id": "…deploy…", "blocker_task_id": "…hero…" } }
{ "tool": "update_task", "arguments": { "task_id": "…hero…", "status": "done" } }
{ "tool": "get_project_progress", "arguments": { "project_id": "…" } }Result: 1-of-2 tasks done → module at 100% → milestone at 50% → project progress matches — all derived, nothing manually scored. This is exactly the flow in Guides · Progress reports.
Projects
| Tool | Args | Does |
|---|---|---|
list_projects | — | Projects with derived progress_pct |
create_project | name string, description? string, status? enum(active, paused, done, archived) | Create project |
update_project | project_id uuid, name? / description? / status? | Update (archive = no hard delete) |
whoami | — | Show the calling member, workspace, and roles |
Milestones + roadmap
| Tool | Args | Does |
|---|---|---|
list_milestones | project_id? uuid | Milestones, with progress |
create_milestone | project_id uuid, name string, target_date? string | Create under a project |
update_milestone | milestone_id uuid, name? / target_date? / status? enum(planned, active, hit, missed) / position? int | Update fields |
list_roadmap | project_id? uuid, from? YYYY-MM-DD, to? YYYY-MM-DD | Milestones by target date |
Drift note (intentional, mirrors the service as-built): MCP milestone status vocabulary is planned | active | hit | missed, while REST milestone status is planned | in_progress | done. The MCP update_milestone.execute writes whatever status it's given, so both surfaces are truthful — the enumerations just differ. See content gaps — this is a service-level follow-up, not a docs one.
Modules
| Tool | Args | Does |
|---|---|---|
create_module | milestone_id uuid, name string, position? int | Create under a milestone |
Tasks
| Tool | Args | Does |
|---|---|---|
list_my_tasks | project_id? uuid, status? stage key | Tasks assigned to the calling member |
list_tasks | project_id? uuid, module_id? uuid, milestone_id? uuid, status? enum, assignee_principal_id? uuid, order? enum(due) | Filtered workspace task list (assigned-only narrowing applies) |
get_task | task_id uuid | Task detail + blockers + derived blocked |
create_task | project_id uuid, title string, module_id? uuid, milestone_id? uuid, description? string, status? stage key, assignee_principal_id? uuid, estimate_days? number, metadata? record, due_date? YYYY-MM-DD | Create task (v1.6: status is a per-type stage key — invalid → readable error listing the project's valid stages) |
update_task | task_id uuid, status? stage key, title? string, description? string, estimate_days? number, module_id? uuid, milestone_id? uuid, metadata? record, due_date? string/null | Update any subset of updatable fields (v1.6: stage validated per type — same contract as REST) |
assign_task | task_id uuid, assignee_principal_id uuid | Assign to any workspace principal |
add_task_blocker | task_id uuid, blocker_task_id uuid | Add blocker edge (same project only; 409 cycle) |
remove_task_blocker | task_id uuid, blocker_task_id uuid | Remove edge |
list_task_blockers | task_id uuid | Blocker list |
add_task_comment | task_id uuid, body string | Append comment (author = calling member) |
list_task_comments | task_id uuid | List comments |
Progress
| Tool | Args | Does |
|---|---|---|
get_project_progress | project_id? uuid | Derived module→milestone→project roll-up |
Semantics + errors
All tools share one behavior: the caller's authorization model applies identically — workspace ladder (owner/admin/member) plus project ladder (viewer/commenter/editor) evaluated server-side before SQL runs, so a tool call either returns the rows you're entitled to or a readable error.
Three error families:
forbidden: you do not have access to … rows in this workspace— RLS denial (row-level visibility)conflict: that value already exists— unique violation (duplicate member name, etc.)invalid reference: the referenced record does not exist (or is in another workspace)— FK mismatch
v1.6 stage vocabulary (type-driven lifecycle): a task's status is a stage key owned by the project's type, not a global enum. Workspace default ladder: backlog | todo | in_progress | done (done flagged). A project created on a custom type carries its own ladder — read it from the project detail's inline type.task_stages, then use those keys in create_task/update_task. Unknown stage → readable error listing the project's valid keys (invalid task stage "x" — valid stages: …). Progress roll-up counts tasks whose current stage has done:true — done-flag based, not name-based, so custom ladders feed the same get_project_progress math.
Passing an argument the tool doesn't declare is rejected before touching the DB:
unknown argument(s): xyz — valid: task_id, status, title, ...Related: Quickstart Path B · Guides · Agent onboarding