MCP任务跟踪器
一个类似Jira的最小任务跟踪器,通过Streamable HTTP作为MCP服务器公开。
任务存储为带有YAML frontmatter的Markdown文件,每次写入操作都会创建一个Git提交。
需求
- Node.js(使用Node v22测试)
- Git CLI可在
PATH - Git存储库初始化于
~/.mcp_tracker/projects(项目根),带有user.name和user.email配置
安装/构建
服务器不需要构建步骤。安装依赖项:
npm ci运行测试:
npm test跑
启动MCP HTTP服务器:
npm start或者:
node server.js默认情况下,服务器监听:
http://127.0.0.1:3000/mcp绑定地址和端口可以配置环境变量:
MCP_HTTP_HOST=127.0.0.1 MCP_HTTP_PORT=3000 npm start命令行界面
CLI提供对项目任务列表的访问,而无需启动MCP服务器。
能力:
- 从以下位置读取任务 `~/.mcp_tracker/projects/
`
- 按以下方式输出的组
backlog,todo,以及in_progress - 按项目和ID显示单个任务的元数据和正文
- 从Markdown文件导入任务并创建Git提交
列出项目的任务:
npm run tasks:list -- --project
输出按以下方式分组 backlog, todo,以及 in_progress,表格中有线条 ID - Title.
例子:
npm run tasks:list -- --project ta-backendbacklog:
todo:
in_progress:
TB-065 - Example task title显示任务详细信息(元数据+正文):
npm run tasks:get -- --project
--id 输出打印 field: value 成对,后跟一个空行和任务正文(如果有的话)。
例子:
npm run tasks:get -- --project ta-backend --id TB-065id: TB-065
project: ta-backend
type: user_story
title: Example task title
status: in_progress
created_at: 2026-01-21T10:00:00+00:00
started_at: 2026-01-21T10:05:00+00:00
tool: codex
Task body content...使用frontmatter从Markdown文件导入任务:
npm run tasks:import -- --project
--file
文件必须以包含以下内容的frontmatter开头 title 和 type. 创建的任务体是从frontmatter后的Markdown内容中复制的。 如果前体包含 id,导入的任务标题以该值作为前缀 除非标题已经包含它。导入接受 story 作为别名 user_story.
---
id: DM-XCRT-006
title: "Zone trail `F1/F2/F3`"
type: story
---
## Description
Task body content...存储布局
服务器将项目存储在以下位置:
~/.mcp_tracker/projects
重要提示:
- 项目根(
~/.mcp_tracker/projects)必须是Git存储库,因为服务器会检查工作树状态,并在每次写入操作时创建提交。 - 示例设置:
mkdir -p ~/.mcp_tracker/projects
cd ~/.mcp_tracker/projects
git init
git config user.email "you@example.com"
git config user.name "Your Name"
git commit --allow-empty -m "init"每个项目都是一个名为的目录:
^[a-z0-9-]+$
每个任务都是一个文件:
- `~/.mcp_tracker/projects/
/.md`
命名规则:
- 任务
ID(文件名和id前场)必须匹配^[A-Z0-9-]+$(仅限大写字母)。
任务文件格式
例子:
---
id: FR-001
project: frontend
type: user_story
title: "My title"
status: backlog
created_at: 2026-01-21T15:03:23+05:00
---
## Description
Task body in Markdown...笔记:
title以JSON字符串(引号)的形式存储在frontmatter中。created_at使用带UTC偏移的ISO-8601。
与MCP客户端一起使用
使用启动服务器 npm start,然后配置MCP客户端以使用 可流式传输的HTTP端点:
http://127.0.0.1:3000/mcpMCP工具参考
所有工具都返回序列化为MCP的JSON有效负载 text 内容。
常见响应形状
- 成功:
- { "ok": true, "data": ... }
- 错误:
- { "ok": false, "error": { "code": string, "message": string } }
projects.list
列出下的有效项目(目录) ~/.mcp_tracker/projects.
- 输入:
{}(无参数) - 输出:
{ ok: true, data: { projects: string[] } }
tasks.template
根据以下内容从项目目录中读取任务模板文件 type 输入。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - type (string):必须匹配 ^[a-z0-9_-]+$ (例如。, story -> STORY_TEMPLATE.md)
- 文件选择:
- 该工具寻找 PROJECT_DIR/[TYPE]_TEMPLATE.md 哪里 [TYPE] 是上壳的吗 type 价值。 - 例子: type: "bug" -> BUG_TEMPLATE.md, type: "story" -> STORY_TEMPLATE.md.
- 有效类型由以下因素决定
*_TEMPLATE.md项目目录中存在的文件名。 - 错误:
- INVALID_TEMPLATE_TYPE 当 type 不匹配 ^[a-z0-9_-]+$. - TASK_TEMPLATE_NOT_FOUND 当预期 *_TEMPLATE.md 文件丢失。
- 输出:
{ ok: true, data: { template: string } }
tasks.create
在项目目录中创建任务文件并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - type (枚举): user_story | bug | review - title (string):非空 - body (字符串,可选)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at } } - 笔记:
- id 输出必须匹配 ^[A-Z0-9-]+$
tasks.update
更新现有任务并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID(也是没有的文件名 .md),必须匹配 ^[A-Z0-9-]+$ - patch (对象): - type (可选枚举): user_story | bug | review - title (可选字符串):非空 - body (可选字符串): "" 清除身体
- 规则:
- 仅在以下情况下允许 status === "backlog" (否则 FORBIDDEN_UPDATE_IN_STATUS)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at } }
tasks.promote_to_todo
从以下位置移动任务 backlog 到 todo 并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$
- 规则:
- 仅在以下情况下允许 status === "backlog" (否则 INVALID_STATUS_TRANSITION)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at } }
tasks.claim
声明任务:将其从 todo 到 in_progress,套 started_at,可选存储 tool,并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$ - tool (字符串,可选):声明工具名称
- 规则:
- 仅在以下情况下允许 status === "todo" (否则 INVALID_STATUS_TRANSITION)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at, started_at?, tool? } }
tasks.done
完成任务:将其从 in_progress 到 done,套 done_at,并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$
- 规则:
- 仅在以下情况下允许 status === "in_progress" (否则 INVALID_STATUS_TRANSITION)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at, done_at? } }
tasks.release
将任务释放回队列:将其从 in_progress 到 todo,清除 started_at 和 tool,并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$
- 规则:
- 仅在以下情况下允许 status === "in_progress" (否则 INVALID_STATUS_TRANSITION)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at } }
tasks.cancel
取消任务:将其从 backlog/todo/in_progress 到 canceled,套 canceled_at,并提交更改。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$
- 规则:
- 不允许在以下情况下 status 是 done 或 canceled (否则 INVALID_STATUS_TRANSITION)
- 输出:
{ ok: true, data: { id, project, type, title, status, created_at, canceled_at? } }
tasks.list
列出具有可选筛选的项目任务。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - status (可选枚举): backlog | todo | in_progress | done | canceled - type (可选枚举): user_story | bug | review - text (可选字符串):不区分大小写的子字符串匹配 title 和 body
- 输出:
{ ok: true, data: { tasks: TaskView[] } } TaskView:
- id, project, type, title, status, created_at
tasks.get
按以下方式读取单个任务 id 并返回扩展表示(包括 body 当它非空时)。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID(也是没有的文件名 .md),必须匹配 ^[A-Z0-9-]+$
- 输出:
{ ok: true, data: TaskDetails } TaskDetails:
- id, project, type, title, status, created_at - started_at?, done_at?, canceled_at?, tool?, body?
tasks.report
时间范围报告:计数 done_count 通过 done_at 在...之内 [from, to] (含)及 remaining_count 状态不在的任务数量 {done, canceled}.
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - from (字符串):带UTC偏移的ISO-8601时间戳 - to (字符串):带UTC偏移的ISO-8601时间戳
- 输出:
{ ok: true, data: { done_count: number, remaining_count: number } }
tasks.history
以结构化形式返回任务文件的Git历史记录。
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$
- 输出:
{ ok: true, data: { commits: GitCommit[] } } GitCommit:
- hash, author, date, subject
tasks.rollback
将任务文件回滚到指定的Git版本,并创建一个单独的提交,如 rollback to .
- 输入:
- project (string):必须匹配 ^[a-z0-9-]+$ 目录必须存在 - id (string):任务ID,必须匹配 ^[A-Z0-9-]+$ - revision (string):git修订(哈希/分支/标签)
- 输出:
{ ok: true, data: TaskView }
tasks.verify
检查项目和任务的完整性,并返回违规列表。只读:不修改存储库,也不创建Git提交。
- 输入:
- project (string):项目名称(可能无效;在这种情况下,将返回违规)
- 输出:
{ ok: true, data: { violations: Violation[] } } Violation:
- code, message, details?
已实施的工具
服务器实现了中列出的所有工具 tools/list,包括:
projects.listtasks.createtasks.gettasks.updatetasks.promote_to_todotasks.claimtasks.donetasks.releasetasks.canceltasks.listtasks.reporttasks.historytasks.rollbacktasks.verifytasks.template
