内容
# gist-mcp: GitHub 代码片段 → MCP 服务器
将任何公共的 GitHub 代码片段转换为可立即使用的 MCP(模型上下文协议)服务器,轻松访问代码片段文件、元数据、修订历史和用户代码片段集合。
## 概述
**gist-mcp** 桥接了 GitHub 代码片段和模型上下文协议,使 Claude 和其他支持 MCP 的 AI 客户端能够:
- 获取代码片段元数据和文件清单
- 读取完整的文件内容(通过 GitHub 原始 URL 处理大文件)
- 列出用户的所有公共代码片段
- 按名称/模式搜索代码片段中的文件
- 访问代码片段修订历史和提交记录
- 以高效的分页方式批量处理多个代码片段
## 架构
```
┌─────────────────────────────────────────────────────────────┐
│ MCP 服务器(stdio) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 工具处理器(server.js) │ │
│ │ - 获取代码片段 → 元数据 + 文件清单 │ │
│ │ - 获取文件内容 → 原始文件内容 │ │
│ │ - 列出用户代码片段 → 用户的公共代码片段 │ │
│ │ - 搜索代码片段文件 → 文件名模式匹配 │ │
│ │ - 获取代码片段历史 → 提交日志 + 修订版本 │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ GitHub REST API 客户端(gistClient.js) │ │
│ │ - 解析代码片段引用() → 解析 ID/URL/所有者格式 │ │
│ │ - 获取代码片段() → GET /gists/{id} │ │
│ │ - 获取文件内容() → GET 原始文件 URL │ │
│ │ - 列出用户代码片段() → GET /users/{u}/gists │ │
│ │ - 获取代码片段提交() → GET /gists/{id}/commits │ │
│ │ - 错误类 → 未找到错误,速率限制错误 │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
└─────────────────────────────────────────────────────────────┘
│
↓
GitHub API(api.github.com)
┌────────────────────────────────┐
│ - 代码片段元数据(仅限公开) │
│ - 原始文件 URL │
│ - 用户代码片段列表 │
│ - 修订历史 │
└────────────────────────────────┘
```
### 数据流
1. **工具请求**(JSON-RPC via stdio)
- 客户端发送:`{ "method": "tools/call", "params": { "name": "fetch_gist", "arguments": {...} } }`
2. **参数验证**(Zod 模式)
- 模式:`FetchGistSchema`、`FetchFileContentSchema` 等
- 类型安全的解析,附带详细的错误信息
3. **引用解析**(gistClient.js)
- 接受:裸 ID、GitHub URL、所有者/ID 路径,附带可选 SHA
- 返回:标准化的 `{ gistId, owner, sha }`
4. **GitHub API 调用**(REST)
- 包括:GITHUB_TOKEN 认证(如果设置)、速率限制头部、适当的 User-Agent
- 错误处理:401(认证)、403/429(速率限制)、404(未找到)、5xx(服务器错误)
5. **响应组装**(JSON)
- 元数据以 JSON 形式返回,用于工具调用
- 文件内容以格式化文本块返回
- 所有响应都包含丰富上下文(语言、大小、时间戳等)
## 安装
### 前提条件
- Node.js >=18.0.0
- npm 或 yarn
### 设置
```bash
# 克隆或导航到存储库
cd gist-mcp
# 安装依赖项
npm install
# (可选)为更高的速率限制设置 GitHub 代币
export GITHUB_TOKEN="ghp_your_token_here"
# 启动 MCP 服务器
npm start
# 或使用自动重新加载的开发模式
npm run dev
```
## 使用
### 在 Claude.ai / 桌面版
在您的 Claude 配置中添加(`~/.claude/mcp.json` 或 Claude 桌面版 `claude_desktop_config.json`):
```json
{
"mcpServers": {
"gist": {
"command": "node",
"args": ["/path/to/gist-mcp/src/server.js"],
"env": {
"GITHUB_TOKEN": "ghp_your_token_here"
}
}
}
}
```
然后在 Claude 中,询问:
```
获取代码片段 "https://gist.github.com/owner/aa5a315d61ae9438b18d"
并显示文件列表和元数据。
```
或
```
获取用户 "torvalds" 的所有公共代码片段并总结它们。
```
### 以编程方式
```javascript
import { parseGistRef, fetchGist, fetchFileContent } from "./src/gistClient.js";
// 解析引用
const ref = parseGistRef("https://gist.github.com/owner/aa5a315d61ae9438b18d");
// → { gistId: "aa5a315d61ae9438b18d", owner: "owner", sha: null }
// 获取代码片段元数据
const gist = await fetchGist(ref.gistId);
console.log(gist.files); // { "example.js": { ... }, ... }
// 获取文件内容
const file = gist.files["example.js"];
const content = await fetchFileContent(file);
console.log(content);
```
## 工具参考
### `获取代码片段`
获取包含文件清单的完整代码片段元数据。
**参数:**
- `代码片段`(字符串,必填):代码片段引用(ID、URL 或所有者/ID)
- `sha`(字符串,可选):特定的修订 SHA
**返回:**
```json
{
"id": "aa5a315d61ae9438b18d",
"description": "有用的脚本",
"owner": "torvalds",
"public": true,
"created_at": "2023-10-15T12:34:56Z",
"updated_at": "2024-01-20T08:22:10Z",
"comments": 3,
"file_count": 2,
"files": [
{
"filename": "example.js",
"language": "JavaScript",
"size": 1024,
"truncated": false,
"type": "text/plain"
}
]
}
```
### `获取文件内容`
检索原始文件内容。对于大文件,自动从 GitHub 原始 URL 获取。
**参数:**
- `代码片段`(字符串,必填):代码片段引用
- `文件名`(字符串,必填):代码片段中的文件名
**返回:** 文件内容作为文本,附带语言提示
### `列出用户代码片段`
列出 GitHub 用户的公共代码片段。分页(默认 3 页 = ~300 代码片段)。
**参数:**
- `用户名`(字符串,必填):GitHub 用户名
- `最大页数`(数字,可选):要获取的页数(1-10,默认:3)
**返回:**
```json
[
{
"id": "aa5a315d61ae9438b18d",
"description": "我的脚本",
"file_count": 2,
"updated_at": "2024-01-20T08:22:10Z",
"html_url": "https://gist.github.com/..."
}
]
```
### `搜索代码片段文件`
按名称/模式搜索代码片段中的文件(不区分大小写)。
**参数:**
- `代码片段`(字符串,必填):代码片段引用
- `模式`(字符串,必填):文件名模式(正则表达式)
**返回:**
```json
{
"pattern": "*.js",
"matches": 2,
"files": [
{
"filename": "example.js",
"language": "JavaScript",
"size": 1024
}
]
}
```
### `获取代码片段历史`
获取代码片段的修订历史和提交日志。
**参数:**
- `代码片段`(字符串,必填):代码片段引用
**返回:**
```json
{
"gist_id": "aa5a315d61ae9438b18d",
"total_commits": 5,
"commits": [
{
"version": "v1",
"user": "owner",
"committed_at": "2024-01-20T08:22:10Z",
"change_status": "modified"
}
]
}
```
## 代码片段引用格式
所有工具都接受多种格式的代码片段引用:
| 格式 | 示例 | 解析 |
|--------|---------|--------|
| 裸 ID | `aa5a315d61ae9438b18d` | `{ gistId: "aa5a315d61ae9438b18d", owner: null, sha: null }` |
| GitHub URL | `https://gist.github.com/owner/aa5a315d61ae9438b18d` | `{ gistId: "aa5a315d61ae9438b18d", owner: "owner", sha: null }` |
| 所有者/ID | `owner/aa5a315d61ae9438b18d` | `{ gistId: "aa5a315d61ae9438b18d", owner: "owner", sha: null }` |
| 带有 SHA | `aa5a315d61ae9438b18d/abc123` | `{ gistId: "aa5a315d61ae9438b18d", owner: null, sha: "abc123" }` |
## 认证
### GitHub 代币(推荐)
设置 `GITHUB_TOKEN` 环境变量以增加速率限制并访问您拥有的私有代码片段:
```bash
export GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
node src/server.js
```
**速率限制:**
- 无令牌:60 请求/小时
- 有令牌:5,000 请求/小时
### 获取令牌
1. 前往 https://github.com/settings/tokens
2. 点击 "生成新令牌(经典)"
3. 选择作用域:`gist`(最小)
4. 复制令牌并设置 `GITHUB_TOKEN` 环境变量
## 错误处理
### 错误类
**未找到错误** – 代码片段或文件不存在(404)
```
未找到:GET /gists/invalid_id
```
**速率限制错误** – GitHub API 速率限制超过(403/429)
```
GitHub API 速率限制(remaining=0, resets=2024-01-20T09:15:00Z)。设置 GITHUB_TOKEN 以提高限制。
```
**认证错误** – 无效或过期的令牌(401)
```
无效或过期的 GitHub 令牌。设置 GITHUB_TOKEN 环境变量。
```
### 恢复策略
- **速率限制**:等待重置时间或设置 GITHUB_TOKEN
- **未找到**:验证代码片段是否为公共(私有代码片段需要认证)
- **网络错误**:使用指数退避重试
- **截断的文件**:`fetch_file_content` 自动处理大文件
## 性能
### 特性
- **获取代码片段元数据**:~100-300ms(取决于网络)
- **获取文件内容**:~50-200ms 用于典型文件,~1-3s 用于大文件(>10MB)
- **列出用户代码片段**:~100-400ms 每页
- **GitHub 速率限制**:有令牌时为 5,000/小时,无令牌时为 60/小时
### 优化
- 使用 `GITHUB_TOKEN` 将速率限制提高 83 倍(5000 vs 60 每小时)
- 在单个 `fetch_gist` 调用中批量读取多个文件(返回所有元数据)
- 缓存代码片段元数据以避免冗余 API 调用
- 使用 `maxPages` 参数限制分页
## API 合规性
### GitHub REST API
- **端点**:https://api.github.com/gists/...
- **版本**:2022-11-28
- **文档**:https://docs.github.com/en/rest/gists/gists
### MCP 协议
- **传输**:stdio(JSON-RPC 2.0)
- **版本**:支持最新的 MCP SDK(@modelcontextprotocol/sdk)
- **规范**:https://modelcontextprotocol.io
## 开发
### 项目结构
```
gist-mcp/
├── src/
│ ├── server.js # MCP 服务器 + 工具处理器
│ └── gistClient.js # GitHub API 客户端
├── package.json
├── README.md
├── ARCHITECTURE.md
├── CONFIG.md
├── QUICKSTART.md
├── INDEX.md
├── PROJECT_SUMMARY.md
├── LICENSE
├── .env.example
└── .gitignore
```
### 关键设计决策
1. **ES 模块** – Node.js `"type": "module"` 用于现代语法
2. **Zod 验证** – 运行时类型安全,用于工具参数
3. **错误恢复** – 带有上下文的 API 错误的优雅处理
4. **分页** – 安全的默认值(3 页)以避免速率限制
5. **文件流式传输** – `fetch_file_content` 通过原始 URL 流式传输大文件
6. **无状态** – 无状态服务器(可扩展、可缓存、可重现)
### 测试
```bash
# 手动测试(需要 GITHUB_TOKEN)
node -e "
import { parseGistRef, fetchGist } from './src/gistClient.js';
const ref = parseGistRef('https://gist.github.com/torvalds/de11361daae787ff5441');
const gist = await fetchGist(ref.gistId);
console.log(gist);
"
```
## 故障排除
### "速率限制超过"
→ 设置 `GITHUB_TOKEN` 环境变量
### "代码片段未找到"
→ 验证代码片段 URL 是否为公共(https://gist.github.com/...)且有效
### "GITHUB_TOKEN 被拒绝"
→ 令牌已过期或被撤销。在 https://github.com/settings/tokens 生成新令牌
### "文件截断"
→ `fetch_file_content` 自动处理截断。如果仍然为空,文件可能超过 GitHub 原始 URL 大小限制(非常罕见)。
### "连接超时"
→ GitHub API 可能很慢。重试并退避,或检查 https://www.githubstatus.com
## 贡献
欢迎贡献:
1. 增强代码片段客户端(额外的 GitHub API 方法)
2. 添加新的 MCP 工具(例如,代码片段统计,内容搜索)
3. 改进错误消息和恢复
4. 性能优化
5. 文档改进
## 许可证
MIT – 请参阅 LICENSE 文件
## 资源
- [模型上下文协议](https://modelcontextprotocol.io)
- [GitHub 代码片段 API](https://docs.github.com/en/rest/gists/gists)
- [GitHub REST API 文档](https://docs.github.com/en/rest)
- [Gist.github.com](https://gist.github.com)