Skip to main content

Hanary MCP Server

Hanary MCP Server for Claude Code & OpenCode - task management that keeps new work outside the priority list until the user decides.

What Hanary MCP Is For

Hanary MCP is an operating layer for AI coding assistants. It lets agents read, start, update, and complete work from Hanary while preserving the user's priority decisions.

The key rule is: agents may capture and organize new work, but they should not silently insert it into the active priority order. New tasks default to needs_decision, staying outside top-task, start, and complete candidates until the user explicitly chooses to prioritize them or enables saved AI priority delegation for that scope.

Use Hanary MCP when you want Claude Code, OpenCode, or Codex to work from your confirmed Hanary task structure instead of inventing its own task order.

Mental model:

  • Hanary owns the user's task hierarchy and priority order.
  • The AI assistant follows that order.
  • New work is captured safely as needs_decision.
  • Explicit user intent, including a saved revocable priority policy, authorizes promotion into the active priority list.
  • executor_type: "ai" means user-approved execution delegation, not AI-owned priority judgment.
  • planning_status answers when work belongs in priority; executor_type answers who can execute it.
  • Human-owned tasks are ownership and completion boundaries, not safe advisory work boundaries: guide mode and safe non-destructive advisory help are allowed when the user asks to start, asks for guidance, or asks what to do next.
  • Users decide priority themselves or delegate priority decisions for new or existing unfinished tasks and can revoke that delegation. Completion judgment remains separate.

Independent AI Decision Delegation

Hanary web settings store two independent switches for each authenticated user's project or personal scope: delegate priority decisions and delegate task completion criteria decisions. Both default to OFF. The connected Codex or Claude AI reads live context, makes the permitted decision itself and saves it through MCP without asking for the same approval again:

Priority delegation Completion criteria delegation Result
OFF OFF Capture work; the user decides priority and task completion criteria.
OFF ON AI defines or revises task completion criteria; new work stays needs_decision.
ON OFF AI defines the comparison rubric and decides priority for new or existing unfinished tasks; task completion criteria require separate user authority.
ON ON AI decides priority and task completion criteria independently.

The assistant reads get_priority_delegation before capture or a delegated decision, using priority_delegated and completion_criteria_delegated separately. The deprecated criteria_delegated field concerned the priority comparison rubric; it never grants task completion criteria permission. Only authenticated web settings can enable or revoke either switch. Keep existing MCP connection configuration; there is no local mode flag. Explicit record-only intent overrides both grants for that request. A request only to defer priority leaves independent completion criteria delegation intact. Personal consent never grants squad changes; use the matching project-bound connection for squad tasks.

With priority delegation ON, the host AI reads prepare_priority_criteria and uses save_priority_criteria when the comparison rubric is absent or changed project goals/evidence warrant revision. The rubric answers which work comes first; it is distinct from the standard for when a task is done. Then use prepare_priority_placement(task_id) and finalize_priority_placement for new or existing unfinished tasks, including already prioritized tasks. The AI chooses a rank within the same parent while preserving all other siblings' relative order, and records a concrete reason. Prepare placement afresh after a rubric save changes the policy version. New tasks are first captured as needs_decision.

With completion criteria delegation ON, the host AI reads prepare_task_completion_criteria(task_id) and judges a concrete, verifiable completion standard from task purpose and live context. It directly saves or revises that standard with save_task_completion_criteria, passing the task ID, prepared policy version and snapshot, completion_criteria (at most 2000 characters), reason and retained idempotency key. The result sets completion_criteria_source="explicit". Reuse suitable existing criteria; do not weaken them just to claim completion. Missing essential intent still needs clarification. Defining what counts as done does not grant authority to execute or mark work done, change its executor or track time; existing completion evidence and review requirements remain in force.

Creation, comparison-rubric saving, priority placement and task completion criteria saving are separate outcomes. priority_workflow can report pending_ai_criteria or pending_ai_priority; independent completion_criteria_workflow can report pending_ai_completion_criteria. Only criteria_saved=true, planning_status="prioritized" or completion_criteria_saved=true, each with its receipt, confirms the relevant save. Failed continuation remains resumable from the captured task ID.

The server checks live authority and context atomically at saving. A stale snapshot requires fresh preparation and a new decision/key. Revocation stops future decisions without undoing saved order or criteria. Never bypass refusal through ordinary update, completion or priority tools. After response loss, keep all original arguments and the key; retry only the identical request to retrieve its receipt, including after revocation while access remains valid. The bridge never retries automatically, invokes a model or continues after the host stops. Separate explicit one-off user instructions still use existing task tools.

API vs MCP

Hanary's REST API remains the canonical product API. Use it for first-party apps, mobile or desktop clients, custom integrations, and any workflow where you control the application code that calls Hanary.

MCP is the AI-assistant integration surface on top of that API. Use it when you want tools like Claude Code, OpenCode, or Codex to discover Hanary actions automatically through tools/list, call them through tools/call, and receive the priority-boundary guidance directly in tool schemas and server instructions.

In practice:

  • REST API is for application integrations.
  • MCP is for agent integrations.
  • hanary-mcp is the installable stdio bridge plus commands, skills, and agent guidance for local coding assistants.

MCP is not required to perform Hanary operations, but it avoids rebuilding the same tool wrapper for every AI host and keeps the assistant's behavior aligned with Hanary's user-owned priority model.

Features

  • MCP Server: Direct tool integration with Claude Code and OpenCode
  • Slash Commands: /hanary-status, /hanary-start, /hanary-done
  • Skills: Task management workflow with estimation patterns
  • Agents: Task planner that drafts complex work decomposition for user review
  • Project Sync: Safe checks, diffs, and updates for generated assistant files
  • Full Compatibility: Works with both Claude Code and OpenCode

Installation

# Using uvx (recommended)
uvx --from hanary-mcp hanary-mcp --squad my-project

# Or install globally
uv tool install hanary-mcp

Configuration

Use project-scoped setup when different repositories should bind to different Hanary squads. Run this from the project root:

uvx --from hanary-mcp hanary-mcp init --squad your-squad-slug .

This creates project-local integration files:

  • .mcp.json for Claude Code
  • opencode.json for OpenCode
  • .codex/config.toml for OpenAI Codex

Repeat the command in each project with that project's squad slug. This keeps AI assistants working inside the right Hanary squad without sharing one global --squad value across all projects.

The value after --squad is the squad slug, not the display name. For example, if Hanary shows FutureGate (futuregate), use futuregate:

uvx --from hanary-mcp hanary-mcp init --squad futuregate .

After setup, verify the local binding:

uvx --from hanary-mcp hanary-mcp doctor --squad your-squad-slug

--squad can appear before or after doctor, init, or sync. For doctor, the same applies to --api-url and --token: explicit CLI values take precedence over environment defaults. If an option is explicitly given on both sides of the command, the later value wins.

Doctor prints the requested scope and checks project files against that scope; it does not infer the requested scope from those files. It reports project configuration and remote diagnostics separately. A successful squad-list lookup is not a membership check: Requested squad access check verifies access to the named squad, or explicitly shows SKIPPED in personal mode. The tool contract check compares the advertised tool catalog; it does not execute every tool or verify the MCP process already running in your assistant.

The printed package version belongs to the newly launched CLI. Doctor compares the configured API's /mcp catalog with that CLI's generated bridge catalog; it does not inspect an external app/session's exposed tools or an existing host process. --version has the same process boundary. A successful doctor result does not establish that an external app exposes the execution tools.

An actual project scope mismatch still exits with status 1, even when remote diagnostics succeed. Review the listed configuration arguments or rerun doctor with the intended scope; doctor never rewrites project files. Missing project files and a client without tools/list diagnostic support are reported as skipped, not failed; a skipped catalog leaves the remote summary INCOMPLETE rather than OK. A catalog request that fails still causes a failed result.

Inside an AI assistant, use get_current_scope when the active project or squad is unclear before creating, starting, completing, or reordering tasks. In project-scoped squad mode, the MCP server exposes the squad as the working boundary: use get_top_task for "what should I do next" inside that project. get_overall_top_task is intentionally not exposed in squad mode; use a separate personal/global Hanary MCP only when the user explicitly asks to leave the project scope.

Keeping Project Files Synced

Use hanary-mcp sync after upgrading hanary-mcp when an existing project should receive updated commands, skills, agents, or generated MCP config.

Start with a status check:

uvx --from hanary-mcp hanary-mcp sync --squad your-squad-slug .

Review diffs before writing:

uvx --from hanary-mcp hanary-mcp sync --squad your-squad-slug --dry-run .

Write only safe changes:

uvx --from hanary-mcp hanary-mcp sync --squad your-squad-slug --write .

sync --write creates missing files and updates files that still match the last managed template hash. It does not overwrite user-modified files. Local config files such as .mcp.json, opencode.json, and .codex/config.toml are marked for review instead of being overwritten, because they may contain squad slugs, tokens, uv cache settings, or other project-specific choices.

Use init --force only when you intentionally want to overwrite existing generated files. It can replace local edits in .codex/config.toml, .mcp.json, and opencode.json; after using it, re-check any OS-specific command, token, and cache settings.

The sync manifest is stored in .hanary-mcp-sync.json. It records template hashes for files managed by hanary-mcp, so future upgrades can distinguish safe generated-file updates from user edits. AI guidance changes are listed separately in sync output because they affect assistant judgment boundaries.

Claude Code Setup

  1. Set your API token as a system environment variable:
export HANARY_API_TOKEN='your-token-here'

On Windows PowerShell, set a persistent user environment variable:

[Environment]::SetEnvironmentVariable("HANARY_API_TOKEN", "your-token-here", "User")

Or set it only for the current PowerShell session:

$env:HANARY_API_TOKEN = "your-token-here"

Restart your AI coding assistant after changing environment variables. Existing Codex, Claude Code, or OpenCode processes do not inherit newly saved user environment variables; if they start the MCP server without the token, you may see an initialize/handshake failure such as connection closed.

  1. Prefer hanary-mcp init above, or add this to your project's .mcp.json manually:
{
  "mcpServers": {
    "hanary": {
      "command": "uvx",
      "args": ["--refresh-package", "hanary-mcp", "--from", "hanary-mcp", "hanary-mcp", "--squad", "your-squad-slug"]
    }
  }
}

Global CLI registration is useful only when one Hanary squad should be used everywhere:

claude mcp add hanary -- uvx --refresh-package hanary-mcp --from hanary-mcp hanary-mcp --squad your-squad-slug

Do not use global CLI registration with --squad when you need project-by-project squad separation. In that case, keep the --squad binding in each project's .mcp.json or .codex/config.toml instead.

OpenAI Codex Notes

hanary-mcp init generates .codex/config.toml for the current operating system. On macOS/Linux it uses zsh -lc so shell profile environment variables can load. On native Windows it runs uvx directly because zsh is not available by default:

[mcp_servers.hanary]
command = "uvx"
args = ["--refresh-package", "hanary-mcp", "--from", "hanary-mcp", "hanary-mcp", "--squad", "your-squad-slug"]

[mcp_servers.hanary.env]
UV_CACHE_DIR = ".uv-cache"

Keep UV_CACHE_DIR in the project root, such as .uv-cache, so Codex sandboxed runs can write to it. If you edit the Codex config manually on Windows, avoid copying a macOS/Linux zsh -lc command into that file.

Environment Variables

Set these in your shell profile (.bashrc, .zshrc, etc.) or OS user environment:

Variable Required Description
HANARY_API_TOKEN Yes Your Hanary API token
HANARY_API_URL No API URL (default: https://hanary.org)

Recovering a task write after a lost response

create_task and update_task accept an optional idempotency_key. Generate and retain a nonsecret unique key before sending one intended write. If its response is lost, call get_mutation_result(idempotency_key="the-original-key") in the same scope, or resend the original tool with exactly the same key and arguments. The bridge performs no automatic write retries.

An applied receipt confirms the write committed. A replay returns the same task ID and its current state, preserving later edits. not_recorded does not prove failure: the request might still be running. Different arguments with a used key are rejected. Never generate a new key merely to retry. Deleted, moved, or inaccessible tasks are not recreated or exposed by recovery.

The backend must advertise this contract before the bridge sends a keyed write. If no key was supplied, inspect the task and records after an uncertain response; legacy writes cannot be automatically retried safely. Receipt keys do not provide conflict detection for separate intentional edits with different keys.

Available Tools

Default Agent Workflow

Use Hanary MCP around one confirmed focus at a time:

get_top_task -> get_task/update_task for context and notes -> start_task
-> do the work -> stop_task/complete_task against the saved user-defined criterion
-> check completion/review state -> get_top_task and review current necessity

list_tasks, search_tasks, list_completed_tasks, list_work_activity, get_tasks_summary, and get_task_tree are context tools. They help inspect related work, historical completion or activity, duplicates, blockers, hierarchy, or review state, but they should not replace get_top_task as the source of current focus. Use list_completed_tasks for completed_at recall and list_work_activity with basis="activity" for work performed in an actual date range. In get_tasks_summary, status_counts uses explicit status meanings: started/in-progress task context means started_at is set and completed_at is nil. highest_priority_started_task is the first started task in summary priority order, not the current AI focus. This is separate from active time tracking; use get_task with include_time_summary=true to inspect has_active_session and active_session_started_at. When this server is started with --squad, get_top_task is the project focus boundary. Do not switch to overall/global focus unless the user explicitly asks to work outside the current project squad.

If get_top_task returns is_llm_boundary=true, treat it as an execution boundary, not as permission to pick from a list and not as an advisory stop signal. The response may include human_prioritized_candidates: these are user-prioritized tasks that are still marked executor_type: "human". Report that prioritized work exists but has not been delegated to AI for execution. Do not change executor_type, start execution work, or skip to a lower-priority AI task unless the user explicitly delegates AI execution or explicitly chooses that lower-priority work. If advisory_allowed=true and the user asks to start, asks for help, asks what to do next, or asks to work together, default to guide mode instead of only asking for AI delegation and stopping. Starting advisory time tracking for the current top-priority human-owned task is allowed in that flow; it is a collaboration record, not AI execution delegation.

That boundary does not block safe advisory support. Human-owned tasks create an ownership and completion boundary, not a safe advisory work boundary. If advisory_allowed=true and the user asks to start, asks for help with the human-owned task, asks what to do next, or says completion/final approval remains theirs, the assistant should continue in guide mode without asking for extra permission for non-destructive support work. Guide mode begins by briefly stating that the task remains human-owned, then reading the task context and providing the first 1-3 concrete user actions.

Safe autonomous advisory work includes reading Hanary task details, completion criteria, notes, and approach; reading related local documents; running read-only inspection commands such as rg, ls, sed, and git status; public research; summarizing findings; first-step guidance; checklists; verification plans; evidence organization; draft communication; interpretations of user-provided results; and creating new non-overwriting support artifacts such as Markdown reports under docs/, guides/, reports/, or notes/. When creating such an artifact, record its path and a short summary in Hanary notes and leave completion approval to the user.

Advisory time tracking is allowed for the current top-priority human-owned task when advisory_allowed=true and the user asks to start, asks for help, asks what to do next, or asks to work together. start_task in this case records advisory work as a collaboration record; it does not change executor_type, grant completion authority, or grant priority authority. Maintain an already active session; do not stop user-started sessions without confirmation, and do not stop any advisory session unless the user asks to stop, wrap up, or says the work is here for now.

External Reply or Approval Wait

When an inquiry, order, or approval request is complete and progress depends on an external reply, delivery, approval, or concrete event, inspect the task and its children. If no independent work remains in the affected subtree and its resume condition is known, call assess_task_hold with external_wait_confirmed=true. The flag is a factual assertion and defaults to false. The non-mutating assessment returns auto_hold_allowed=true only when the evidence is confirmed and hold_recommended=true; then user_confirmation_required=false and hold_task can proceed without an explicit stop or hold request, or another dependency-impact confirmation. Inspect and report dependency impact. Hold only the affected portion; keep executable preparation and siblings available. Use a dependency for an actual Hanary predecessor, not a hold for the same reason.

Time tracking must be inactive on the task and descendants. Never stop an active session automatically to make a hold possible. A user stop/wrap-up request authorizes its own time-tracking action: verify that it succeeds, then reassess task state from context. A break or end-of-day stop alone does not establish external waiting. Timer-only requests change only tracking; assessment-only requests such as "should we hold this?", explicit read-only/status-only/planning-only requests, and a planning-only agent role leave task state and tracking unchanged even if the assessment says auto holding is allowed. If evidence is unclear, clarify the missing fact or use existing explicit hold intent.

hold_task requires a reason plus a resume condition or follow-up time; automatic external-wait holds require a concrete resume condition. Record the waiting party, start time, and follow-up time when known. It preserves rank, planning_status, dependencies, and time sessions and stores a durable hold period without creating a judgment record. Report hold and timer results separately, including partial failures. next_actionable_task is context, not permission to start another task after a user stop. Use get_task_hold_history to recover prior context. Call unhold_task only after explicit user intent; it may add a short resume note and returns the task at its existing priority.

Prerequisites vs Hold

add_dependency represents a prerequisite relationship. Its legacy fields map blocking_task_id to the prerequisite and blocked_task_id to the dependent task. dependency_type defaults to blocks_start, which excludes the dependent task and its descendants from top-task selection and prevents starting or completion. Use blocks_completion when work and time tracking may proceed but review submission and completion must wait; that gate does not propagate to descendants. Use update_dependency_type to change the gate without deleting the relationship. Every gate is derived: rank and planning_status do not change, and completing the prerequisite clears the applicable gate automatically.

Use a dependency when a real Hanary task must finish first. Use hold_task when progress depends on an external reply or condition that has no Hanary task. Do not apply both mechanisms for the same waiting reason.

The assistant must ask first before modifying, deleting, or overwriting existing files; changing source code, circuit designs, or config; completing tasks; stopping user-started time sessions; stopping any time session without a user stop/wrap-up request; changing executor_type; changing priority; committing, pushing, or deploying; sending external messages; placing orders, payments, or bookings; or define completion criteria for the user without active completion criteria delegation or explicit instruction; or making/replacing the user's final judgment or completion approval.

Personal and Squad Mutation Boundary

Personal/global MCP keeps the normal tools for the user's personal tasks. An accessible squad task does not become personally governed work: membership and visibility provide context, not mutation authority. Only the directly assigned, accepted assignee may start, complete, hold, or unhold that squad task, append execution evidence through approach, notes, or retrospective, create an AI judgment draft, record their own historical work, and stop or clean up their own time session.

Squad priority, planning status, hierarchy, shared fields, dependencies, links, deletion, completion reversal, relocation, and planning-session mutations require the matching project-bound --squad context and server authorization. Tools such as reorder_task remain available in personal mode for personal work; their presence is not permission to apply them to a visible squad task.

Resuming saved work

Call get_task(task_id="123", include_resume_context=true) to add a read-only resume_context containing saved purpose, completion criteria, notes, holds, prerequisites, current judgments, an accepted next action when recorded, and AI report freshness. Source IDs and timestamps accompany saved records; full note text is preserved. Omit the option or use false to keep the existing response. The option accepts only a boolean.

not_recorded means no applicable saved record was found; unavailable means it could not be confirmed. A stale AI report means unknown liveness, not proof that an external process stopped. Multiple accepted next actions remain visible as conflicting candidates. Reading never generates or accepts a next action, changes priorities or holds, or starts timers or execution. Use get_top_task for the current priority and the existing history tools for older records.

Reviewing the next work after completion

After actual completion, assistant guidance connects what was resolved or newly learned to the next task in the same scope's confirmed priority order. It reuses fresh evidence and reads get_task(include_resume_context=true) only when the completed task or next candidate needs more context; a parent's purpose is read separately when relevant. The brief explanation identifies the next task and why it still matters, or suggests a narrower scope or reconsideration based on the new evidence. Missing context remains unconfirmed rather than an invented reason to proceed.

This is a read-only assessment, not a new approval gate: it never starts timers or AI execution, changes priority or delegation, writes a judgment, or skips to lower-ranked work. Human-owned candidates remain visible without starting an advisory timer. pending_review means submitted for review even when completion flags are set; it is not final acceptance. If a later context read fails, the known completion result is preserved and only the next-work review is reported as unavailable. These are assistant instructions, not an automatic necessity classifier or a guarantee that every agent will follow them.

Priority comparison scope

Execution candidates and comparison groups are separate choices. An explicit comparison anchor or parent in the current request takes precedence, followed by the conversation's confirmed scope and then a valid remembered selection. next_actionable_task and current_ai_focus never choose the comparison parent. Verify the project's connection with get_current_scope and briefly state the anchor and comparison parent before assessment. Ask for a scope choice only when the request remains ambiguous; a clear scope needs no repeated approval.

  • get_priority_comparison_scope reads the live comparison context. No arguments restore this user's remembered selection in the current project or personal scope. anchor_task_id alone selects its siblings, while parent_id selects direct children and explicit parent_id: null selects root. Supplying both verifies the relationship. Explicit arguments affect only that read.
  • save_priority_comparison_scope remembers one deliberately user-selected anchor_task_id and parent_id for future sessions. The scope choice can authorize saving it; incidental reads and "this time only" comparisons do not overwrite the remembered selection.
  • clear_priority_comparison_scope forgets only the current scope's selection when the user asks. Invalid selections are never automatically cleared.

Results include status, scope_source, the anchor and ancestor path, comparison parent and ID, unfinished direct children, saved selection, invalid reason and whether scope selection is required. Children include current ranks, planning_status, holds and actionability; ranks on not-yet-prioritized tasks do not represent a confirmed order. Restoration refreshes these states and includes new siblings. A move, deletion or access change that breaks the stored relationship or scope invalidates the selection instead of silently following a new parent. Moving the parent within the same scope can remain valid when the anchor is still its direct child.

Reads never change priority, execution or time sessions. Saving and clearing change only this authenticated user's selection. Remembering a scope grants no priority or execution authority. Existing parent assertions on prioritization and guards on reorder tools still apply, and applying an order requires user confirmation.

Task Management

  • get_current_scope - Show whether this MCP server is in personal mode or bound to a project squad
  • get_top_task - Primary tool for ordinary top-priority and "what should I do next?" questions; returns the current AI focus without bypassing the user's confirmed priority order
  • get_priority_comparison_scope - Read or restore a comparison anchor, parent and live direct children without changing state
  • save_priority_comparison_scope / clear_priority_comparison_scope - Remember or forget only the user's deliberately chosen comparison scope
  • get_overall_top_task - Personal mode only and only for an explicit all-squad request. Returns personal_top, squad_tops, and selection metadata; it does not invent a cross-scope winner when no global order is confirmed. This tool is not exposed when the MCP server is bound to a project squad.
  • get_task - Inspect a specific task with its purpose, attempts & decisions, references & results, children, ancestors, and time summary
  • list_judgment_records - Read the append-only problem → assessment → proposal → decision → outcome history attached to one task
  • create_judgment_record - Record a concise AI-authored problem/assessment/proposal draft. It never records user acceptance or rejection.
  • withdraw_judgment_proposal - After explicit user confirmation of the exact task_id, proposal_event_id, and reason, withdraw a pending AI proposal from review. Its effective status becomes withdrawn, not rejected. Original content, actor, time, and reason remain in history; nothing is permanently deleted.
  • supersede_judgment_proposal - With explicit user confirmation, provide the same fields plus replacement_proposal_id to retain an already-existing pending AI proposal in the same task and dimension. The old proposal becomes superseded; no third proposal is created and the target's content and acceptance state are unchanged. Human-authored or closed proposals cannot be cleaned up via MCP. Report cleanup_applied, affected IDs and effective statuses, and the remaining decision_targets with exact links. Neither cleanup action is acceptance or authorization to change or execute a task. Re-list history after an uncertain response before retrying. Original events keep their historical status; follow replacement_proposal_id on cleanup events to see the connection.
  • replace_judgment_proposal - Replace a pending AI proposal using its exact task_id and proposal_event_id. Optional problem_raised, assessment, and proposal inherit omitted sections; at least one must change. The old thread becomes superseded and a full, unaccepted AI snapshot becomes the new review target. Human-authored, accepted, rejected, and already superseded proposals cannot be replaced through MCP. Independent alternative proposals are preserved. Text saying “replaces X” does not perform replacement. After a timeout or stale-target error, re-list history before retrying; never create another proposal as a fallback. Check replacement_applied, state whether the old proposal was superseded, and concisely present the current decision_target with its exact review link. Retain previous_proposal and replacement_proposal IDs for follow-up calls; show them when requested or needed to resolve an ambiguous target or recover from an error. This does not change task fields, priority, or execution authorization; final acceptance/rejection stays web-only.
  • list_tasks - List tasks as supporting context; use get_tasks_summary for overviews
  • search_tasks - Find related tasks, duplicates, or blockers without choosing focus automatically
  • list_completed_tasks - List completed tasks by completed_at date range for historical recall and retrospectives
  • list_work_activity - List the authenticated user's actual activity by performed date with timer/manual provenance and exact/estimated accuracy
  • get_task_tree - Inspect hierarchy and decomposition without treating the tree as a new priority order
  • create_task - Create a new task. In personal mode, pass a squad_slug selected from list_my_squads to capture root squad work as a needs_decision proposal; omit parent_id and rank, and omit the slug for personal work. Adding a squad child or prioritized squad insertion requires the matching project-bound --squad context.
  • update_task - Update task title, description, completion-criteria selection, executor, purpose/background/approach/notes/retrospective, or due date. Set due_date with YYYY-MM-DD, send explicit null to clear it, or omit the field to keep the current value unchanged.
  • complete_task - Mark task as completed against the user's saved completion-criteria selection
  • uncomplete_task - Mark task as incomplete
  • delete_task - Soft delete a task
  • reorder_task / batch_reorder_tasks - Change priority order only after explicit user-confirmed placement
  • prioritize_task / batch_prioritize_tasks - Atomically promote existing tasks into the priority chain using an explicit user-confirmed order
  • move_task / batch_move_tasks - Clarify hierarchy inside the current personal or squad scope after user confirmation. They never expose personal work to a squad; use relocate_task_to_squad from the matching project-bound squad context for that visibility change.
  • list_reference_child_violations - Read-only audit for legacy personal task roots hidden under squad-reference pointers or actual squad tasks without inherited squad scope. It never moves or shares tasks.
  • relocate_task_to_squad - Project-bound squad mode only. After explicit user choice, move one repairable personal task subtree into the bound squad and pass a confirmation summarizing that choice. Personal/global mode reports the target squad but does not expose this mutation.
  • assess_task_hold - Evaluate an external-wait hold candidate without changing task state or time tracking
  • hold_task / unhold_task - Automatically hold confirmed external waits or follow explicit hold intent; resume only after explicit user intent, preserving existing priority
  • get_task_hold_history - Read newest hold periods without changing task state
  • record_historical_completion - Record an explicitly confirmed past completion instant separately from the time it was entered; requires an existing saved completion standard
  • add_dependency - Add a typed prerequisite that defaults to blocks_start
  • update_dependency_type - Change an existing prerequisite between blocks_start and blocks_completion without changing task priority or planning status
  • remove_dependency - Remove an existing prerequisite relationship

Historical Work Records

Do not start and stop today's timer to represent work performed on an earlier date. First call assess_historical_work with the intended payload and present the normalized performed date, duration, and any conflict. Call record_historical_work only after the user confirms that assessment.

Use entry_mode="exact_interval" only when both real timestamps are known. If the user remembers only the local date and duration, use entry_mode="duration_only" with performed_on and duration_minutes. Mark an approximate memory with accuracy="estimated" instead of inventing precise timestamps. Reuse an idempotency_key only for an identical retry.

Historical activity and task completion are separate records. record_historical_work never completes a task; use record_historical_completion only after the user explicitly confirms the actual completion instant and the task already has a saved user-confirmed completion standard. Use list_work_activity for performed-date recall and list_completed_tasks for completion-date recall.

Squad

  • list_my_squads - List squad display names and unique slugs. In personal mode, use it to resolve a user-named squad before passing its returned slug to create_task.
  • get_squad - Get squad details and shared-problem context
  • list_squad_members - List members who share the squad problem context
  • list_squad_events - List events and deadlines for shared-problem coordination
  • get_online_members - Check current presence when coordination is needed
  • start_planning_session / stop_planning_session - Change squad planning-session state only from the matching project-bound --squad context

Messages

  • list_messages - List squad messages for recent decisions, blockers, and shared context
  • create_message - Send a squad message around the shared problem, decisions, or blockers

Task Creation Policy

create_task records new work without assuming it belongs in the priority list. By default, new tasks are created as needs_decision, so they stay outside top-task, start, or complete candidates until the user decides whether to break them down or place them into priority. Use planning_status: "prioritized" only when the user explicitly wants the task placed in the priority order now. rank is ignored unless planning_status: "prioritized" is explicit, and is required for prioritized creation except for the first executable child under a prioritized parent with no prioritized siblings. Use get_task on the parent first when unsure; its child_creation_policy reports the parent planning_status, direct incomplete child counts by planning status, prioritized child count, and whether rankless first executable child creation is allowed.

When a user in personal mode asks to add work to a named squad, call list_my_squads before creating. Prefer an exact returned slug; otherwise require one unique exact display-name match. If there is no exact match or multiple squads share the display name, ask the user to choose from the returned names and slugs instead of guessing. Call create_task with that returned squad_slug, omit parent_id and rank, and omit planning_status or use needs_decision. This captures a root proposal without changing the squad's shared hierarchy or agreed priority. In project-bound mode, task creation always stays in the configured --squad, a per-call squad_slug override is rejected, and adding a child or explicitly confirmed prioritized insertion is available.

A task with squad_ref_id is a personal dashboard reference to a squad, not an actual squad task parent. Never use that reference as parent_id. From personal/global mode, create only a squad root proposal with squad_slug and no parent. In the matching project-bound squad context, a child may use an actual squad task whose squad_id identifies that same squad.

Use list_reference_child_violations to detect legacy personal children that already exist under squad references or actual squad tasks without inherited squad scope. The audit is read-only: it returns each entry's violation_type, repairable flag, blocking_reasons, descendant_count, and target squad without moving or sharing anything. In personal/global mode, present the findings and tell the user which target --squad context to enter; the wrapper intentionally returns no executable relocation action. In that matching project-bound context, require an explicit user choice before calling relocate_task_to_squad, because relocation exposes the entire task subtree to squad members. Relocate only entries marked repairable, pass a non-empty confirmation, and do not pass a per-call squad override.

References & Results and child tasks have different jobs. record_update is only an update_task input. create_task accepts initial purpose/background/approach/notes without this object. Include record_update with every update_task record write; use it for all References & Results and Attempts & Decisions writes while keeping purpose/background/retrospective in their named update_task fields. Put links, research notes, command output, formulas, and deliverables in references_results (stored as notes), and put what was tried, blockers, and reasons for an already chosen direction change in attempts_decisions (stored as approach). Always include the required action_items array, even for evidence-only updates, and put uncertain placement in optional ambiguous_items. In update_task, do not send legacy top-level notes or approach; they remain compatibility-only during rollout. If action_items or ambiguous_items is non-empty, Hanary changes nothing and returns needs_decision child task candidates for user review. This is an explicit caller classification rather than an AI classifier, and Hanary never creates or prioritizes those candidates automatically. If a checklist item can be executed independently, have its result recorded separately, and be judged complete on its own, create it as a child task candidate with parent_id instead of burying it in a record. Measurements, tests, checks, and concrete actions often belong in child task candidates when they can be performed one by one. Creating child task candidates clarifies hierarchy only; it does not make them executable or prioritized unless the user explicitly asks for priority placement.

When a problem, assessment, or improvement proposal materially changes a task's purpose, approach, scope, completion criteria, priority, next action, or shared commitment, use create_judgment_record instead of flattening the turning point into a mutable note. Summarize the transition and keep only an opaque source reference; never copy raw conversations, prompts, credentials, or secrets. AI-created records remain proposals. list_judgment_records preserves adopted, rejected, and superseded history, but MCP intentionally exposes no decision tool: silence, an AI recommendation, and general execution delegation are not acceptance, and final acceptance or rejection must come from an authenticated user action in Hanary's web UI.

A proposal should contain one independently adoptable decision. Split decisions only when the user could accept one and reject another; multiple checks supporting the same completion judgment can stay together. Put detailed test results, logs, and supporting analysis in assessment or existing task results. Keep acceptance-defining conditions, thresholds, exceptions, and scope in the proposal, with references to supporting records where needed. Do not remove a condition merely to shorten the text or enforce a new fixed-length template.

For judgment tool results, inspect user_decision_required and decision_target or decision_targets. When a decision is required, the default chat response names the task and judgment dimension, briefly explains the core decision and what adoption would settle, and links directly to the returned decision_url. After replacement, also say whether the old proposal was superseded and identify the current review target. Preserve decisive conditions and uncertainty in the summary; use the necessary proposal text if a shorter summary would hide the decision scope.

proposal_summary remains the full stored proposal in the MCP response. Full text, history, identifiers and exact review links are preserved; only routine chat presentation is shorter. Show the full text or identifiers when requested or needed for disambiguation or recovery. Never invent or reconstruct a missing URL: say when no direct review link was returned and show the returned target identifiers. A required decision with a missing or inconsistent target must be reported without guessing. When user_decision_required=false, do not request a decision. Final acceptance or rejection remains the authenticated user's action in Hanary's web UI.

If the user explicitly asks to make a new child task executable now and there are no prioritized siblings under its prioritized parent, create it in one call with parent_id and planning_status: "prioritized"; Hanary places that first executable child at rank: 0 without a comparison. needs_decision and priority_pending siblings do not block this first executable child exception because they are not priority comparison targets. If prioritized siblings already exist, ask the user for sibling order and include a rank from the user's confirmed order. Otherwise, even the first child task under a parent remains a needs_decision candidate.

For existing tasks, plain reordering does not finalize execution readiness. After the user explicitly confirms or delegates priority, use prioritize_task for one existing task or batch_prioritize_tasks for a complete sibling order. For root-level work, explicitly pass expected_parent_id: null or parent_id: null; do not omit the field. A non-null parent must be the prioritized parent the user reviewed. These tools atomically update planning_status and sibling ranks. The batch tool rejects omitted existing prioritized siblings by default; use append_after only when the user explicitly keeps them after the listed tasks.

planning_status and executor_type are separate axes. planning_status answers when the task belongs in the priority chain; executor_type answers who can execute it. A clear coding task can be planning_status: "prioritized" and executor_type: "ai" when the user has placed it into priority and the cause, likely fix location, and verifiable completion criteria are known. A human task can also be prioritized when it requires hardware assembly, measurement, purchase, installation, field operation, external approval, or final human judgment.

When executor_type is omitted, Hanary assigns the safe human default without automatic executor classification or recommendation. Send executor_type: "ai" only after the user explicitly approves AI execution. Mixed work should usually be split: create the explicitly delegated AI implementation task separately from the human real-device or field validation task.

Priority placement and AI delegation are separate decisions. A task can be planning_status: "prioritized" and still remain a human task. In that case get_top_task should stop execution actions at the boundary and explain that the user must explicitly delegate AI execution or explicitly choose lower-priority AI work before the assistant changes executor_type, starts execution work, or moves down the priority list. If advisory_allowed=true, the assistant should default to guide mode when the user asks to start, asks for help, or asks what to do next. A completion follow-up or next-work necessity assessment remains read-only within guide mode; it does not authorize advisory time tracking or record writes.

For human tasks, guidance is still useful and allowed. The assistant can help the person perform the task through safe autonomous advisory work: read-only inspection, public research, summaries, checklists, verification plans, safety/risk notes, evidence organization, draft communication, draft measurement criteria for user confirmation, new non-overwriting support documents, and interpretations of results the user reports back. This is advisory support, not task execution or final judgment. The assistant should give the first 1-3 concrete user steps rather than stopping at an AI delegation prompt.

For the current top-priority human task, advisory time tracking is also allowed as a collaboration record when the user asks to start, asks for help, asks what to do next, or asks to work together. This use of start_task does not delegate completion, change executor type, or change priority. Stopping time tracking is intentionally stricter: do not stop a user-started session without confirmation, and do not stop any advisory session unless the user asks to stop, wrap up, or says the work is here for now.

When starting a child task while an ancestor task has an active session, start_task defaults to ancestor_session_action: "ask" and returns a confirmation payload instead of silently stopping the ancestor session. After the user confirms, call start_task with ancestor_session_action: "switch" or use switch_active_session(from_task_id, to_task_id) to stop the ancestor session and start the child session.

Completion Policy

complete_task should be called against the user's saved completion-criteria selection. A saved completion_criteria_source: "title" means the user explicitly confirmed that the task title itself is the completion standard; do not repeat the title in completion_criteria. A saved completion_criteria_source: "explicit" means the task has a separate completion_criteria. Reuse either saved selection by calling complete_task with only task_id (and optional retrospective); do not prompt for or resend a criterion that is already saved.

With active completion_criteria_delegated consent, the host AI can define or revise the standard directly through prepare_task_completion_criteria and save_task_completion_criteria without repeated approval. Only when no completion-criteria source is saved and no active grant or separate explicit instruction covers the decision should the assistant ask the user to choose. If the user explicitly confirms that the title is sufficient, call complete_task with completion_criteria_source: "title". If the user defines a separate standard, send completion_criteria_source: "explicit" together with completion_criteria. Never infer that a title is sufficient, copy it into the separate field, or invent a criterion without the applicable permission. Criteria delegation never grants execution or completion authority. If the effective criteria are clear and verifiable, the agent may judge completion from evidence such as tests, deployment status, or document changes; if sufficiency is vague or depends on taste, values, social agreement, or priority judgment, ask the user to confirm it.

AI execution and human time

Autonomous AI work uses a separate execution record, not the user's timer:

  1. Read get_top_task; only this scope's current hierarchical top task with explicit executor_type: "ai" delegation can start.
  2. Call start_delegated_execution with task_id, a stable external_session_id, and an idempotency_key. Retain the IDs and returned version; reuse the same key on retries. If the host has no conversation ID, generate and retain an opaque ID. The bridge's process run ID is not a conversation identifier.
  3. Report running, waiting, or blocked with update_execution_status, supplying the execution ID, external session ID, and expected_version.
  4. Call finish_delegated_execution with succeeded or failed. This does not complete or approve the task; existing completion criteria and user approval still apply to complete_task separately.

Use list_delegated_executions(task_id) for the active run and recent history. get_task and get_top_task include execution_context. Different scopes can run concurrently alongside a human timer. One task cannot have two active AI claims. AI wall-clock duration includes waits; it is not human time or compute usage and is not added to existing human time statistics.

A heartbeat missing for 15 minutes means liveness is unknown, not stopped. Hanary does not automatically release stale claims or cancel external processes. After confirming the host is stopped, the owner can use cancel_delegated_execution with the execution ID, version, and reason, even if the old conversation identity was lost. Priority changes do not cancel runs.

start_task remains for human work and intentional advisory collaboration. Replacing any other active human timer requires user confirmation and the exact expected_active_session_id from the prompt; a stale source is rejected. Do not stop another timer as a workaround. If the execution tools are unavailable, explain that this connection cannot provide Hanary AI execution tracking; do not claim a registered execution or substitute start_task for AI work. Check the current connection's actual start/update/finish/list tools before claiming a run. For local stdio, refresh the package and restart the actual host/MCP process. For an external app, verify its connector registration and tool catalog refresh or reconnection separately. A local package refresh does not update that app's schema, and an unknown server label alone does not identify the cause. Do not invent a server name or switch connections/scopes automatically to bypass the missing tools.

Development

# Clone and install
git clone https://github.com/hanary/hanary-mcp.git
cd hanary-mcp
uv sync

# Run locally
HANARY_API_TOKEN=your_token uv run hanary-mcp --squad test

# Run tests
uv run --with pytest python -m pytest

Enhanced Features

Beyond the MCP tools, this project includes commands, skills, and agents for better UX.

Slash Commands

Command Description
/hanary-status Show current task status and squad overview
/hanary-start Begin working on top priority task
/hanary-done Complete current task against user-defined completion criteria and get next

Skills

  • hanary-workflow: Complete task management workflow with estimation patterns and best practices

Agents

  • task-planner: Drafts structured subtasks and estimates for user review

Platform Setup

Claude Code

Files auto-discovered from .claude/ directory:

.claude/
├── commands/          # /hanary-status, /hanary-start, /hanary-done
├── skills/
│   └── hanary-workflow/
│       └── SKILL.md
└── agents/
    └── task-planner.md

For project-specific squad separation, use the .mcp.json generated by hanary-mcp init --squad ... in each project. Global CLI registration binds hanary to one squad across projects, so use it only for a single shared default:

claude mcp add hanary -- uvx --refresh-package hanary-mcp --from hanary-mcp hanary-mcp

OpenCode

Files auto-discovered from .opencode/ directory:

.opencode/
├── commands/          # /hanary-status, /hanary-start, /hanary-done
└── agents/
    └── task-planner.md

Skills are shared via .claude/skills/ (OpenCode reads both .opencode/skills/ and .claude/skills/).

Configuration in opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcpServers": {
    "hanary": {
      "command": "uvx",
      "args": ["--refresh-package", "hanary-mcp", "--from", "hanary-mcp", "hanary-mcp"]
    }
  }
}

Note: HANARY_API_TOKEN must be set as a system environment variable.

Directory Structure

hanary-mcp/
├── .claude/                    # Claude Code files
│   ├── commands/
│   │   ├── hanary-status.md
│   │   ├── hanary-start.md
│   │   └── hanary-done.md
│   ├── skills/
│   │   └── hanary-workflow/
│   │       ├── SKILL.md
│   │       └── references/
│   └── agents/
│       └── task-planner.md
├── .opencode/                  # OpenCode files
│   ├── commands/
│   │   ├── hanary-status.md
│   │   ├── hanary-start.md
│   │   └── hanary-done.md
│   └── agents/
│       └── task-planner.md
├── .mcp.json                   # MCP server config
├── opencode.json               # OpenCode config
└── src/hanary_mcp/             # MCP Server implementation

License

MIT

Decision context in read responses

  • detect_overload checks configured risk signals, not available capacity. Its assessment reports scope and per-rule candidate, evaluated, missing-data and matched counts. No signal does not mean the schedule has spare time. In a squad-bound connection the calculation is restricted to the user's work in that squad; personal/global mode retains the accessible user-work scope.
  • list_work_activity.review_summary reports total, pending-review and excluding-pending-review minutes for the returned page's activity slices. get_task with include_time_summary provides the same breakdown under time_summary.review_summary for the task across all actors and all time, including corrections and active sessions. Pending session IDs allow review; approval and correction remain subject to session ownership. exact describes recorded interval boundaries, and excluding pending review does not establish that the user verified every remaining record.
  • Use lifecycle_status for the task's own state. Child progress and active time tracking are separate. Legacy status meanings are documented in task_state_semantics, including compact task summaries.
  • list_hold_reviews accepts due, needs_context, undated, or all. needs_context finds missing reasons or return paths, not every undated wait. update_hold_review supplements the current reason/condition or reschedules follow_up_at; omit a field to keep it, use null to clear an optional field. It preserves original hold history, hold state, priority and timers. Resume explicitly with unhold_task when the user chooses to do so.

Connection capabilities can differ. doctor checks the advertised tool inventory, executor default and structured update input against the bridge's contract; a missing field is a connection mismatch, not an instruction to invent an input.

Criteria and verification reports

Use get_task(include_resume_context=true) to read saved criteria and reported evidence together. record_verification_report appends a report against the exact expected_criteria_source and expected_criteria_text you read, with a retained idempotency_key, checked scope, optional limitations, and up to ten items (criterion, outcome: met/unmet/unknown, optional checks, evidence, and HTTP(S) result_url). A changed criterion rejects a stale submission.

list_verification_reports reads three reports per page; pass its next_before_id as before_id for older reports. The web task resume panel shows the same records and highlights changes to the original criterion. Corrections are new reports; existing notes remain intact. After a lost write response, use get_mutation_result or retry the identical request with its original key. Reports are AI-reported evidence, not independently verified tests, complete criterion coverage, user approval, or automatic task completion.

First-action drafts

Use get_task(task_id="…", include_planning_context=true) to reuse the saved goal, current purpose and completion picture. The optional planning_context contains original note IDs, explicit missing states and drafting guidance. Present 1–3 small first-action candidates with reasons, asking only for missing information that changes the first action. Let the user edit, select or cancel before saving accepted candidates through create_task. Its default needs_decision state keeps priority confirmation separate; reading context or drafting candidates does not assign an executor, choose completion criteria, or start a timer or execution. Existing executor inheritance still applies when a user accepts a child task. Omitting the option preserves the existing response.

Saved standing delegation

In a task's 작업 이어보기 → 반복 위임 관리, save the tasks/project, allowed and excluded actions, excluded branches and expiry. Manage or revoke your saved instructions from Settings. They grant no new account or API access.

The assistant can read list_task_delegations, check assess_delegated_action and use execute_delegated_action for a supported action. Existing priority, AI ownership, saved completion criteria and review rules still apply. Completion through this mechanism covers AI-owned leaves with no active human timer. Create/edit/revoke are web actions, never MCP self-approval.

Retain the action's request key. After an uncertain response, read get_delegated_action_result; it can recover the original result even after revocation while task access remains. That result is a saved snapshot, not current task state. No automatic retry occurs. get_delegation_history shows rule changes.

These instructions apply to the delegated-call tool, not every legacy API action. Do not bypass a refused standing instruction through a direct tool. Revocation does not stop external AI processes, undo completed work or revoke API tokens. External commits/deployments/messages and human timers require separate authority.

Metadata

Release files for hanary-mcp 0.39.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hanary-mcp 0.39.0
File Size Uploaded Provenance
hanary_mcp-0.39.0.tar.gz 268.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hanary-mcp 0.39.0
File Interpreter ABI Platform
hanary_mcp-0.39.0-py3-none-any.whl Python 3 none any Details

Total release size: 403.9 kB

Release files / hanary_mcp-0.39.0.tar.gz

Download URL hanary_mcp-0.39.0.tar.gz
Size 268.8 kB
Tags Source
SHA-256 checksum
How to use checksums
4c5ff477df694a8a8fcc899505515f8dd550aa73d7f87c2681d1d094ffc36f3e
BLAKE2b-256 checksum
How to use checksums
b18980943b22ad5ef020c952e519cb0e3be7404de1dbed5fc4aed1100d62070e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / hanary_mcp-0.39.0-py3-none-any.whl

Download URL hanary_mcp-0.39.0-py3-none-any.whl
Size 135.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6759ad1a0ae6f0f9f8ce84ec59b23ba021dbecbc8278fe66e6f60f958e87850a
BLAKE2b-256 checksum
How to use checksums
91e8ab6ac33bdb343b644aa93f54d2c6ef6b400f347a5442fbae78a1ab0b926b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Security for hanary-mcp 0.39.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for hanary_mcp-0.39.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.39.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page