accept_handoff
[SUPPORT] Read-only: (1bd5e810) Canonical receiver-side acceptance check for a handoff envelope — composes token verification, capability/tool availability, tool-manifest drift, and board-revision divergence into ONE structured verdict, so MCP/HTTP/stdio all produce identical results for identica...
This record as markdown: /tools/io-github-ajc3xc-meridian/accept-handoff.md
What accept_handoff does on Meridian
AI agents call accept_handoff to permanently remove resources in Meridian, typically in cleanup and lifecycle workflows. It does its job in a single call, and there is no undo.
| Parameter | Type | Required | Description |
|---|---|---|---|
goal_token | string | — | Optional: the token value from the <goal_token>…</goal_token> line in the /goal block being accepted. |
live_items | array | — | Optional: your own get_sprint_items(...) result (the exact items/filter the compared handoff/manifest was generated from) — required for the tool-manifest-drift |
project_id | string | — | |
session_id | string | — | Optional (1b7eb437): your own claiming session's id, used ONLY to attribute a durable handoff-provenance receipt to this call when accepted=true (action_audit_l |
project_name | string | — | Project name — an alternative to project_id; resolved to the id internally. project_id wins if both are given. |
presented_body | string | — | Optional: the full pasted /goal block (token + SECURITY banner included), checked against the token's stored body_hash AND against project_id/expected_repo_path |
required_tools | array | — | Optional: tool names the handoff declared as required. Paired with available_tools to detect CAPABILITY_UNAVAILABLE. |
available_tools | array | — | Optional: tool names actually available to you right now (e.g. from a live tools/list). Paired with required_tools. |
delivery_source | string | — | Optional (22f2604d): a label for how you received this content (default 'chat_paste'). Echoed back verbatim; purely informational bookkeeping alongside the alwa |
expected_repo_path | string | — | Optional (22f2604d): YOUR OWN independently-known repo root (e.g. from your own meridian.toml/cwd) — never a value read out of presented_body itself. Compared a |
expected_board_revision | string | — | Optional: the board_revision value from a manifest's <handoff_manifest board_revision="..."> attribute, or any prior meridian.handoff.compute_board_revision(... |
expected_required_tools_hash | string | — | Optional: a prior meridian.handoff.compute_required_tools_hash(...) result to compare against live_items' current tool_requirements. |
Parameters from the server's own tool schema.
Why accept_handoff is rated Critical
An AI agent that decides to call accept_handoff doesn't hesitate, doesn't double-check, and doesn't stop at one. Whatever it removes from Meridian is gone. There is no undo for destructive operations.
Risk signalsHigh parameter count (12 properties) · Bulk/mass operation — affects multiple targets
Attacks that exploit this kind of access
The rule that runs accept_handoff safely
PolicyLayer is an MCP gateway: it sits between your AI agents and Meridian, and checks every tool call against a rule you set before the call runs. Nothing changes on the server itself. For accept_handoff, this is the rule to start with:
accept_handoff is removed from the agent's tool list entirely, so the agent never calls it. The rest of the server keeps working.
The button opens the PolicyLayer dashboard: create your workspace, connect Meridian, apply this rule, and every accept_handoff call is checked against it from then on.
Questions about accept_handoff
[SUPPORT] Read-only: (1bd5e810) Canonical receiver-side acceptance check for a handoff envelope — composes token verification, capability/tool availability, tool-manifest drift, and board-revision divergence into ONE structured verdict, so MCP/HTTP/stdio all produce identical results for identical input (same underlying meridian.handoff.accept_handoff_envelope every transport calls). Every input is optional and independently gated — supply whatever you have; an omitted check is skipped, never failed. Returns {accepted: bool, result: 'ok'|'STALE_HANDOFF'|'FOREIGN_PROJECT_CONFIG'|'BOARD_DIVERGENCE'|'TOOL_MANIFEST_DRIFT'|'BODY_HASH_MISMATCH'|'CAPABILITY_UNAVAILABLE', reasons: [str], token_check, identity_check, capability_check, tool_manifest_check, board_check, is_trusted_channel: false, delivery_source: str}. Checks run in this order, short-circuiting on first failure: (1) token — token/presented_body via the same verify_handoff_token check; a body_mismatch reason maps to BODY_HASH_MISMATCH, every other invalid reason (not_found/wrong_project/already_consumed/expired) maps to STALE_HANDOFF — the raw token_check.reason sub-field always preserves which one, since AGENTS.md treats not_found/wrong_project as real spoofing signals and already_consumed/expired as usually just a sibling session having already acted. (2) identity binding (22f2604d) — presented_body's own <project_start_config> tag vs THIS call's project_id/expected_repo_path, via meridian.handoff.check_project_start_config_identity; runs whenever step (1) did not already reject the envelope on its own basis — i.e. token verification passed or no token was presented — so a body whose embedded identity disagrees with project_id is FOREIGN_PROJECT_CONFIG even when the token itself verified ok. This catches a genuine token paired with a foreign project's start-config, which step (1)'s wrong_project check alone cannot (that only catches a token minted for a DIFFERENT project_id, not a body whose own tag disagrees with a token that legitimately matches project_id). It does NOT re-run after step (1) already failed (STALE_HANDOFF/BODY_HASH_MISMATCH) — that failure is independently sufficient to reject the envelope. (3) capability — required_tools vs available_tools: any required name missing from available_tools is CAPABILITY_UNAVAILABLE. (4) tool-manifest drift — expected_required_tools_hash vs a hash computed live from live_items' own tool_requirements fields (see meridian.handoff.compute_required_tools_hash): mismatch is TOOL_MANIFEST_DRIFT. (5) board revision — expected_board_revision (acf6f51a's manifest <handoff_manifest board_revision=...>) vs a hash computed live from live_items via meridian.handoff.compute_board_revision: mismatch is BOARD_DIVERGENCE. live_items is YOUR OWN get_sprint_items(...) result — this tool never queries the board itself, so you control exactly which project/version/status filter "live" means; pass the same filter used when the compared handoff/manifest was generated. is_trusted_channel is always false here (calling this tool at all means verifying something other than the trusted pending_goal/load_handoff channel — see those tools' own docs). Scope note: this is a validation/report tool, not a hard gate — it is not wired into claim_sprint_item in this pass. Persistent-state disclosure: on hosted Meridian, supplied text and project/session metadata -- including task log entries, pinned decisions, sprint items, notes, handoff/goal state, and HITL queue items -- are sent to and stored in Meridian's service, in an isolated per-tenant Postgres database (Neon); self-hosted deployments keep the same categories in the configured local SQLite/Postgres database. This data is visible in the dashboard and API, and may resurface in later project context or handoffs. Notes and pinned decisions can be deleted individually; task log entries and sprint items can be deleted via the dashboard/API (not exposed as an agent-facing tool); HITL queue items and handoff state have no per-record delete. Full removal of any of this data is available via project or account deletion, using the documented controls. Do not include secrets. It is categorised as a Destructive tool in the Meridian MCP Server, which means it can permanently delete or destroy data. Block by default and require explicit approval.
accept_handoff accepts 12 parameters: goal_token, live_items, project_id, session_id, project_name, presented_body, required_tools, available_tools, delivery_source, expected_repo_path, expected_board_revision, expected_required_tools_hash. The full parameter table on this page comes from the server's own tool schema.
Register the Meridian MCP server in PolicyLayer and add a rule for accept_handoff: allow, deny, rate-limit, or require approval. Point your MCP client at the PolicyLayer proxy URL and the rule is enforced on every call, before it reaches Meridian. Nothing to install.
accept_handoff is a Destructive tool with critical risk. Critical-risk tools should be blocked by default and only enabled with explicit human approval.
Yes. Add a rate_limit block to the accept_handoff rule in your PolicyLayer policy. For example, setting max: 10 and window: 60 limits the tool to 10 calls per minute. Rate limits are tracked per agent session and reset automatically.
Set action: deny in the PolicyLayer policy for accept_handoff. The AI agent will receive a policy violation error and cannot call the tool. You can also include a reason field to explain why the tool is blocked.
accept_handoff is provided by the Meridian MCP server (@meridianmcp/mcp). PolicyLayer sits as a proxy in front of this server to enforce policies before tool calls reach the server.
More on Meridian, and thousands of servers like it.
Across the catalogue