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, andtask_listreturnid,title,summary,tags, and structural fields (kind/status,version, timestamps). They never return the fullbody,description, orhandoff_*text. - Detail —
task_getreturns full task fields.memory_getreturns full active content. A superseded ID returns a notice and the terminalcurrent_memory; obsolete prose is withheld unlessinclude_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.