Basecamp 2 MCP
# Basecamp 2 MCP
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that connects Claude and other AI assistants to the [Basecamp 2 API](https://github.com/basecamp/bcx-api). Manage projects, todos, messages, and people directly from your AI assistant.
## Prerequisites
- Node.js 18 or later
- A Basecamp 2 account
- OAuth 2 credentials **or** your username and password
## OAuth Setup (recommended)
1. **Register your app** at [launchpad.37signals.com/integrations](https://launchpad.37signals.com/integrations) to obtain a `client_id` and `client_secret`.
2. **Run the auth helper** — it opens a browser, handles the redirect, exchanges the code for tokens, and prints your `BASECAMP_ACCOUNT_ID` automatically:
```bash
BASECAMP_CLIENT_ID=your_client_id \
BASECAMP_CLIENT_SECRET=your_client_secret \
npx basecamp-2-mcp-auth
```
Copy the printed env vars into your `.env` or MCP server config.
3. The MCP server will **automatically refresh the access token** when it expires (~2 weeks) as long as `BASECAMP_REFRESH_TOKEN`, `BASECAMP_CLIENT_ID`, and `BASECAMP_CLIENT_SECRET` are set.
> By default `npx basecamp-2-mcp-auth` listens on port `3000`. Set `OAUTH_PORT` to change it (your registered redirect URI must match).
## Environment Variables
| Variable | Required | Description |
|---|---|---|
| `BASECAMP_ACCOUNT_ID` | Yes | Your account ID — printed by the auth helper, or found in the URL: `basecamp.com/{account_id}/` |
| `BASECAMP_ACCESS_TOKEN` | Yes* | OAuth 2 access token |
| `BASECAMP_REFRESH_TOKEN` | No | Enables automatic token refresh when the access token expires |
| `BASECAMP_CLIENT_ID` | No† | Required for automatic token refresh |
| `BASECAMP_CLIENT_SECRET` | No† | Required for automatic token refresh |
| `BASECAMP_USERNAME` | Yes* | Your Basecamp email (Basic Auth alternative) |
| `BASECAMP_PASSWORD` | Yes* | Your Basecamp password (Basic Auth alternative) |
| `USER_AGENT` | Yes | Identifies your integration, e.g. `MyApp (you@example.com)` |
\* Either `BASECAMP_ACCESS_TOKEN` **or** both `BASECAMP_USERNAME` + `BASECAMP_PASSWORD` are required.
† Required together with `BASECAMP_REFRESH_TOKEN` to enable automatic token refresh.
## Setup with Claude Desktop
Add the following to your `claude_desktop_config.json` (usually at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"basecamp-2": {
"command": "npx",
"args": ["-y", "basecamp-2-mcp"],
"env": {
"BASECAMP_ACCOUNT_ID": "your_account_id",
"BASECAMP_ACCESS_TOKEN": "your_access_token",
"BASECAMP_REFRESH_TOKEN": "your_refresh_token",
"BASECAMP_CLIENT_ID": "your_client_id",
"BASECAMP_CLIENT_SECRET": "your_client_secret",
"USER_AGENT": "MyApp (you@example.com)"
}
}
}
}
```
Then restart Claude Desktop.
## Setup with Claude Code
```bash
claude mcp add basecamp-2 -- npx -y basecamp-2-mcp
```
Then set the required environment variables in your shell or `.env` file.
## Running Locally
```bash
# 1. Clone the repo and install dependencies
npm install
# 2. Copy and fill in environment variables
cp .env.example .env
# 3. Build
npm run build
# 4. Start the MCP server
npm start
```
For development with live reload:
```bash
npm run dev
```
To test interactively with the MCP Inspector:
```bash
npx @modelcontextprotocol/inspector npx tsx src/index.ts
```
## Available Tools
### Projects
| Tool | Description |
|---|---|
| `list_projects` | List all active projects |
| `get_project` | Get a project by ID |
### People
| Tool | Description |
|---|---|
| `get_me` | Get the currently authenticated user |
| `list_people` | List all people in the account |
| `get_person` | Get a person by ID |
### Todo Lists
| Tool | Description |
|---|---|
| `list_todolists` | List all todo lists in a project |
| `get_todolist` | Get a todo list with its todos |
| `create_todolist` | Create a new todo list in a project |
### Todos
| Tool | Description |
|---|---|
| `list_todos` | List all todos in a todo list |
| `get_todo` | Get a single todo item |
| `create_todo` | Create a new todo (supports due date + assignee) |
| `update_todo` | Update a todo's content, due date, or assignee |
| `complete_todo` | Mark a todo as completed |
| `delete_todo` | Delete a todo item |
### Messages & Topics
| Tool | Description |
|---|---|
| `list_topics` | List all topics (messages, forwards, etc.) in a project |
| `get_message` | Get a full message by ID (use the `topicable.id` from `list_topics`) |
| `create_message` | Post a new message to a project |
## Authentication
Basecamp 2 uses [OAuth 2 via Launchpad](https://github.com/basecamp/api/blob/master/sections/authentication.md). The authorization flow is:
1. User visits `https://launchpad.37signals.com/authorization/new?type=web_server&client_id=…&redirect_uri=…`
2. After approving, Basecamp redirects to your `redirect_uri` with a short-lived `code`
3. Your app POSTs the code to `https://launchpad.37signals.com/authorization/token` to receive an access token and a refresh token
4. Access tokens are sent as `Authorization: Bearer <token>`. Refresh tokens last ~2 weeks.
The `npx basecamp-2-mcp-auth` helper handles steps 1–3 automatically. The MCP server handles step 4 including silent refresh.
Every API request must also include a `User-Agent` header identifying your app and a contact email — this is a Basecamp API requirement. See [Identifying your application](https://github.com/basecamp/bcx-api#identifying-your-application).
## License
MIT
TDQS
Scored across 17 tools
Most tools target distinct resource+action pairs (todo, todolist, project, person, message). Minor overlap exists between list_topics and get_message/create_message since messages are a subset of topics, and get_me vs get_person/list_people could momentarily confuse, but overall boundaries are clear.
Every tool follows a consistent verb_noun snake_case pattern: list_x, get_x, create_x, update_x, complete_x, delete_x. Even get_me fits the convention, making the set highly predictable.
17 tools is slightly heavy but well-scoped across five resources (projects, todolists, todos, messages, people). Each tool earns its place, with no obviously redundant entries.
Todos have full lifecycle (create/get/list/update/complete/delete), but todolists lack update/delete, messages lack update/delete (and only list_topics surfaces them), and projects lack create/update/delete. These notable gaps leave dead ends for common management workflows.