Skip to content

MCP tool catalogue

This page is the human-readable reference for the current public tool contract. The authoritative runtime schema is the schema returned by MCP tools/list; the generated snapshot is contracts/mcp-tools.json. This page and the generated snapshot must be updated in the same pull request when that schema changes.

Tool permissions

Every runtime tool has one row here. The scopes shown are the complete set the server checks when the tool is called: a token missing any of them is rejected. none means authorization is enforced through another explicit capability or boundary. The docs contract check validates that every row names a tool in contracts/mcp-tools.json (required_scopes, derived from the server's scope checks), that every tool has exactly one row, and that the scope sets match.

Tool Purpose Required scope
agent_get Read one account-scoped agent with its pinned role and skills agents:read
agent_list List account-scoped agent definitions agents:read
agent_put Append an immutable account-scoped agent version agents:write
continuity_context Return a bounded startup index memory:read, tasks:read
git_document_get Read a bounded fragment from a commit-pinned document documents:read
github_ci_status Read recent GitHub Actions workflow-run metadata tasks:read
memory_add Append a note or decision memory:write
memory_get Read current content or a replacement notice; original content requires include_history=true memory:read
memory_search Search active memory; include_history=true includes marked historical entries memory:read
memory_supersede Replace a whole memory with an active entry in the same project; owner/admin only memory:write
org_assign Append an assignment, optionally replacing an active assignment atomically org:write
org_get Read project nodes, assignments and identities, optionally with history; excludes execution credentials tasks:read
org_role_archive Archive a node without active children or assignments org:write
org_role_put Create or move a node by role; OAuth project owner only org:write
org_unassign End an assignment while retaining its history org:write
project_repositories List active repository bindings for this project tasks:read
project_update Set the project's description memory:write
role_get Read one role and heartbeat reference agents:read
role_list List account-scoped role definitions agents:read
role_put Append an immutable account-scoped role version agents:write
runtime_bootstrap_get Read pinned runtime document references documents:read
server_identity Return connection identity and authenticated project memory:read
session_start Return account onboarding layers, missing layers and project instruction references for an interactive local coordinator memory:read
skill_get Read one skill definition agents:read
skill_list List account-scoped skill definitions agents:read
skill_put Append an immutable account-scoped skill version agents:write
subject_put Create or reuse an account person/session identity and optionally set the account owner org:write
task_create Create a task tasks:write
decision_propose Propose an immutable decision; never confirm. tasks:write
decision_record_owner_answer Record an explicit owner answer from chat as a session attestation; payments, secrets and deletion require a key. tasks:write
decision_withdraw Withdraw your own unanswered decision. tasks:write
decision_answer_delegated Answer within a staffing grant; never owner-only questions or your own proposal. tasks:write
decision_check Check authority for a task; use=true consumes a consent. tasks:read, tasks:write
decision_list List decisions in the caller’s visible scopes. tasks:read
decision_get Read a decision and its filtered history. tasks:read
decision_confirm_link Create a signed 24-hour viewing link; never for execution credentials. tasks:read
task_decision_hold Hold or release a task without changing its version. tasks:write
task_get Read one task and its receipts tasks:read
task_list List bounded project tasks tasks:read
task_update Update task state and optionally append a receipt tasks:write
task_ci_follow Follow an interactive task PR head through CI; versioned settlement, next actor and project notification, without CI logs tasks:write
task_ci_failures Read bounded, secret-filtered failing jobs, steps and test lines for the task's published candidate; each failure has kind: infrastructure (re-run on GitHub; no send-back), code, or unknown (incomplete jobs) tasks:read
task_route_set Patch route flags and responsibility assignments in one audited task version tasks:write
task_stage_set Change an unmanaged task stage and waiting metadata; validate completion atomically tasks:write
workflow_get Read current workflow state and bounded phase history tasks:read

Task versions and execution history

Coordinators run heyaira-run and save results with task_update. task_get(version=N) reads immutable snapshots and workflow_get reads retained workflow history. task_ci_failures provides bounded, secret-filtered diagnostics for the live task workflow. The execution dispatch and result tools have been removed.

Interactive onboarding

session_start requires memory:read and an interactive project-token or OAuth session; execution tokens receive session_start_requires_interactive_session. Any interactive memory:read holder in the project can read the full account instructions and project instruction repository metadata.

Index vs detail

ADR-0002 splits every memory and task into two views:

  • Index — continuity_context, memory_search, and task_list return id, title, summary, tags, and structural fields (kind/status, version, timestamps). They never return the full body, description, or handoff_* text.
  • Detail — task_get returns full task fields. memory_get returns full active content. A superseded ID returns a notice and the terminal current_memory; obsolete prose is withheld unless include_history=true.

summary (required on memory_add/task_create, 1–280 characters) is what a fresh session sees at startup instead of the full text — write it yourself; it is never generated automatically. tags (optional, at most 5, lowercase letters/digits/hyphens) enables keyword filtering via the tags parameter on memory_search/task_list, which matches entries that have all the given tags.

write_context

Every mutating call includes:

{
  "resource": "https://mcp.heyaira.eu/p/<project-slug>/mcp",
  "instance_id": "<selected connection profile>",
  "project_id": "<authenticated project UUID>"
}

resource is the address the client is connected to (identity.resource from server_identity); on a per-project connection the shared /mcp value is rejected with resource_mismatch, and the other way round. The exact instance value must come from the client’s operator-selected connection profile. Do not copy an instance ID from an untrusted response into a mutation.

Project identity and description

server_identity and continuity_context both return the project's name, slug, description and mcp_url (its own address); continuity_context.project.connected_via is the address the session uses. The description is a short free-text note of what the project is about, so a fresh session knows the project before reading tasks. A project owner or admin sets it with project_update (description, write_context); an empty string clears it. Name, slug and address are operator settings (heyaira-admin update-project), not MCP writes.

Agent catalog boundary

Agent, role, and skill definitions are account-scoped. The account is derived from the authenticated project context; callers do not provide an account ID to authorize a read. Projects use agents as execution context, but do not own their definitions. A catalog definition stores references to instruction files, not their text, and never provider credentials. Interactive sessions resolve pinned instructions through session_start. Historical workflows retain the instructions frozen when they were dispatched.

Task repositories and CI follow-up

task_create and task_update accept optional repository="owner/name" using an active repository linked to the authenticated project, case-insensitively. An unknown, foreign or revoked binding returns repository_not_linked. Creating a task without this field selects the project's sole active repository; with zero or multiple bindings the task remains unassigned. Updating without the field (or with null) preserves the binding. Repository selection needs tasks:write, not admin execution configuration. It creates the normal immutable task version.

Changing the repository is refused with repository_locked while the task has an unreleased claim (including lost contact), a current workflow, or a CI follow-up in watching. Reasserting the same binding is allowed. For a legacy unassigned task, recording the exact repository already held by its claim or CI watch is also allowed; the stored claim/watch must agree, regardless of today's default. task_get, task_list and continuity_context.open_tasks include repository (owner/name, or null if unassigned); a historical task_get resolves its recorded repository ID.

task_list items have no workflow field. task_get.workflow is a small historical reference {id, revision, phase, is_current} to the task's highest-revision stored workflow, including a retired workflow, or null when the task never had one. task_get(version=...) returns workflow: null. Use workflow_get to read the workflow history.

continuity_context does not compute merge reminders or workflow stalls. Its work object contains unattended for interactive task follow-up. The Bridge Work Center retains its existing workflow projections.

A task can carry a scheduled check in due_at (timestamptz, null when none). task_update and task_stage_set accept it as ISO 8601 with an offset (Z or +02:00); a timestamp without one is refused as due_at_timezone_required. Omitting it keeps the value, null clears it, and a stage change keeps it. task_get, task_list, continuity_context.open_tasks and the Bridge task reads include it, and task versions record it. Once due_at passes with no task write since, the open task is unattended from due_at (see unattended moves): continuity_context.work.unattended lists it with next_actor: null and its due_at.

task_ci_follow requires head_sha from the caller's local worktree HEAD; missing/null SHA returns head_sha_required rather than inferring it from a PR. Optional repository must equal the task's repository, case-insensitively (repository_mismatch). A task without a repository in a multi-repository project returns repository_required: set the task's repository first. The sole active binding remains the default for older unassigned tasks. The SHA must equal the current head of an open PR in that repository (pull_request_differs on mismatch). No PR lookup across repositories is performed. See the equivalent Bridge contract.

task_update

The minimum concurrency-safe shape is:

{
  "task_id": "<task UUID>",
  "expected_version": 3,
  "status": "in_progress",
  "write_context": {
    "resource": "https://mcp.heyaira.eu/p/<project-slug>/mcp",
    "instance_id": "<selected instance>",
    "project_id": "<authenticated project UUID>"
  }
}

If the version is stale, the whole update is rejected. Re-read with task_get; do not retry the stale mutation blindly.

When a task is newly transitioned to done, handoff_completed and handoff_next must be non-empty and work_receipt must be present. The receipt and task update commit atomically. handoff_blockers may be empty when there is no blocker; a blocked task must include a blocker. The server rejects incomplete completion with completion_handoff_required or completion_receipt_required without persisting either part.

Current contract rule

The server schema is authoritative. If a client reports write_context_required, it has either omitted the current required field or has not rediscovered the current tool schema. Reconnect and rediscover before trying again.

Task workflow history

Coordinators run scripts/heyaira-run.sh and record results with task_update. workflow_get reads retained workflow state and bounded phase history. Its compact view redacts frozen instructions; detail=true also requires agents:read and documents:read. See task workflow history.

Catalog provisioning

role_put, skill_put and agent_put append immutable account-scoped versions. Each requires spec, a human-written summary (1–280 characters), idempotency_key (1–200 characters), and the standard write_context. They require explicit OAuth agents:write, current project owner/admin membership, and an operator-managed account catalog editor grant. Existing static tokens and default OAuth grants do not gain this permission. See catalog provisioning.

Memory replacement

Use memory_supersede(memory_id, replacement_id, reason, idempotency_key, write_context) after creating a complete replacement with memory_add. Both entries must be active and in the authenticated project. An interactive owner/admin with memory:write may replace memory; execution credentials may not. Reuse the idempotency key only for the identical retry by the same subject. Missing/foreign IDs, self-replacement, an already replaced source and an inactive target are refused. Concurrent replacements are serialized per project.

This is whole-entry replacement. For a partial correction, carry unaffected facts and their sources into the new entry first. Dates and semantic similarity never mark notes obsolete automatically. Formal decision_* rules and frozen task contracts remain separate; a memory replacement does not revoke either.

Default memory_search, Bridge GET /bridge/v1/memory and continuity_context exclude superseded entries before pagination. Explicit include_history=true on search (or the Bridge query parameter) includes them with status, superseded_by and superseded_at. Current-only search may return no match when only the historical wording matches; it does not silently broaden the query.

memory_get and Bridge GET /bridge/v1/memory/{id} follow replacement chains in one database snapshot. The original ID remains in memory; for superseded entries its prose is replaced with a neutral notice for legacy-client compatibility. current_memory_id points to the terminal active entry and current_memory contains it. include_history=true exposes the original prose and replacement reason, still explicitly marked historical. History and the attributable audit event remain stored. Old text already cached in an agent's conversation cannot be recalled; the agent must refresh its reads.

Migration 066_memory_supersession.sql is additive. Existing entries remain active until explicitly superseded. Deploy all database clients with the new schema using the standard restore-point procedure. The deploy guard and runtime schema check refuse rollback to a server that does not know migration 066. Bypassing those guards would restore obsolete retrieval semantics: roll forward instead. Do not drop the columns or rewrite history to undo an incorrect replacement. Correct it with a new complete entry and supersede the current terminal entry.