使用说明
Basecamp MCP服务器
MCP(模型上下文协议)服务器,将Basecamp 3项目管理操作作为工具公开。这允许像克劳德这样的人工智能助手与Basecamp进行交互——列出项目、管理待办事项、阅读/发布消息等等。
用Ruby、Sinatra和 主控程序 gem使用流式HTTP传输。
先决条件
- Ruby 3.2+
- 打包机
- 带有API访问令牌的Basecamp 3帐户
设置
git clone https://github.com/k0va1/basecamp-mcp.git && cd basecamp-mcp
make install
cp .env.example .env
编辑 .env 使用您的Basecamp证书:
BASECAMP_ACCESS_TOKEN=your_access_token_here
BASECAMP_ACCOUNT_ID=your_account_id_here
MCP_AUTH_TOKEN=optional_secret_token
您可以通过以下方式获得访问令牌 Basecamp的OAuth 2流程 或者通过创建个人整合。
认证
集 MCP_AUTH_TOKEN 要求所有MCP请求上都有承载令牌。设置后,客户端必须包含 Authorization: Bearer <token> 头球未设置时,MCP端点打开(适用于本地开发)。
OAuth2授权流
要通过浏览器进行身份验证而不是手动获取令牌,请将您的OAuth2凭据添加到 .env:
BASECAMP_CLIENT_ID=your_oauth_client_id
BASECAMP_CLIENT_SECRET=your_oauth_client_secret
BASECAMP_REDIRECT_URI=http://localhost:9292/oauth/callback
然后访问 http://localhost:9292/oauth/authorize 在您的浏览器中。使用37signals授权后,令牌会自动保存。
设置OAuth凭据后,服务器还会:
- 将令牌持久化
.basecamp_tokens.json(自动识别) - 在到期前5分钟主动刷新令牌
- 使用401错误的新令牌检索请求
如果未设置这些变量,服务器将使用静态 BASECAMP_ACCESS_TOKEN.
跑步
bundle exec rackup
服务器启动于 http://localhost:9292 默认情况下。
- MCP端点:
POST /--处理所有MCP协议消息 - 健康检查:
GET /health--退货{"status":"ok"} - OAuth授权:
GET /oauth/authorize--启动OAuth2流 - OAuth回调:
GET /oauth/callback--处理OAuth2重定向
集 DEBUG=1 以启用MCP和Basecamp API调用的请求/响应日志记录。
工具
项目
| 工具 | 说明 |
|---|---|
list_projects |
列出所有活动项目 |
get_project |
获取特定项目的详细信息 |
待办事项
| 工具 | 说明 |
|---|---|
list_todolists |
在项目的待办事项集中列出待办事项列表(支持 status 过滤器) |
get_todolist |
获取特定待办事项列表的详细信息 |
create_todolist |
创建新的待办事项列表 |
update_todolist |
更新现有待办事项列表 |
大惊小怪
| 工具 | 说明 |
|---|---|
list_todos |
在待办事项列表中列出待办事项 |
get_todo |
获取特定待办事项的详细信息 |
create_todo |
创建新待办事项 |
update_todo |
更新现有待办事项 |
complete_todo |
将待办事项标记为已完成 |
消息
| 工具 | 说明 |
|---|---|
list_messages |
在留言板上列出消息 |
get_message |
获取特定消息的详细信息 |
create_message |
发布新消息 |
评论
| 工具 | 说明 |
|---|---|
list_comments |
列出对录音的评论 |
create_comment |
在录音中添加评论 |
人们
| 工具 | 说明 |
|---|---|
list_people |
列出所有可见的人 |
get_person |
获取特定人员的详细信息 |
MCP客户端配置
要与Claude Code或其他MCP客户端一起使用,请在MCP配置中添加:
{
"mcpServers": {
"basecamp": {
"url": "http://localhost:9292/",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
省略 headers 字段if MCP_AUTH_TOKEN 未设置。
发展
make install # install dependencies
make test # run tests
make lint-fix # fix linting issues
测试使用Minitest+WebLock。所有的HTTP调用都是存根-测试中没有真正的API请求。
项目结构
basecamp-mcp/
├── Gemfile # Dependencies
├── Rakefile # Test + lint tasks
├── Makefile # Dev shortcuts
├── Dockerfile # Multi-stage Docker build
├── config.ru # Rack entrypoint
├── app.rb # Server setup and wiring
├── .env.example # Environment variable template
├── .standard.yml # StandardRB linter config
└── lib/
├── basecamp/
│ ├── client.rb # Faraday HTTP client for Basecamp 3 API
│ ├── errors.rb # Custom error classes
│ ├── token_store.rb # Thread-safe token persistence
│ └── oauth_refresher.rb # OAuth2 token refresh
├── oauth_app.rb # OAuth2 authorize/callback Sinatra app
├── middleware/
│ ├── downcase_headers.rb # Rack 3 header normalization
│ ├── request_logger.rb # DEBUG-gated request logger
│ └── token_auth.rb # Bearer token authentication
└── tools/
├── base_tool.rb # Shared base class with helpers
└── *.rb # Auto-discovered tool classes
码头工人
本地建设
docker build -t basecamp-mcp .
docker run -e BASECAMP_ACCESS_TOKEN=... -e BASECAMP_ACCOUNT_ID=... -p 9292:9292 basecamp-mcp
Docker Compose
services:
basecamp-mcp:
image: ghcr.io/k0va1/basecamp-mcp:latest
ports:
- "9292:9292"
environment:
- BASECAMP_ACCESS_TOKEN=${BASECAMP_ACCESS_TOKEN}
- BASECAMP_ACCOUNT_ID=${BASECAMP_ACCOUNT_ID}
- MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN:-}
- BASECAMP_CLIENT_ID=${BASECAMP_CLIENT_ID:-}
- BASECAMP_CLIENT_SECRET=${BASECAMP_CLIENT_SECRET:-}
- BASECAMP_REDIRECT_URI=${BASECAMP_REDIRECT_URI:-http://localhost:9292/oauth/callback}
- BASECAMP_TOKEN_PATH=/app/data/.basecamp_tokens.json
volumes:
- basecamp-tokens:/app/data
restart: unless-stopped
volumes:
basecamp-tokens:
验证
# Health check
curl http://localhost:9292/health
# MCP initialize
curl -X POST http://localhost:9292/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
