Skip to main content
Glama
Attri-Inc

Basecamp MCP Server

by Attri-Inc
README.md
# Basecamp MCP Server

[![CI](https://github.com/Attri-Inc/Basecamp-MCP-Server/actions/workflows/ci.yml/badge.svg)](https://github.com/Attri-Inc/Basecamp-MCP-Server/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](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)