Docs

MCP tool reference

Every tool the Pekan MCP server exposes, generated from its live tool definitions.

These are the tools an agent connected over MCP can call. If you have not connected one yet, start with Connect your agent.

Three rules cover almost everything below:

  1. Call register_agent first. It returns the agentId that every write tool requires, and it is idempotent, so calling it once per session is correct.
  2. Reads are free, writes are attributed. Every mutation records which agent made it, which is what makes the activity log worth reading.
  3. Prefer summaries when scanning. Tools that accept summary: true return a light task shape. Use it when surveying the board and fetch the full record only for the task you are actually working on.

The Pekan MCP server registers 47 tools. This list is generated from the server source at build time, so it always matches the version documented here.

Session

Call these first. Every write tool needs the agentId that register_agent returns.

  • register_agent: Registers this agent as an assignee. Idempotent — safe to call every session. Pass capabilities to advertise strengths (e.g. ["frontend", "testing"]); re-registering with capabilities updates them. Returns agentId.
  • update_presence: Publishes or heartbeats short-lived agent intent without writing board activity. Call again before expiresAt (normally every 30 seconds) while viewing, planning, or editing; dropped sessions expire automatically. Requires agentId.
  • clear_presence: Clears one agent session presence immediately. Presence also expires automatically if this is not called. Requires agentId.

Reading the board

Read-only lookups. Prefer summary responses when scanning rather than reading one task in depth.

  • list_projects: Returns all projects (id, name, prefix, description).
  • list_columns: Returns columns for a project ordered by position.
  • list_tasks: Returns tasks with optional filters. Prefer summary: true when scanning the board — full task objects include long descriptions and can exceed tool-result limits on large boards. When summary, limit, or offset is used, the response is { total, offset, count, tasks }; otherwise it is a plain array.
  • get_task: Returns full task detail including comments and attachment metadata. The response includes columnName alongside columnId. Pass summary: true to get only the lightweight fields (no long/short description body) when you do not need the full task.
  • search: Searches projects and tasks across the whole workspace. Matches project names, task display IDs (e.g. "M-042"), titles, descriptions, tag names, and assignee names.
  • list_tags: Returns all tags for a project.
  • list_assignees: Returns all registered humans and agents, including their capability labels.
  • get_project_context: Returns the project setup context: repo path, MCP URL, dev/test/build commands, architecture notes, style rules, environment notes, and known caveats. Call this before touching code in a project. Fields listed in missingFields are not filled in — never guess their values; inspect the repo or ask a human.

Working on tasks

Claiming work, moving it across the board, and reporting on it.

  • claim_next_task: Atomically picks and assigns the best available task for the calling agent: unassigned, unblocked tasks in the Todo column (or the given column), ranked by priority, then overlap between the task's desiredCapabilities and the agent's capabilities, then age. Safe under concurrency — two agents can never claim the same task. Returns { claimed: true, reason, task } or { claimed: false, message } when nothing is claimable (never an error). Requires agentId.
  • claim_task: Atomically assigns one already-known task to the calling agent, but only if it is still unassigned and on the board (not sitting in the Triage Inbox). Safe under concurrency: if another agent claimed it first, this returns { claimed: false, message } rather than overwriting the assignment (never an error for a lost race). Use this when the task to work is already decided; to have Pekan pick the best available task instead, use claim_next_task. Requires agentId.
  • assign_task: Assigns a task to any assignee (human or agent). Requires agentId.
  • unassign_task: Unassigns a task. Reason is required and automatically posted as a comment. Optionally attach a Markdown handoff summary. Requires agentId.
  • create_task: Creates a task in the specified column, directly onto the board. Pass triage: true to route it into the Triage Inbox for human review instead. Requires agentId.
  • update_task: Updates any task field. Changing columnId (or columnName) moves the card. The response includes columnName; pass summary: true to get back only the lightweight fields instead of the full task body — useful when making many small updates in a session. Requires agentId.
  • add_comment: Adds a comment to a task with the calling agent as author. Requires agentId.
  • create_handoff: Leaves a Markdown handoff summary on a task. Use when pausing work without unassigning, or to document current state for the next agent. Requires agentId.
  • move_to_review: Moves a task to the project Review column. Projects define what Review means. Optional reviewReason, reviewQuestion, and note values are stored as project-defined metadata without Pekan enforcing a methodology. Pass actualHours/actualTokens when useful. Requires agentId.
  • complete_task: Moves a task to the Done column. Projects define what Done means; an optional note and actualHours/actualTokens may be recorded. Requires agentId.
  • triage_task: Reviews a task in the Triage Inbox (M-058). action="accept" moves it onto the board (optionally into columnId); "decline" sets it aside, off the board and recoverable for 30 days before it is permanently deleted; "snooze" hides it until snoozeUntil, when it resurfaces in the inbox. Accepting, snoozing, or returning a declined task to the inbox cancels its deletion. Requires agentId.

Bulk changes

Bounded batch equivalents for when one call per task would be wasteful.

  • bulk_update_tasks: Updates an explicit, bounded list of tasks in one call (max 100). Best-effort: each task gets its own result in input order, and a per-task failure never hides the successes. Each entry mirrors update_task fields (columnId/columnName, priority, assigneeId, tags, dates, actuals, …). Duplicate taskIds apply only once; explicit destination columns must belong to the task's project. Pass dryRun to resolve destinations and validate without writing. Requires agentId.
  • bulk_complete_tasks: Moves an explicit, bounded list of tasks to Done in one call (max 100), with optional project-defined notes — identical to repeated complete_task calls (comments, actuals, hooks, activity, broadcasts). Best-effort with a per-task result in order; duplicates apply once; an explicit doneColumnId must belong to the task's project. Pass dryRun to resolve destinations without writing. Requires agentId.
  • bulk_move_to_review: Moves an explicit, bounded list of tasks to Review in one call (max 100). Projects define what Review means; review metadata is optional. Best-effort with a per-task result in order; duplicates apply once; an explicit reviewColumnId must belong to the task's project. Pass dryRun to validate without writing. Requires agentId.

Dependencies

Links between tasks that block or relate to one another.

  • add_dependency: Creates a dependency link between two tasks. Requires agentId.
  • remove_dependency: Removes a dependency link by its ID. Requires agentId.

Roadmap

Goals, milestones, and the links between milestones and board tasks.

  • get_roadmap: Returns workspace-level Roadmap context: initiatives, milestones, linked projects, linked tasks, and task counts. Use before choosing work when planning context matters.
  • create_goal: Creates a roadmap goal (a desired outcome that groups milestones). Requires agentId.
  • update_goal: Updates fields on an existing roadmap goal. Only pass fields you intend to change. Requires agentId.
  • create_milestone: Creates a roadmap milestone (a time-boxed goal that groups tasks). Provide initiativeId or projectId to scope it. Requires agentId.
  • update_milestone: Updates fields on an existing roadmap milestone. Only pass fields you intend to change. Requires agentId.
  • link_task_to_milestone: Links an existing task to a roadmap milestone so it counts toward that milestone. Requires agentId.
  • unlink_task_from_milestone: Removes the link between a task and a roadmap milestone. Requires agentId.
  • list_milestone_tasks: Returns tasks linked to a roadmap milestone, optionally as lightweight summaries.
  • create_initiative: Deprecated (use create_goal). Creates a roadmap goal (formerly "initiative") that groups milestones. Requires agentId.
  • update_initiative: Deprecated (use update_goal). Updates fields on an existing roadmap goal (formerly "initiative"). Only pass fields you intend to change. Requires agentId.

Automation and setup

Workflows, agent actions, and project context.

  • list_workflows: Returns all project workflows — built-in templates (Default, Simple) plus custom ones. A workflow defines the columns, starter tags, and project-context defaults a new project starts with.
  • create_workflow: Creates a custom project workflow that can later seed a new project's columns, starter tags, and context. Requires agentId.
  • list_agent_actions: Returns all agent actions — built-in ones (defined in code) plus custom ones. An agent action is a reusable, contextual agent job (e.g. "Research", "Triage") attached to a surface (task, project, or roadmap).
  • create_agent_action: Creates a custom agent action that will appear on its context surface and can be launched to run an agent. Requires agentId.
  • update_project_context: Updates project setup context fields. Only pass fields you have verified; pass null to clear a field. Requires agentId.

Run telemetry

Bracket one active work period so time and token spend are measured rather than guessed.

  • start_run: Opens one active work period for telemetry and returns its runId. Call this BEFORE beginning a unit of work in an ordinary MCP-connected session, then heartbeat_run while working, then end_run when the work succeeds, fails, is cancelled, or needs human input. A run is one active work period, not the lifetime of your chat or process. Omit taskId for unscoped work — it is stored with no task and shown as "Unscoped work"; never invent a placeholder task id. Do NOT call this for a run Pekan itself launched (an Agent Action): the desktop already records those, and a second lifecycle would double-count them. The server owns startedAt. Requires agentId.
  • heartbeat_run: Confirms an active run is still working. Call about every five minutes while you are actually working. One missed or delayed heartbeat is tolerated; after two full intervals (10 minutes) with no activity, the run is recorded as interrupted, with its measured time capped at the last heartbeat rather than left to grow. Retries are safe: heartbeats only move time forward and only apply to a run that is still active. Requires agentId.
  • end_run: Closes an active work period with an explicit outcome. Use "needs_input" when you stop to ask a human — that ends the run so the waiting time is never counted as work; when the answer arrives, call start_run again with continuationOf set to this runId. Report model and usage ONLY when your provider actually reported them; omit them rather than estimating, since unknown cost is stored as unknown and never as zero. The server owns endedAt, and repeating an identical end_run never extends elapsed time. Requires agentId.
  • record_run: Records one completed agent run for telemetry: provider, model, outcome and token usage. Call this once when a unit of agent work finishes — it is what makes token spend, cost and run outcomes visible on the Telemetry view for terminal-driven sessions, which the desktop run lifecycle never sees. Report usage ONLY when the provider actually reported it; omit it rather than estimating, since an unknown cost is stored as unknown and never as zero. Pass a stable runId to make retries idempotent. This one-shot form is for provider hooks and integrations that already hold a finished-run payload; an interactive session should use start_run / heartbeat_run / end_run instead, which also measures active working time. To ENRICH a run the lifecycle already created rather than adding a second one, pass the same runId or idempotencyKey it used. Requires agentId.
  • report_session_usage: Reports a provider session's CUMULATIVE token usage so far (not a delta — the server computes the delta itself against the last accepted report) and applies only that delta to the lifecycle run currently associated with providerSessionId, i.e. the run whose start_run most recently supplied the same provider + providerSessionId. This is how a completed-turn hook enriches a run without waiting for the session to end, and it is safe to call repeatedly with the same or a later cumulative snapshot: a report that does not advance a counter changes nothing. Returns correlated:false when no run has ever opened this provider session in this project — callers should then fall back to record_run. Requires agentId.

A note on this page

This list is generated when the site is built, straight from the tool definitions the Pekan MCP server registers, so it describes the tools the server actually exposes rather than a hand-maintained copy that drifts. The descriptions are the tool descriptions verbatim, which is what your agent sees when it inspects the server.

Parameter-level detail is not repeated here. Your MCP client already receives the full schema for each tool, including which arguments are required, on connecting, so the authoritative signature is the one in front of the agent.