Basecamp MCP Server
by Attri-Inc
README.md
# Basecamp MCP Server
[](https://github.com/Attri-Inc/Basecamp-MCP-Server/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.python.org/downloads/)
The first open-source MCP server for Basecamp 3 with **multi-user and enterprise hosting support**. Gives AI clients (Claude Desktop, Cursor, Codex, etc.) direct access to Basecamp via 148+ tools.
## Why this project?
Every existing Basecamp MCP integration was single-user only — you had to run a local process per user with your own credentials. That doesn't work for teams or enterprise deployments.
This project solves that with a **streamable-http mode**: one server, one port, multiple users — each authenticating with their own Basecamp account via OAuth. Deploy it once for your entire organization.
## Modes
| Mode | Use case |
|------|----------|
| **stdio** | Single-user, local process. Standard MCP transport. |
| **streamable-http** | Multi-tenant HTTP server. One deployment for your whole org. |
---
## Quick Start
### Prerequisites
- Python 3.10+
- A Basecamp 3 account
- A Basecamp OAuth app — register at [launchpad.37signals.com/integrations](https://launchpad.37signals.com/integrations)
### Install
```bash
git clone https://github.com/Attri-Inc/basecamp-mcp-server.git
cd Basecamp-MCP-Server
# Using uv (recommended)
uv venv --python 3.12 venv && source venv/bin/activate
uv pip install -r requirements.txt && uv pip install mcp
# Or using pip
python setup.py
```
### Configure
Copy `.env.example` to `.env` and fill in your credentials:
```bash
cp .env.example .env
```
Your Basecamp account ID is in the URL: `https://3.basecamp.com/{account_id}/projects`
---
## Mode 1: stdio (Single-user)
**Step 1** — Authenticate with Basecamp (one-time):
```bash
MCP_TRANSPORT=streamable-http ./venv/bin/python basecamp_fastmcp.py
```
Visit `http://localhost:8001`, click **Connect Basecamp**, complete OAuth. Tokens are saved to `oauth_tokens.json`. Stop the server.
**Step 2** — Add to your MCP client config:
```json
{
"mcpServers": {
"basecamp": {
"command": "/full/path/to/venv/bin/python",
"args": ["/full/path/to/basecamp_fastmcp.py"],
"env": {
"PYTHONPATH": "/full/path/to/project",
"BASECAMP_ACCOUNT_ID": "your_account_id"
}
}
}
}
```
**Claude Desktop** — auto-generate config:
```bash
python generate_claude_desktop_config.py
```
Then restart Claude Desktop completely.
---
## Mode 2: streamable-http (Multi-tenant)
This is the core feature that makes this project different. A single server instance handles any number of users, each connected to their own Basecamp account. No per-user processes, no shared credentials.
### How it works
```
User A ──► POST /mcp (Bearer api_key_A) ──► validates key ──► uses User A's Basecamp tokens
User B ──► POST /mcp (Bearer api_key_B) ──► validates key ──► uses User B's Basecamp tokens
User C ──► POST /mcp (Bearer api_key_C) ──► validates key ──► uses User C's Basecamp tokens
```
Each user authenticates once via OAuth and receives a unique API key. From that point on, every MCP request they make is scoped to their own Basecamp account. Tokens are stored in PostgreSQL and auto-refreshed transparently.
### Setup
Requires PostgreSQL. Add to `.env`:
```bash
MCP_TRANSPORT=streamable-http
DATABASE_URL=postgresql://user:pass@localhost:5432/basecamp_mcp
MCP_SERVER_URL=http://your-server:8001
MCP_HOST=0.0.0.0
MCP_PORT=8001
```
**Start the server:**
```bash
MCP_TRANSPORT=streamable-http ./venv/bin/python basecamp_fastmcp.py
```
### User onboarding (per user, one-time)
1. User visits `http://your-server:8001/`
2. Clicks **Connect Basecamp** → redirected to 37signals OAuth
3. Authorizes the app → redirected back to your server
4. Server stores their Basecamp tokens in PostgreSQL and generates a unique API key
5. User copies their API key and adds it to their MCP client config:
```json
{
"mcpServers": {
"basecamp": {
"url": "http://your-server:8001/mcp",
"headers": { "Authorization": "Bearer <their_api_key>" }
}
}
}
```
After this, the user's AI client has full access to their own Basecamp — and only their Basecamp. No other user's data is accessible.
---
## Available Tools (148 total)
| Category | Tools |
|----------|-------|
| **Projects** | `get_projects`, `get_project` |
| **Todos** | `get_todolists`, `get_todolist`, `create_todolist`, `update_todolist`, `trash_todolist`, `get_todos`, `get_todo`, `create_todo`, `update_todo`, `delete_todo`, `complete_todo`, `uncomplete_todo`, `reposition_todo`, `archive_todo` |
| **Todo Groups** | `get_todolist_groups`, `create_todolist_group`, `reposition_todolist_group` |
| **Card Tables** | `get_card_tables`, `get_card_table`, `get_columns`, `get_column`, `create_column`, `update_column`, `move_column`, `update_column_color`, `put_column_on_hold`, `remove_column_hold`, `watch_column`, `unwatch_column`, `get_cards`, `get_card`, `create_card`, `update_card`, `move_card`, `complete_card`, `uncomplete_card` |
| **Card Steps** | `get_card_steps`, `get_card_step`, `create_card_step`, `update_card_step`, `delete_card_step`, `complete_card_step`, `uncomplete_card_step` |
| **Messages** | `get_message_board`, `get_messages`, `get_message`, `get_message_categories`, `create_message` |
| **Comments** | `get_comments`, `create_comment` |
| **Campfire** | `get_campfire_lines` |
| **Documents** | `get_documents`, `get_document`, `create_document`, `update_document`, `trash_document` |
| **Inbox** | `get_inbox`, `get_forwards`, `get_forward`, `get_inbox_replies`, `get_inbox_reply`, `trash_forward` |
| **Uploads** | `get_uploads`, `get_upload`, `create_attachment` |
| **Search** | `search_basecamp`, `global_search` |
| **Check-ins** | `get_daily_check_ins`, `get_question_answers` |
| **Events & Webhooks** | `get_events`, `get_webhooks`, `create_webhook`, `delete_webhook` |
---
## Architecture
| File | Purpose |
|------|---------|
| `basecamp_fastmcp.py` | Main MCP server — stdio and streamable-http transport |
| `basecamp_client.py` | Basecamp 3 API client |
| `basecamp_oauth.py` | OAuth 2.0 for 37signals Launchpad |
| `search_utils.py` | Cross-project search |
| `auth_manager.py` | Auto token refresh (stdio) |
| `token_storage.py` | OAuth token persistence (stdio) |
| `user_store.py` | PostgreSQL per-user credential store (HTTP) |
| `api_key_verifier.py` | API key validation (HTTP) |
| `multi_auth_manager.py` | Per-user token refresh (HTTP) |
| `auth_routes.py` | OAuth portal routes (HTTP) |
---
## Troubleshooting
| Problem | Fix |
|---------|-----|
| Tools not appearing | Restart MCP client completely |
| `0 tools available` | Run `python setup.py` to reinstall dependencies |
| Token expired (stdio) | Re-run HTTP server, visit auth portal, stop server |
| Basecamp not linked (HTTP) | Visit `http://your-server:8001/` and connect |
**Logs:**
```bash
tail -f basecamp_fastmcp.log
tail -f ~/Library/Logs/Claude/mcp-server-basecamp.log # Claude Desktop (macOS)
```
---
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
## License
MIT — see [LICENSE](LICENSE).
---
Created and open-sourced by [Attri](https://attri.ai)This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues