# 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.

Agent View of the PolicyLayer registry record for `accept_handoff`. HTML page: https://policylayer.com/tools/io-github-ajc3xc-meridian/accept-handoff

## Facts

- Tool: `accept_handoff`
- Server: Meridian (`@meridianmcp/mcp`) — https://policylayer.com/tools/io-github-ajc3xc-meridian.md
- Install: `npx -y @meridianmcp/mcp`
- Homepage: https://github.com/meridianmcp/Meridian
- Risk category: Destructive (Critical risk)
- Registry record: grade D, identity unverified
- Server auth posture: gated
- Server CORS policy: *
- Server rate-limited: no
- Parameters: 12
- Recommended policy verdict: Hidden

## Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `goal_token` | string | no | Optional: the token value from the <goal_token>…</goal_token> line in the /goal block being accepted. |
| `live_items` | array | no | 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 | no |  |
| `session_id` | string | no | 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 | no | Project name — an alternative to project_id; resolved to the id internally. project_id wins if both are given. |
| `presented_body` | string | no | 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 | no | Optional: tool names the handoff declared as required. Paired with available_tools to detect CAPABILITY_UNAVAILABLE. |
| `available_tools` | array | no | Optional: tool names actually available to you right now (e.g. from a live tools/list). Paired with required_tools. |
| `delivery_source` | string | no | 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 | no | 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 | no | 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 | no | 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.

## Example call (MCP tools/call, JSON-RPC 2.0)

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "accept_handoff",
    "arguments": {}
  }
}
```

## 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 signals: High parameter count (12 properties) · Bulk/mass operation — affects multiple targets

## Use case

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.

## Recommended policy (PolicyLayer)

Verdict: **Hidden**. Enforced by the PolicyLayer MCP gateway (https://policylayer.com/mcp-gateway) before a call reaches Meridian:

```json
{
  "version": "1",
  "default": "deny",
  "hide": [
    "accept_handoff"
  ]
}
```

## Other tools on Meridian (234)

- `acquire_docx_document_lease` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/acquire-docx-document-lease.md
- `answer_hitl` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/answer-hitl.md
- `batch_mutate` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/batch-mutate.md
- `capture_research_finding` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/capture-research-finding.md
- `checkpoint` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/checkpoint.md
- `claim_docx_region` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/claim-docx-region.md
- `claim_file` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/claim-file.md
- `claim_sprint_item` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/claim-sprint-item.md
- `clear_capability_profile` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/clear-capability-profile.md
- `clone_profile_layer` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/clone-profile-layer.md
- `delete_custom_hook` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/delete-custom-hook.md
- `delete_note` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/delete-note.md
- `delete_sprint_item_pointer` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/delete-sprint-item-pointer.md
- `delete_watchlist_query` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/delete-watchlist-query.md
- `dismiss_hitl` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/dismiss-hitl.md
- `fan_out_sprint_items` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/fan-out-sprint-items.md
- `idle_until_all_done` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/idle-until-all-done.md
- `index_equation` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/index-equation.md
- `index_figure` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/index-figure.md
- `index_table` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/index-table.md
- `ingest_document` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/ingest-document.md
- `ingest_document_structure` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/ingest-document-structure.md
- `link_figure_caption` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/link-figure-caption.md
- `link_flag_to_section` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/link-flag-to-section.md
- `link_proposal_lineage` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/link-proposal-lineage.md
- `link_table_caption` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/link-table-caption.md
- `log_task` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/log-task.md
- `purge_ai_log` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/purge-ai-log.md
- `receive_messages` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/receive-messages.md
- `reconcile_stale_claims` — Destructive — https://policylayer.com/tools/io-github-ajc3xc-meridian/reconcile-stale-claims.md
- …and 204 more: https://policylayer.com/tools/io-github-ajc3xc-meridian.md

## For agents

This record is a snapshot. Live verdicts and the full registry:

- Check every server in your MCP config at once: `npx -y policylayer stack`
- Vet a server before you add it: install the mcp-precheck skill — `npx skills add https://policylayer.com` (skill text: https://policylayer.com/skill.md)
- Query the registry over MCP: endpoint `https://api.policylayer.com/mcp` — tools `check_mcp_server`, `check_mcp_stack`, `check_tool`, `search_registry`, `get_change_events`

---

Source: the PolicyLayer MCP registry — one continuously verified record per MCP server. Full record: https://policylayer.com/registry?q=io-github-ajc3xc-meridian · API: https://policylayer.com/registry/api · Policy library: https://policylayer.com/policies/io-github-ajc3xc-meridian
