MCP GitHub应用服务器
一个轻量级的MCP(模型上下文协议)服务器,使用GitHub App身份验证而不是个人访问令牌提供GitHub操作。
目录
- - 测试服务器
先决条件
- 安装了GitHub应用程序,具有内容(读写)和拉取请求(读写”)的存储库权限
- 所需的环境变量:
- GITHUB_APP_ID -您的GitHub应用程序ID - GITHUB_PRIVATE_KEY -您的GitHub应用程序私钥(PEM格式) - GITHUB_INSTALLATION_ID -您的GitHub应用程序安装ID
工具
服务器实现了标准的MCP协议,并提供了一个工具:
get_token:使用GitHub App身份验证获取用于访问私有存储库的临时GitHub令牌
- 参数: - owner (string,必填):GitHub存储库所有者/组织 - repo (string,必填):GitHub存储库名称 - 返回:一个临时的GitHub令牌(有效期约为1小时),可用于Git命令和GitHub REST API调用
是什么 get_token?
这 get_token 该工具生成一个临时的GitHub身份验证令牌,可用于各种Git操作和GitHub API调用。这不仅仅是用于克隆-令牌可用于:
Git操作:
- 克隆:克隆私有存储库
- git推送:将提交推送到远程存储库
- 拉取:从远程存储库中提取更新
- git获取:获取远程分支和标签
- 任何其他需要身份验证的Git操作
GitHub REST API操作:
- 创建/管理问题:创建、更新、评论问题
- 拉取请求:创建、审核、合并拉取请求
- 存储库管理:列出内容、下载文件、获取存储库信息
- 发布:创建和管理发布
- 任何GitHub REST API端点:令牌可用于所有经过身份验证的API操作
令牌格式:
对于Git操作,请在URL中使用标记:
https://x-access-token:@github.com//.git对于GitHub REST API操作,请使用授权标头中的令牌:
Authorization: Bearer 代理商注意事项:
- 令牌是临时的,大约1小时后到期
- 该令牌可用于任何需要身份验证的Git操作(克隆、推送、拉取、获取等)
- 该令牌还可用于ANY GitHub REST API操作(创建问题、PR、管理转发等)
- 你不需要打电话
get_token每个操作单独使用-一个令牌适用于所有Git和API操作 - 如果操作失败并出现身份验证错误,则令牌可能已过期-只需调用
get_token再次获得新的代币
此服务器本身不执行Git操作,但提供临时GitHub令牌供标准Git命令使用。
安装
pip install .用法
Docker使用
从GitHub容器注册表中提取预构建映像:
docker pull ghcr.io/legido-ai/mcp-github-app-auth:latest对于ARM主机,您可以使用显式的ARM标签:
docker pull ghcr.io/legido-ai/mcp-github-app-auth:arm或者从源代码本地构建:
docker build . -t mcp-github-app-auth测试服务器
此服务器实现了模型上下文协议(MCP),该协议要求在执行任何操作之前进行适当的初始化握手。未初始化的直接JSON-RPC请求将被拒绝。
直接JSON-RPC命令与初始化
要测试服务器,您必须手动发送完整的初始化序列:
- 获取工具:
(
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "manual-test", "version": "1.0"}}}'; \
echo '{"jsonrpc": "2.0", "method": "notifications/initialized"}'; \
echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}'
) | docker run -i --rm \
-e GITHUB_APP_ID="$GITHUB_APP_ID" \
-e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
-e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
ghcr.io/legido-ai/mcp-github-app-auth- 得到一个令牌。在这个例子中,我们想为私有Github存储库获取一个令牌https://github.com/my-org/my-private-repo:
(
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "manual-test", "version": "1.0"}}}'; \
echo '{"jsonrpc": "2.0", "method": "notifications/initialized"}'; \
echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "my-org", "repo": "my-private-repo"}}}'
) | docker run -i --rm \
-e GITHUB_APP_ID="$GITHUB_APP_ID" \
-e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
-e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
ghcr.io/legido-ai/mcp-github-app-auth与MCP客户端一起使用:
该服务器旨在与MCP兼容的客户端一起使用,例如:
- 克劳德桌面/代码
- 谷歌Gemini CLI
- 其他与MCP兼容的AI助手
有关设置说明,请参阅下面的集成部分。
直接JSON-RPC测试注意事项:
MCP在接受请求之前需要一个三步初始化序列:
- 客户端发送
initialize请求协议版本和功能 - 服务器以其功能进行响应
- 客户端发送
initialized通知 - 只有这样,客户端才能发送以下请求
tools/list或tools/call
为什么没有初始化的直接命令不起作用:
简单的echo命令绕过初始化序列,并将失败:
WARNING:root:Failed to validate request: Received request before initialization was complete这是 正确的MCP协议行为上述命令包括协议所需的完整初始化序列。
使用令牌进行Git操作
一旦你有了令牌,你就可以将其用于各种Git操作:
克隆存储库:
git clone https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git克隆特定分支:
git clone -b feature-branch https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git推送到存储库:
cd private-repo
# Make some changes
git add .
git commit -m "Update files"
git push https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git main拉取更新:
git pull https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git main获取远程分支:
git fetch https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git设置为远程URL:
git remote set-url origin https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git
# Now you can use regular git push/pull commands
git push origin main使用代币进行GitHub API操作
该令牌还可以与GitHub的REST API一起用于Git命令之外的各种操作:
创建问题:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/issues \
-d '{"title":"Found a bug","body":"Description of the issue","labels":["bug"]}'创建拉取请求:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/pulls \
-d '{"title":"Amazing new feature","body":"Please pull these changes","head":"feature-branch","base":"main"}'向问题添加评论:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/issues/1/comments \
-d '{"body":"This is a comment on the issue"}'列出存储库内容:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/contents/path/to/directory从私有存储库下载文件:
curl -H "Authorization: Bearer ghs_tokenhere" \
-H "Accept: application/vnd.github.v3.raw" \
-o downloaded-file.txt \
-L https://api.github.com/repos/fictional-org/private-repo/contents/path/to/file.txt获取存储库信息:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo列出拉取请求:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/pulls创建发布:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghs_tokenhere" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/fictional-org/private-repo/releases \
-d '{"tag_name":"v1.0.0","name":"Release v1.0.0","body":"Description of the release"}'端到端示例
示例1:克隆存储库
- 拉取预构建的图像:
docker pull ghcr.io/legido-ai/mcp-github-app-auth:latest- 获取GitHub令牌:
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
docker run -i --rm \
-e GITHUB_APP_ID="$GITHUB_APP_ID" \
-e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
-e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
ghcr.io/legido-ai/mcp-github-app-auth:latest- 使用返回的令牌克隆存储库:
# Extract the token from the response (example shows ghs_tokenhere)
git clone https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git示例2:克隆、修改和推送
- 获取GitHub令牌:
TOKEN=$(echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
docker run -i --rm \
-e GITHUB_APP_ID="$GITHUB_APP_ID" \
-e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
-e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
ghcr.io/legido-ai/mcp-github-app-auth:latest | \
jq -r '.result.content[0].text' | grep -oP 'ghs_\w+')- 克隆存储库:
git clone https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git
cd private-repo- 进行更改并推送:
echo "# New content" >> README.md
git add README.md
git commit -m "Update README"
git push https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git main示例3:使用具有多个操作的令牌
# Get token
TOKEN=$(echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
docker run -i --rm \
-e GITHUB_APP_ID="$GITHUB_APP_ID" \
-e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
-e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
ghcr.io/legido-ai/mcp-github-app-auth:latest | \
jq -r '.result.content[0].text' | grep -oP 'ghs_\w+')
# Clone repository
git clone https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git
cd private-repo
# Set remote URL with token for subsequent operations
git remote set-url origin https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git
# Now you can use regular git commands
git pull origin main
git push origin main
git fetch --all与Claude Desktop集成
⚠️ 关键:可变膨胀不起作用
Claude Desktop/Code不支持在配置文件中扩展环境变量。
这是克劳德配置系统的一个基本局限性。如果你尝试使用以下变量 $GITHUB_APP_ID克劳德会把他们当作 字面字符串,而不是作为对环境变量的引用。
这意味着:
- ❌
GITHUB_APP_ID=$GITHUB_APP_ID→ Claude传递文字字符串"$GITHUB_APP_ID"Docker - ❌ 这会导致身份验证失败,并出现“无法解析提供的公钥”等错误
- ❌ MCP服务器收到无效凭据,无法在GitHub上进行身份验证
为什么会发生这种情况: Claude的JSON配置解析器不执行shell风格的变量替换。这 $VARIABLE 语法原封不动地传递给底层命令,导致Docker容器接收文字字符串而不是实际的凭据值。
❌ 此配置不起作用:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_APP_ID=$GITHUB_APP_ID", ← Passed as literal "$GITHUB_APP_ID"
"-e",
"GITHUB_PRIVATE_KEY=$GITHUB_PRIVATE_KEY", ← Passed as literal string
"-e",
"GITHUB_INSTALLATION_ID=$GITHUB_INSTALLATION_ID", ← Not expanded
"ghcr.io/legido-ai/mcp-github-app-auth:latest"
]
}
}
}
}
}结果: 身份验证失败,因为MCP接收的是文字字符串,而不是您的实际凭据。
选项1:手动配置(不推荐)
您可以手动编辑 ~/.claude.json 使用硬编码值,但这是 不推荐 出于安全原因:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_APP_ID=123456",
"-e",
"GITHUB_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\n...",
"-e",
"GITHUB_INSTALLATION_ID=78910",
"ghcr.io/legido-ai/mcp-github-app-auth:latest"
]
}
}
}
}
}✅ 选项2:自动设置脚本(推荐)
为什么你需要这个脚本:
由于Claude无法展开变量,您需要一个外部脚本来:
- 读取环境变量(
$GITHUB_APP_ID等等) - 提取其实际值
- 把这些文字值写进克劳德的
~/.claude.json配置文件
此脚本自动化了该过程,是 推荐解决方案 用于与Claude一起设置MCP服务器。
脚本:
此脚本可在 或者可以从下面复制:
#!/bin/bash
#
# Setup script for configuring GitHub MCP server in Claude Code
# This script properly expands environment variables when adding the MCP server configuration
#
set -e
echo "Configuring GitHub MCP server for Claude Code..."
# Check if required environment variables are set
if [ -z "$GITHUB_APP_ID" ] || [ -z "$GITHUB_INSTALLATION_ID" ] || [ -z "$GITHUB_PRIVATE_KEY" ]; then
echo "ERROR: Missing required environment variables!"
echo "Please ensure the following environment variables are set:"
echo " - GITHUB_APP_ID"
echo " - GITHUB_INSTALLATION_ID"
echo " - GITHUB_PRIVATE_KEY"
exit 1
fi
# Check if Python is available
if ! command -v python3 &> /dev/null; then
echo "ERROR: python3 is required but not found in PATH"
exit 1
fi
# Ensure .claude.json exists
if [ ! -f "$HOME/.claude.json" ]; then
echo "Creating $HOME/.claude.json..."
echo '{}' > "$HOME/.claude.json"
fi
# Use Python to safely update the JSON configuration with expanded environment variables
python3 " https://api.github.com/app/installations`
#### 如何手动测试配置
要在配置Claude之前验证您的设置是否有效:
1. Set environment variables
export GITHUB_APP_ID="your-app-id" export GITHUB_INSTALLATION_ID="your-installation-id" export GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----"
2. Test the MCP server directly
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "legido-ai", "repo": "tasks"}}}' | \ docker run -i --rm \ -e GITHUB_APP_ID="$GITHUB_APP_ID" \ -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \ -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \ ghcr.io/legido-ai/mcp-github-app-auth:latest
3. You should get a response with a token like:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"GitHub token for legido-ai/tasks: ghs_..."}]}}
如果这有效,则您的凭据是正确的,您可以继续进行Claude配置。
## 测试
### 使用Make(推荐)
make test-mcp-validation
这将运行Github MCP验证测试,该测试验证服务器是否正确响应了完整的MCP初始化握手,并给出了正确的JSON-RPC响应。
**注:** 测试需要设置以下环境变量:
- `GITHUB_APP_ID`
- `GITHUB_PRIVATE_KEY`
- `GITHUB_INSTALLATION_ID`
该测试会自动检测您的系统架构,并使用适当的Docker镜像标签(`arm` 对于aarch64, `latest` 对于其他架构)。
### 与docker openclaw集成
此测试作为docker openclaw的一部分自动执行 `full-test` 套房通过 `test-github-app-auth-mcp-validation` 目标。
### 使用pytest
使用以下工具运行单元测试:
python3 -m pytest tests/ -v
## 安全说明
- 安装令牌将在大约1小时后过期
- 服务器自动缓存和刷新令牌