cc-handoff
cc-handoff is a local MCP server that hands Markdown tasks and reports back and forth between a planning Claude chat and Claude Code.
create_task(project, title, body) — the planner creates the next task (
P001,P002, …) with statusopen.get_next_task(project) — Claude Code takes the oldest
opentask, receiving its ID, title and body, and the task becomesin_progress.submit_report(project, task_id, body) — Claude Code saves
<id>-report.mdand marks the taskreported.get_report(project, task_id?) — the planner reads a specific task's report, or the most recent one if no ID is given.
list_tasks(project) — lists ID, title and status of every task in a project.
Tasks move through
open→in_progress→reported→closed, though closing is a manual file edit since no tool does it.Inputs are validated: project slugs must be lowercase/digits/hyphens (e.g.
my-app), task IDs matchP001-style patterns, and bodies are Markdown.All state lives as plain Markdown files with YAML frontmatter in
~/.cc-handoff/(orHANDOFF_DIR), one sub-folder per project.All tools declare
execution.taskSupport: "forbidden"— they run synchronously and never spawn or manage long-running server-side tasks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cc-handoffCreate a task in my-app: add a dark-mode toggle"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cc-handoff
A small local MCP server that removes the copy-paste loop between a planning Claude chat (Claude Desktop) and Claude Code. The chat writes a task, Claude Code picks it up and leaves a report, and the chat reads the report — all through plain Markdown files on your disk.
Install
Requires Node.js 20+.
git clone https://github.com/ardayldz8/cc-handoff.git
cd cc-handoff
npm install
npm run buildData lives in ~/.cc-handoff/ by default (override with the HANDOFF_DIR
environment variable). Each project is a sub-folder holding P001-task.md,
P001-report.md, and so on. Task files carry YAML frontmatter
(id, project, title, status, created_at, updated_at).
Related MCP server: backlog
Configure
Use the absolute path to dist/index.js. Point both clients at the same data
directory (the default does that), so they see the same tasks.
Claude Code (user scope, available in every project):
claude mcp add --scope user cc-handoff -- node /absolute/path/to/cc-handoff/dist/index.jsClaude Desktop on Windows: after npm run build, quit Claude Desktop and
double-click install-desktop.cmd in the repo folder. See
Windows: Claude Desktop install below.
Claude Desktop on macOS: with the app fully quit, add this to
~/Library/Application Support/Claude/claude_desktop_config.json, then start it:
{
"mcpServers": {
"cc-handoff": {
"command": "node",
"args": ["/absolute/path/to/cc-handoff/dist/index.js"]
}
}
}Windows: Claude Desktop install
Claude Desktop must be fully closed while its config is edited. The running
app keeps claude_desktop_config.json in memory and rewrites the whole file
whenever a setting changes, so anything added while it runs is silently lost.
Quit Claude Desktop from the system tray (right-click the icon → Quit). Closing the window is not enough.
Double-click
install-desktop.cmdin the repo folder. If Claude is still running, the script asks you to quit it and waits (up to 5 minutes).The script backs up the config (
claude_desktop_config.json.bak-<timestamp>), addsmcpServers.cc-handoff, verifies that nothing else changed, and starts Claude again. Check Settings → Developer forcc-handoff.
Running it again is safe: if the entry is already there, nothing is written. Preview without changing anything:
install-desktop.cmd --dry-runNotes:
Where the config really is. Claude Desktop from the Microsoft Store / MSIX installer reads
%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude\claude_desktop_config.json. Inside the app (and in terminals it starts)%APPDATA%\Claudeis redirected there, but from a normal terminal that folder does not exist, so a file created at%APPDATA%\Claudeis never read. The script follows the app's own rule: it uses the LocalCache file when the package'sLocalCache\Roaming\Claudefolder exists, and the real%APPDATA%\Claudeotherwise (classic installs, or MSIX installs upgraded from the classic installer).Run it outside Claude. Claude Code sessions in the desktop app are child processes of Claude Desktop and are closed with it, so the script refuses to install from inside one. Use Explorer or a normal terminal.
The entry stores the full path of the
node.exethat ran the script. If you move or reinstall Node.js elsewhere, or move this repo, run the installer again.
Tools
Tool | Who uses it | What it does |
| chat | Creates the next task ( |
| Claude Code | Returns the oldest |
| Claude Code | Saves |
| chat | Returns a task's report; without |
| both | Lists ID, title and status of every task. |
Statuses: open → in_progress → reported → closed (close a task by
editing its file; no tool does that yet).
Example flow
Chat: "Create a task in project
my-app: add a dark-mode toggle." →create_task→P001(open)Claude Code: "Get the next task for
my-app." →get_next_task→ receives P001, which is nowin_progress, and does the work.Claude Code:
submit_report(my-app, P001, "...")→ P001 isreported.Chat: "Read the latest report for
my-app." →get_report→ plans the next step.
Development
npm test # store and installer unit tests (vitest)
npm run smoke # builds, starts the server over stdio, runs a full task -> report cycleTo try the Windows installer against a copy of a config file:
node scripts/install-desktop.mjs --dry-run --config path/to/copy/claude_desktop_config.jsonLicense
MIT
Available Tools
5 toolscreate_taskCreate taskB
Planner: create a new task for Claude Code in a project. Gets the next ID (P001, P002, ...) and status open.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Full task description in Markdown. | |
| title | Yes | Short task title. | |
| project | Yes | Project slug: lowercase letters, digits and hyphens (e.g. my-app). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it does disclose two useful side effects: ID auto-assignment (P001, P002, ...) and the task starting in 'open' status. However, it says nothing about permissions, duplicate handling, or failure behavior for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and scope. The second sentence is slightly telegraphic ('Gets the next ID ... and status open') but every clause conveys real information about the tool's side effects.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema and no annotations, so the description must cover behavior; it partially does by explaining ID and status assignment. It omits error/duplicate cases and what the caller receives back, leaving clear gaps for a write operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so project, title, and body are all documented in the schema (including the slug pattern and Markdown format). The description adds only the loose hint that the task lives 'in a project', which is baseline-appropriate but not additive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('create a new task') and scopes it to a project within the Planner/Claude Code domain. The verb alone distinguishes it from siblings get_next_task, list_tasks, and the report tools, though it never explicitly names or contrasts them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use or when-not-to-use guidance, and no mention of alternatives such as list_tasks for inspection or get_next_task for retrieval. The agent is left to infer that 'create' means 'use this one when adding a task.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_next_taskGet next taskA
Claude Code: take the oldest open task in a project. Returns its ID, title and body and marks it in_progress.
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project slug: lowercase letters, digits and hyphens (e.g. my-app). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose the critical non-obvious behavior: despite the read-like 'get_' name, it marks the task in_progress and returns ID, title and body. It stops short of edge-case behavior such as atomicity/concurrency when two agents claim the same task, or the outcome when no open task remains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler, and the note that it mutates state ('marks it in_progress') is saved for last where it lands as the key warning. Nothing redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, the description covers the return payload (ID, title, body) and the state side effect, which is most of what an agent needs. It omits failure/empty-queue behavior, which is a minor but real gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (project) with 100% schema description coverage including format and an example, so the schema already does the work. The description adds no syntax or scope detail beyond 'in a project', which is the expected baseline when coverage is complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — taking the oldest open task in a project — and immediately clarifies it also returns ID/title/body and mutates state. Among siblings (create_task, list_tasks, submit_report) this is clearly the claiming action, so an agent can distinguish it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'the oldest open task in a project' implies when the tool applies, but there is no explicit guidance on when to use it versus list_tasks, nor any note on prerequisites or what happens when no open task exists. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_reportGet reportA
Planner: read a task's report. Without task_id, returns the most recently submitted report in the project.
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project slug: lowercase letters, digits and hyphens (e.g. my-app). | |
| task_id | No | Task ID, e.g. P001. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the default-scope behavior (most recent report when task_id is absent) and the 'Planner:' prefix hints at a role/authorization scope, but it never confirms read-only safety, permissions, or what the report object contains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, front-loaded with the tool's role and resource, then the default-scope rule. No filler and nothing redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with no output schema, the description covers the essential call semantics and the default case. It stops short of describing the returned report's shape or errors, which is a minor gap given the simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented with patterns and examples. The description adds meaning beyond the schema by explaining the consequence of omitting task_id, which the schema does not state.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (a task's report), plus the fallback behavior when task_id is omitted. It does not reference any sibling such as list_tasks or submit_report, so the agent gets a clear purpose but no explicit differentiation from related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description conditions the call: 'Without task_id, returns the most recently submitted report,' which tells the agent how to invoke it in the default case. However, it never states when to prefer this over list_tasks or after submit_report, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tasksList tasksB
List all tasks in a project with ID, title and status.
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project slug: lowercase letters, digits and hyphens (e.g. my-app). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the returned fields but says nothing about ordering, pagination/limits for large projects, permissions required, or whether archived tasks are included.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler; the scope and returned fields are packed into one clause and nothing is repeated or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read tool with no output schema, naming the returned fields (ID, title, status) compensates well. However, with no annotations and no ordering or pagination details, an agent calling this on a large project knows little about the result shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema itself documents the project slug format with a regex and example, so the baseline is 3. The description only restates that the project scopes the listing and adds no syntax or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') plus resource ('tasks') and scope ('in a project'), and even names the fields returned (ID, title, status). It is distinguishable from create_task and get_next_task, though it never explicitly contrasts itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance and no mention of alternatives such as get_next_task for the next actionable item or get_report for reporting. The usage is only implied by the word 'List', leaving the agent to infer routing on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_reportSubmit reportB
Claude Code: save the report for a task and mark the task reported.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Report in Markdown. | |
| project | Yes | Project slug: lowercase letters, digits and hyphens (e.g. my-app). | |
| task_id | Yes | Task ID, e.g. P001. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses a second side effect beyond saving a report — the task is marked as reported — but says nothing about auth/permission requirements, whether an existing report is overwritten, or whether resubmission is idempotent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence that front-loads the primary action and appends the side effect. The 'Claude Code:' prefix is slightly odd framing but costs little.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-required-parameter mutation with no annotations and no output schema, the description covers the happy path but leaves state-change behavior on resubmission, error semantics, and the relationship to get_report unaddressed. Minimally adequate rather than complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: body, project slug format, and task_id pattern are all documented in the schema. The description adds no additional parameter meaning (e.g. precedence or how body relates to existing reports), so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('save the report for a task') plus the resulting state change ('mark the task reported'). It contrasts implicitly with the sibling get_report (retrieve) but never names alternatives, so the differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no mention of the sibling tools (get_report, get_next_task) that an agent might pick instead. The only usage signal is the implicit 'for a task' scoping.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
create_task - First observed
get_next_task - First observed
get_report - First observed
list_tasks - First observed
submit_report
TDQS
Scored across 5 tools
Each tool has a distinct action and resource: creating tasks, claiming the next task, submitting reports, reading reports, and listing tasks. The role annotations further clarify intended usage, so an agent should not confuse them.
All tool names use consistent snake_case verb_noun phrasing, such as create_task, get_next_task, submit_report, get_report, and list_tasks. The pattern is predictable and easy to scan.
Five tools are well-scoped for a lightweight task handoff workflow. Each tool supports a distinct step in the planner/Claude Code loop without unnecessary surface area.
The core handoff lifecycle is covered: create, claim, report, read report, and list. A direct get_task by ID or update/delete operation is missing, but the main workflow has no obvious dead ends.
Maintenance
Related MCP Connectors
One shared project for a team's coding agents: decisions, a task board and handoffs.
Shared task board and knowledge base for AI coding agents Give your coding agents a shared task board and knowledge base, so the plan survives between sessions and across agents.
Hand tasks, bugs and finished work to AI coding agents, and get back a write-up with evidence.
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA shared operational layer that synchronizes tasks and project contexts across Claude Chat, Cowork, and Code surfaces using local markdown files. It enables persistent state management and cross-session knowledge sharing without the need for a database.632 npm34MIT
- AlicenseAqualityDmaintenancePersistent, cross-session task management for Claude Code. 24 MCP tools for tasks, projects, dependencies, and docs. 7 skills for planning, standups, and handoffs. Event-sourced storage with per-project isolation.5MIT
- AlicenseAqualityAmaintenanceEnables AI agents to manage hierarchical tasks and stories stored as Markdown files, providing tools for creating, listing, editing, and updating task status through the Model Context Protocol.9MIT
- AlicenseBqualityCmaintenanceTask planning and tracking for AI agents with project-based organization and Obsidian-compatible markdown storage.1310 npmMIT