GitHub项目MCP服务器
一个模型上下文协议(MCP)服务器,用于自动化GitHub Projects v2工作流——以编程方式创建项目、里程碑、问题和迭代。
适用于: Claude Desktop(桌面应用程序)和Claude Code(VS Code扩展)
特性
- ✅ 创建项目:设置新的GitHub Projects v2板
- ✅ 创建里程碑:将工作组织成里程碑
- ✅ 创建问题:批量创建里程碑和标签问题
- ✅ 添加到项目:自动将问题添加到项目板
- ✅ 迭代字段:创建每周/冲刺迭代字段
- ✅ 添加/更新迭代:向现有字段添加新迭代或更新现有字段
- ✅ 分配迭代:在冲刺阶段分配问题
- ✅ 子问题管理:添加、删除和重新确定子问题的优先级
- ✅ 更新状态:使用人类可读值更改项目项状态
- ✅ 项目状态更新:添加和检索项目级状态更新(按计划、有风险等)
- ✅ 更新项目:修改项目设置,如标题、描述和可见性
- ✅ 显示简介:检索存储库和项目元数据
安装
先决条件
- Node.js 20+
- 选项A: GitHub个人访问令牌(PAT)
repo和project范围 - 选项B: 启用了设备流的GitHub OAuth应用程序(自动刷新令牌)
快速入门(推荐)
使用 npx 无需安装即可直接运行服务器:
npx -y @joaodotwork/plantas-github-projects-mcp安装为全局npm包
npm install -g @joaodotwork/plantas-github-projects-mcp从源代码构建(开发)
git clone https://github.com/joaodotwork/plantas-github-projects-mcp.git
cd plants-github-projects-mcp
npm install
npm run build配置
认证
服务器支持两种身份验证方法:
选项A:个人访问令牌(最简单)
export GITHUB_TOKEN=ghp_your_token_here选项B:OAuth设备流(推荐)
使用GitHub OAuth应用程序,自动刷新存储在加密本地存储中的令牌。无需手动管理令牌。
export GITHUB_CLIENT_ID=your_oauth_app_client_id
export GITHUB_CLIENT_SECRET=your_oauth_app_client_secret在第一次调用工具时,服务器将提示您通过浏览器进行授权。身份验证被推迟到需要时,因此服务器会立即启动——在Claude Code或其他MCP主机中没有超时的风险。令牌以加密方式存储在 ~/.config/github-projects-mcp/credentials.enc 并自动刷新。
配置Claude
对于Claude Code(CLI):
# With PAT
claude mcp add github-projects --env GITHUB_TOKEN=ghp_your_token_here -- npx -y @joaodotwork/plantas-github-projects-mcp
# With OAuth
claude mcp add github-projects \
--env GITHUB_CLIENT_ID=your_client_id \
--env GITHUB_CLIENT_SECRET=your_client_secret \
-- npx -y @joaodotwork/plantas-github-projects-mcp对于Gemini CLI:
gemini mcp add github-projects npx -e GITHUB_TOKEN=ghp_your_token_here -- -y @joaodotwork/plantas-github-projects-mcp对于Claude Desktop: 添加 ~/Library/Application Support/Claude/claude_desktop_config.json
看 安装.md 了解详细的平台特定说明。
{
"mcpServers": {
"github-projects": {
"command": "npx",
"args": ["-y", "@joaodotwork/plantas-github-projects-mcp"],
"env": {
"GITHUB_TOKEN": "ghp_your_token_here"
}
}
}
}3.重新启动
克劳德桌面: 完全退出并重新打开应用程序
克劳德代码: 重新加载VS代码窗口(Cmd+Shift+P→ “开发人员:重新加载窗口”)
可用工具
create_project
创建一个新的GitHub Projects v2板。
参数:
owner(string,必填):GitHub用户名或组织title(字符串,必填):项目标题description(字符串,可选):项目描述
例子:
{
"owner": "joaodotwork",
"title": "v1.0 Production Release",
"description": "Sprint to ship v1.0"
}退货:
{
"id": "PVT_kwHOAwJiCM4BNC20",
"number": 7,
"title": "v1.0 Production Release",
"url": "https://github.com/users/joaodotwork/projects/7"
}______________________________________________________________________
create_milestone
在存储库中创建里程碑。
参数:
owner(字符串,必填):存储库所有者repo(字符串,必填):存储库名称title(字符串,必填):里程碑标题description(字符串,可选):里程碑描述dueOn(字符串,可选):ISO 8601格式的到期日期
例子:
{
"owner": "joaodotwork",
"repo": "dpds-arkiv",
"title": "Epic 1: GitHub Metadata Workflow",
"description": "Automate GitHub Projects sync (1 issue)"
}退货:
{
"id": "MI_kwDOPxqaGM4A3o8i",
"number": 4,
"title": "Epic 1: GitHub Metadata Workflow",
"url": "https://github.com/joaodotwork/dpds-arkiv/milestone/4"
}______________________________________________________________________
create_issue
使用可选的里程碑、标签和指定人员创建问题。
参数:
owner(字符串,必填):存储库所有者repo(字符串,必填):存储库名称title(字符串,必填):发行标题body(string,必填):问题正文(markdown)milestoneNumber(数字,可选):里程碑编号labelIds(string\[\],可选):标签ID数组assignees(string\[\],可选):用户名数组
例子:
{
"owner": "joaodotwork",
"repo": "dpds-arkiv",
"title": "Implement GitHub Projects Sync Workflow",
"body": "**Epic:** GitHub Metadata Workflow\n...",
"milestoneNumber": 4,
"labelIds": ["LA_kwDOPxqaGM8AAAACVcj5iQ"],
"assignees": ["joaodotwork"]
}退货:
{
"id": "I_kwDOPxqaGM6RkGzw",
"number": 80,
"title": "Implement GitHub Projects Sync Workflow",
"url": "https://github.com/joaodotwork/dpds-arkiv/issues/80"
}______________________________________________________________________
add_issue_to_project
在Projects v2板上添加一个问题。
参数:
projectId(字符串,必填):项目节点IDissueId(字符串,必填):问题节点ID
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"issueId": "I_kwDOPxqaGM6RkGzw"
}退货:
{
"id": "PVTI_lAHOAwJiCM4BNC20zgXYZ..."
}______________________________________________________________________
create_iteration_field
创建一个包含每周冲刺的迭代字段。
参数:
projectId(字符串,必填):项目节点IDfieldName(字符串,必填):字段名称(例如“Sprint”)duration(数字,必填):持续时间(通常为7天)startDate(字符串,必填):开始日期(YYYY-MM-DD)iterations(array,必填):迭代定义数组
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"fieldName": "Sprint",
"duration": 7,
"startDate": "2026-01-20",
"iterations": [
{ "title": "Week 1", "startDate": "2026-01-20", "duration": 7 },
{ "title": "Week 2", "startDate": "2026-01-27", "duration": 7 },
{ "title": "Week 3", "startDate": "2026-02-03", "duration": 7 }
]
}退货:
{
"id": "PVTIF_lAHOAwJiCM4BNC20zg8J544",
"name": "Sprint",
"configuration": {
"iterations": [
{
"id": "bab3ba50",
"title": "Week 1",
"startDate": "2026-01-20",
"duration": 7
},
...
]
}
}______________________________________________________________________
assign_issue_to_iteration
将问题分配给特定的迭代。
参数:
owner(字符串,必填):存储库所有者repo(字符串,必填):存储库名称projectNumber(数字,必填):项目编号issueNumber(数字,必填):发行号fieldId(字符串,必填):迭代字段IDiterationId(字符串,必填):迭代ID
例子:
{
"owner": "joaodotwork",
"repo": "dpds-arkiv",
"projectNumber": 7,
"issueNumber": 80,
"fieldId": "PVTIF_lAHOAwJiCM4BNC20zg8J544",
"iterationId": "bab3ba50"
}______________________________________________________________________
add_iteration
向现有迭代字段添加新迭代。
参数:
projectId(字符串,必填):项目节点IDfieldId(字符串,必填):迭代字段IDtitle(字符串,必填):迭代标题(例如“Sprint 5”)startDate(字符串,必填):开始日期(YYYY-MM-DD)duration(数字,必填):持续时间(通常为7或14天)
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"fieldId": "PVTIF_lAHOAwJiCM4BNC20zg8J544",
"title": "Phase 4: Production hardening",
"startDate": "2026-02-10",
"duration": 14
}______________________________________________________________________
update_iteration
更新现有迭代的标题、开始日期或持续时间。
参数:
projectId(字符串,必填):项目节点IDfieldId(字符串,必填):迭代字段IDiterationId(字符串,必填):要更新的迭代IDtitle(字符串,可选):新标题startDate(字符串,可选):新开始日期(YYYY-MM-DD)duration(数字,可选):新的持续时间(以天为单位)
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"fieldId": "PVTIF_lAHOAwJiCM4BNC20zg8J544",
"iterationId": "bab3ba50",
"title": "Sprint 3 (extended)",
"duration": 14
}______________________________________________________________________
add_subissue
将子问题添加到父问题中。
参数:
issueId(字符串,必填):父问题的节点IDsubIssueId(字符串,可选):子问题的节点IDsubIssueUrl(字符串,可选):子问题的URLreplaceParent(布尔值,可选):如果父问题已存在,则替换父问题
例子:
{
"issueId": "I_kwDOPxqaGM6RkGzw",
"subIssueId": "I_kwDOPxqaGM6RkHAB"
}退货:
{
"success": true,
"message": "Sub-issue added successfully"
}______________________________________________________________________
remove_subissue
从父问题中删除子问题。
参数:
issueId(字符串,必填):父问题的节点IDsubIssueId(string,必填):要删除的子问题的节点ID
例子:
{
"issueId": "I_kwDOPxqaGM6RkGzw",
"subIssueId": "I_kwDOPxqaGM6RkHAB"
}退货:
{
"success": true,
"message": "Sub-issue removed successfully"
}______________________________________________________________________
reprioritize_subissue
在父问题中重新排列子问题的优先级。
参数:
issueId(字符串,必填):父问题的节点IDsubIssueId(字符串,必填):要重新确定优先级的子问题的节点IDafterId(字符串,可选):要优先处理的子问题的IDbeforeId(字符串,可选):要优先处理的子问题的ID
注: 指定其中之一 afterId 或 beforeId不是两者都有。
例子:
{
"issueId": "I_kwDOPxqaGM6RkGzw",
"subIssueId": "I_kwDOPxqaGM6RkHAB",
"afterId": "I_kwDOPxqaGM6RkHCD"
}退货:
{
"success": true,
"message": "Sub-issue reprioritized successfully"
}______________________________________________________________________
update_item_status
使用人类可读的状态值更新项目项的状态。
参数:
projectId(字符串,必填):项目节点IDitemId(字符串,必填):项目项节点IDstatus(字符串,必填):人类可读状态(例如,“待办”、“进行中”、“完成”)
注: 该工具会自动查找状态字段并匹配状态名称(不区分大小写)。如果未找到状态,它将显示可用选项。
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"itemId": "PVTI_lAHOAwJiCM4BNC20zgXYZ...",
"status": "In Progress"
}退货:
{
"success": true,
"message": "Status updated to 'In Progress'",
"itemId": "PVTI_lAHOAwJiCM4BNC20zgXYZ..."
}______________________________________________________________________
update_project_settings
更新项目设置,如标题、描述、README或可见性。
参数:
projectId(字符串,必填):项目节点IDtitle(字符串,可选):新项目标题shortDescription(字符串,可选):新的简短描述readme(字符串,可选):新的README内容(markdown)public(布尔值,可选):设置项目可见性(true=公共,false=私有)
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"title": "Q1 2025 Product Launch",
"shortDescription": "Sprint planning for v2.0 release",
"public": true
}退货:
{
"success": true,
"message": "Project settings updated successfully",
"project": {
"id": "PVT_kwHOAwJiCM4BNC20",
"title": "Q1 2025 Product Launch",
"shortDescription": "Sprint planning for v2.0 release",
"public": true,
"url": "https://github.com/users/joaodotwork/projects/7"
}
}______________________________________________________________________
get_repository_info
获取存储库ID、标签和里程碑。
参数:
owner(字符串,必填):存储库所有者repo(字符串,必填):存储库名称
例子:
{
"owner": "joaodotwork",
"repo": "dpds-arkiv"
}退货:
{
"id": "R_kgDOPxqaGA",
"name": "dpds-arkiv",
"labels": {
"nodes": [
{ "id": "LA_kwDOPxqaGM8...", "name": "priority:high" },
...
]
},
"milestones": {
"nodes": [
{ "id": "MI_kwDOPxqaGM4...", "number": 4, "title": "Epic 1..." },
...
]
}
}______________________________________________________________________
get_project_info
获取项目ID、字段和迭代ID。
参数:
owner(string,必填):项目负责人projectNumber(数字,必填):项目编号
例子:
{
"owner": "joaodotwork",
"projectNumber": 7
}退货:
{
"id": "PVT_kwHOAwJiCM4BNC20",
"title": "v1.0 Production Release",
"number": 7,
"fields": {
"nodes": [
{
"id": "PVTIF_lAHOAwJiCM4BNC20zg8J544",
"name": "Sprint",
"dataType": "ITERATION",
"configuration": {
"iterations": [...]
}
},
...
]
}
}create_project_status_update
为项目板创建状态更新。
参数:
projectId(字符串,必填):项目节点IDstatus(string,必填):状态级别(INACTIVE,ON_TRACK,AT_RISK,OFF_TRACK,COMPLETE)body(字符串,可选):状态更新正文(markdown)startDate(字符串,可选):开始日期(YYYY-MM-DD)targetDate(字符串,可选):目标日期(YYYY-MM-DD)
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"status": "ON_TRACK",
"body": "Project is proceeding as planned. All milestones for this week are met."
}______________________________________________________________________
get_project_status_updates
获取项目的最新状态更新。
参数:
projectId(字符串,必填):项目节点IDlimit(number,可选):要检索的更新数(默认值:5)
例子:
{
"projectId": "PVT_kwHOAwJiCM4BNC20",
"limit": 3
}用法示例
示例1:创建完整的Sprint设置
// 1. Create project
const project = await create_project({
owner: "joaodotwork",
title: "v1.0 Production Release",
description: "Sprint to ship v1.0"
});
// 2. Create milestones
const milestone1 = await create_milestone({
owner: "joaodotwork",
repo: "dpds-arkiv",
title: "Epic 1: GitHub Metadata Workflow",
description: "Automate GitHub Projects sync (1 issue)"
});
// 3. Get repository info (for label IDs)
const repoInfo = await get_repository_info({
owner: "joaodotwork",
repo: "dpds-arkiv"
});
// 4. Create issue
const issue = await create_issue({
owner: "joaodotwork",
repo: "dpds-arkiv",
title: "Implement GitHub Projects Sync Workflow",
body: "...",
milestoneNumber: milestone1.number,
labelIds: [repoInfo.labels.nodes[0].id],
assignees: ["joaodotwork"]
});
// 5. Add issue to project
await add_issue_to_project({
projectId: project.id,
issueId: issue.id
});
// 6. Create iteration field
const iterationField = await create_iteration_field({
projectId: project.id,
fieldName: "Sprint",
duration: 7,
startDate: "2026-01-20",
iterations: [
{ title: "Week 1", startDate: "2026-01-20", duration: 7 },
{ title: "Week 2", startDate: "2026-01-27", duration: 7 },
{ title: "Week 3", startDate: "2026-02-03", duration: 7 }
]
});
// 7. Assign issue to iteration
await assign_issue_to_iteration({
owner: "joaodotwork",
repo: "dpds-arkiv",
projectNumber: project.number,
issueNumber: issue.number,
fieldId: iterationField.id,
iterationId: iterationField.configuration.iterations[0].id
});示例2:批量创建问题
const issues = [
{
title: "Issue 1",
body: "Description...",
milestoneNumber: 4
},
{
title: "Issue 2",
body: "Description...",
milestoneNumber: 5
}
];
for (const issueData of issues) {
const issue = await create_issue({
owner: "joaodotwork",
repo: "dpds-arkiv",
...issueData
});
await add_issue_to_project({
projectId: "PVT_kwHOAwJiCM4BNC20",
issueId: issue.id
});
}故障排除
“401未经授权”错误
- PAT用户: 检查一下
GITHUB_TOKEN已正确设置并具有repo和project范围 - OAuth用户: 您的令牌可能已过期。重新启动MCP服务器以触发刷新或重新身份验证
- 服务器在第一次工具调用时验证令牌,并提供可操作的错误消息
“在项目中找不到问题”错误
- 确保首先使用以下命令将问题添加到项目中
add_issue_to_project - 验证
projectNumber是正确的
MCP服务器未加载
- 检查Claude Desktop配置文件路径
- 验证配置文件中的JSON语法
- 完全重新启动克劳德桌面
- 检查日志:
~/Library/Logs/Claude/mcp*.log
发展
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run dev
# Test locally
node dist/index.js许可证
麻省理工学院
作者
João Doria de Souza 的@joaodowork)
______________________________________________________________________
使用MCP SDK构建 -Claude桌面模型上下文协议
