Skip to main content
Glama

Basecamp MCP Server

by stefanoverna
AGENTS.md22.7 kB
# AGENTS.md This document provides comprehensive guidance for AI agents (like Claude) working with the Basecamp MCP Server codebase. It covers project structure, development workflow, code conventions, and testing procedures. ## Project Overview ### What is this project? **Basecamp MCP Server** is a TypeScript-based Model Context Protocol (MCP) server that enables Large Language Models (LLMs) to interact with Basecamp's project management platform. It acts as a bridge between AI assistants and Basecamp's API. ### Purpose - Provide LLMs with programmatic access to Basecamp projects, messages, todos, comments, people, and kanban boards - Implement the Model Context Protocol standard for AI tool integration - Offer a command-line executable for easy installation in MCP-compatible clients (Claude, Cursor, VS Code, etc.) - Handle OAuth authentication and API communication with Basecamp ### Key Features - **25 MCP Tools** organized into 6 categories: Projects, Messages, TODOs, Comments, People, and Kanban - **Advanced content operations**: append, prepend, search-replace for rich text editing - **Response size management**: 25K character limit with pagination support - **Comprehensive error handling**: User-friendly, status-specific error messages - **OAuth token caching**: Minimize API calls and improve performance - **Type-safe validation**: Zod schemas for all tool inputs - **NPM package**: Distributed as `basecamp-mcp` on npm registry ### Technology Stack | Component | Technology | |-----------|------------| | Language | TypeScript 5.7+ | | Runtime | Node.js 18+ | | Protocol | Model Context Protocol (MCP) | | API Client | basecamp-client v1.0.7 | | Validation | Zod v3.23.8 | | Transport | Stdio (MCP communication) | | Build Tool | TypeScript compiler (tsc) | | Code Quality | Biome 2.3.0 (formatter + linter) | | Package Manager | npm | | Authentication | OAuth 2.0 | ## Architecture ### Directory Structure ``` basecamp-mcp/ ├── src/ # TypeScript source code │ ├── index.ts # Main entry point - server initialization │ ├── types.ts # TypeScript interfaces and types │ ├── constants.ts # Shared constants (limits, URLs) │ ├── tools/ # MCP tool implementations (6 categories) │ │ ├── projects.ts # Project operations (2 tools, 141 lines) │ │ ├── messages.ts # Message board operations (5 tools, 369 lines) │ │ ├── todos.ts # Todo management (5 tools, 263 lines) │ │ ├── comments.ts # Universal commenting (3 tools, 222 lines) │ │ ├── people.ts # User management (3 tools, 183 lines) │ │ └── kanban.ts # Kanban board operations (7 tools, 462 lines) │ ├── utils/ # Cross-cutting utility functions │ │ ├── auth.ts # OAuth authentication & client setup with token caching │ │ ├── errorHandlers.ts # API error handling with user-friendly messages │ │ ├── contentOperations.ts # HTML content manipulation (append/prepend/replace) │ │ └── serializers.ts # Data serialization and formatting helpers │ └── schemas/ # Zod validation schemas │ └── common.ts # Shared input parameter schemas ├── dist/ # Compiled JavaScript (generated by build, gitignored) ├── node_modules/ # Dependencies (gitignored) ├── package.json # NPM metadata, scripts, dependencies ├── tsconfig.json # TypeScript compiler configuration ├── biome.json # Formatter and linter configuration ├── run-evaluation.js # Evaluation test harness ├── evaluations.xml # Test cases in XML format ├── .gitignore # Git exclusions ├── README.md # User-facing documentation └── AGENTS.md # This file - agent documentation ``` ### Module Organization #### Entry Point: `src/index.ts` The main entry point follows this flow: 1. **Validate environment variables** - Checks for required OAuth credentials 2. **Create MCP server instance** - Initializes server with name and version 3. **Register tools** - Calls registration functions from each tool category 4. **Create stdio transport** - Sets up MCP protocol communication channel 5. **Connect and listen** - Starts server and waits for client connections #### Tool Categories: `src/tools/*.ts` Each tool file exports a single registration function: ```typescript export function registerToolNameTools(server: McpServer): void { server.registerTool("tool_name", { config }, async (params) => { // Implementation }); } ``` **Tool Registration Pattern:** 1. **Input Schema**: Define Zod schema for parameter validation 2. **Annotations**: Mark tool with metadata (readOnlyHint, destructiveHint, etc.) 3. **Handler**: Async function that executes the tool logic 4. **Error Handling**: Wrap in try-catch, use `handleBasecampError()` 5. **Response**: Return structured JSON via `{ content: [{ type: "text", text: JSON.stringify(...) }] }` #### Utility Modules: `src/utils/*.ts` - **auth.ts**: OAuth token management with in-memory caching - **errorHandlers.ts**: Converts API errors to LLM-friendly messages - **contentOperations.ts**: Advanced HTML editing operations - **serializers.ts**: Data normalization and formatting #### Type Definitions: `src/types.ts` - `ParsedBasecampUrl`: URL parsing interface - `PaginationMetadata`: Response pagination info - `TruncationInfo`: Response size management #### Shared Schemas: `src/schemas/common.ts` - `BasecampIdSchema`: Number-based ID validation - `BasecampUrlSchema`: Basecamp URL validation with format checking #### Constants: `src/constants.ts` - `CHARACTER_LIMIT = 25000`: Maximum response size - `DEFAULT_LIMIT = 20`: Default pagination size - `MAX_LIMIT = 100`: Maximum items per request - `BASECAMP_API_BASE`: API endpoint base URL - `BASECAMP_WEB_BASE`: Web UI base URL ### Design Patterns 1. **Modular Tool Registration**: Each domain exports registration functions, keeping concerns separated 2. **Token Caching**: Bearer tokens cached in memory to minimize OAuth requests 3. **Response Size Management**: Truncate large responses with metadata about what was truncated 4. **Status-Specific Error Handling**: Different error messages for 400, 401, 403, 404, 422, 429, 5xx 5. **Input Validation**: Zod schemas ensure type safety at runtime 6. **MCP Annotations**: Tools tagged with behavioral hints for clients ## Build and Test Commands ### Installation ```bash # Install dependencies npm install # Install globally from npm (for end users) npm install -g basecamp-mcp # Run via npx (recommended for testing latest version) npx -y basecamp-mcp@latest ``` ### Development ```bash # Run in development mode with auto-reload npm run dev # Start the compiled server npm start # Run TypeScript type checking (no output files) npx tsc --noEmit ``` ### Building ```bash # Compile TypeScript to JavaScript npm run build # Clean build artifacts npm run clean # Clean and rebuild npm run clean && npm run build # Pre-publish workflow (runs automatically before npm publish) npm run prepublishOnly ``` Build output goes to `dist/` directory. The compiled `dist/index.js` includes a shebang (`#!/usr/bin/env node`) and is marked as executable in package.json's `bin` field. ### Testing ```bash # Run placeholder test (currently just echoes "All good") npm test # Run evaluation harness (requires ANTHROPIC_API_KEY) node run-evaluation.js ``` **Evaluation Test Flow:** 1. Loads test cases from `evaluations.xml` 2. Starts MCP server as subprocess 3. Connects to server via stdio transport 4. For each question: - Sends question to Claude API with MCP tools available - Claude calls MCP tools to answer the question - Compares actual answer against expected answer 5. Outputs results to `evaluation-results.json` 6. Exits with code 0 if all tests pass, 1 if any fail ### Code Quality ```bash # Format code with Biome npm run format # Check formatting (no changes) npm run format:check # Lint and auto-fix npm run lint # Lint check (no changes) npm run lint:check # Format + lint combined (recommended) npm run check # CI mode - check only, no auto-fix npm run check:ci ``` ## Code Style Guidelines ### TypeScript Configuration **Compiler Options (tsconfig.json):** - **Target**: ES2022 - **Module**: Node16 (ESM with .js extensions in imports) - **Strict Mode**: Enabled (strict null checks, strict function types, etc.) - **Output**: `dist/` directory - **Source Maps**: Enabled for debugging - **Declarations**: Generated for library usage - **Module Resolution**: Node16 (ESM-compatible) **Important Rules:** - Always use `.js` extensions in import statements (ESM requirement) - All files must pass strict TypeScript checks - Prefer type inference over explicit types when obvious - Use `unknown` instead of `any` when type is truly unknown ### Biome Configuration **Formatting Rules:** - **Indentation**: 2 spaces (not tabs) - **Line Width**: 80 characters - **Line Ending**: LF (Unix-style) - **Quotes**: Double quotes for strings - **Semicolons**: Always required - **Trailing Commas**: Always (even in single-line) - **Arrow Parens**: Always (even for single parameter) - **Bracket Spacing**: Enabled (`{ foo }` not `{foo}`) **Linting Rules:** - **recommended**: true (all Biome recommended rules) - **noDoubleEquals**: error (use `===` and `!==`) - **noExplicitAny**: warn (prefer specific types) - **noUnusedVariables**: error - **noUnusedLabels**: error - **useConsistentArrayType**: error (prefer `T[]` shorthand) ### Naming Conventions - **Files**: camelCase (e.g., `errorHandlers.ts`, `contentOperations.ts`) - **Functions**: camelCase (e.g., `handleBasecampError`, `registerProjectTools`) - **Classes/Interfaces**: PascalCase (e.g., `ParsedBasecampUrl`, `PaginationMetadata`) - **Constants**: SCREAMING_SNAKE_CASE (e.g., `CHARACTER_LIMIT`, `DEFAULT_LIMIT`) - **Variables**: camelCase - **Tool Names**: snake_case with `basecamp_` prefix (e.g., `basecamp_list_projects`) ### Code Organization Patterns **Tool Implementation Pattern:** ```typescript /** * [Category]-related tools for Basecamp MCP server */ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { BasecampIdSchema } from "../schemas/common.js"; import { initializeBasecampClient } from "../utils/auth.js"; import { handleBasecampError } from "../utils/errorHandlers.js"; export function registerCategoryTools(server: McpServer): void { server.registerTool( "basecamp_tool_name", { title: "Human-Readable Title", description: "Detailed description with examples", inputSchema: { param: z.string().describe("Parameter description"), }, annotations: { readOnlyHint: true, // Tool doesn't modify data destructiveHint: false, // Tool doesn't delete data idempotentHint: true, // Same input = same output openWorldHint: true, // Tool returns open-ended data }, }, async (params) => { try { const client = await initializeBasecampClient(); // Tool implementation return { content: [ { type: "text", text: JSON.stringify(result, null, 2) } ], }; } catch (error) { return { content: [ { type: "text", text: handleBasecampError(error) } ], }; } }, ); } ``` **Error Handling Pattern:** Always use `handleBasecampError()` utility: ```typescript try { // API call } catch (error) { return { content: [{ type: "text", text: handleBasecampError(error) }], }; } ``` **Response Format:** Always return JSON with proper formatting: ```typescript return { content: [ { type: "text", text: JSON.stringify(data, null, 2), // 2-space indentation }, ], }; ``` ### Import Order 1. External dependencies (SDK, libraries) 2. Internal utilities (auth, error handlers) 3. Internal schemas 4. Internal types/constants Example: ```typescript import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { BasecampIdSchema } from "../schemas/common.js"; import { initializeBasecampClient } from "../utils/auth.js"; import { handleBasecampError } from "../utils/errorHandlers.js"; ``` ## Development Workflow ### Setting Up Development Environment 1. **Clone the repository**: ```bash git clone https://github.com/stefanoverna/basecamp-mcp.git cd basecamp-mcp ``` 2. **Install dependencies**: ```bash npm install ``` 3. **Set up environment variables** (create `.env` file): ```bash BASECAMP_CLIENT_ID=your_client_id BASECAMP_CLIENT_SECRET=your_client_secret BASECAMP_REFRESH_TOKEN=your_refresh_token BASECAMP_USER_AGENT="YourApp (your@email.com)" BASECAMP_ACCOUNT_ID=your_account_id ``` 4. **Build the project**: ```bash npm run build ``` 5. **Run in development mode**: ```bash npm run dev ``` ### Making Changes **When adding a new tool:** 1. Choose the appropriate tool category file in `src/tools/` 2. Add the tool registration within the existing `register*Tools()` function 3. Follow the tool implementation pattern (see Code Organization Patterns) 4. Define input schema using Zod 5. Add proper error handling with `handleBasecampError()` 6. Format response as JSON with 2-space indentation 7. Update tool count in documentation if needed **When adding a new tool category:** 1. Create new file in `src/tools/` (e.g., `calendars.ts`) 2. Implement `registerCalendarTools(server: McpServer)` function 3. Export the registration function 4. Import and call in `src/index.ts` 5. Update documentation **When modifying utilities:** 1. Ensure backward compatibility with existing tools 2. Update JSDoc comments 3. Run type checking: `npx tsc --noEmit` 4. Test with evaluation harness if applicable ### Testing Changes 1. **Type checking**: ```bash npx tsc --noEmit ``` 2. **Format and lint**: ```bash npm run check ``` 3. **Manual testing**: ```bash npm run dev # Test with MCP client (Claude Code, etc.) ``` 4. **Evaluation testing**: ```bash npm run build ANTHROPIC_API_KEY=your_key node run-evaluation.js ``` ### Publishing Changes The project uses `np` for releases: ```bash # Run np to publish (interactive prompts) npx np # Pre-publish automatically runs: # - npm run clean # - npm run build ``` ## Testing Instructions ### Manual Testing **Prerequisites:** - Built server: `npm run build` - Environment variables configured - MCP client available (Claude Code, etc.) **Steps:** 1. Start server in development mode: ```bash npm run dev ``` 2. Connect with MCP client 3. Test tool calls with various inputs: - Valid inputs (happy path) - Invalid inputs (validation errors) - Edge cases (empty lists, missing resources) - Error conditions (403, 404, etc.) ### Automated Evaluation Testing **Prerequisites:** - Built server: `npm run build` - `ANTHROPIC_API_KEY` environment variable set - Test cases defined in `evaluations.xml` **Run evaluations:** ```bash node run-evaluation.js ``` **Evaluation Output:** - Console: Progress and summary statistics - `evaluation-results.json`: Detailed results for each test case **Evaluation XML Format:** ```xml <evaluation> <qa_pair> <question>What is the name of project 12345?</question> <answer>Project Name</answer> </qa_pair> <!-- More test cases --> </evaluation> ``` **Adding New Test Cases:** 1. Open `evaluations.xml` 2. Add new `<qa_pair>` element with question and expected answer 3. Run evaluation harness 4. Verify results in `evaluation-results.json` **Success Criteria:** - All tests pass (100% pass rate) - Answers match expected results (exact or contains match) - No errors or timeouts ## Dependencies ### Production Dependencies | Package | Version | Purpose | |---------|---------|---------| | `@modelcontextprotocol/sdk` | ^1.6.1 | MCP protocol implementation | | `basecamp-client` | ^1.0.7 | Official Basecamp API client | | `zod` | ^3.23.8 | Runtime type validation | ### Development Dependencies | Package | Version | Purpose | |---------|---------|---------| | `typescript` | ^5.7.2 | TypeScript compiler | | `tsx` | ^4.19.2 | TypeScript execution for dev mode | | `@biomejs/biome` | 2.3.0 | Code formatter and linter | | `@types/node` | ^22.10.0 | Node.js type definitions | | `@anthropic-ai/sdk` | ^0.67.0 | Claude API for evaluation testing | | `dotenv` | ^17.2.3 | Environment variable loading | | `xml2js` | ^0.6.2 | XML parsing for evaluation tests | | `np` | ^10.2.0 | Publish automation tool | ## Environment Variables **Required for Server Operation:** - `BASECAMP_CLIENT_ID`: OAuth client ID from Basecamp app registration - `BASECAMP_CLIENT_SECRET`: OAuth client secret - `BASECAMP_REFRESH_TOKEN`: Refresh token for authentication - `BASECAMP_USER_AGENT`: Application identifier (format: "YourApp (email@example.com)") - `BASECAMP_ACCOUNT_ID`: Basecamp account ID (optional for some operations) **Required for Evaluation Testing:** - `ANTHROPIC_API_KEY`: Claude API key for running evaluation harness ## Tool Implementation Reference ### Available Tool Categories 1. **Projects (2 tools)**: - `basecamp_list_projects`: List all projects with optional filtering - `basecamp_get_project`: Get detailed project information 2. **Messages (5 tools)**: - `basecamp_list_messages`: List messages with filtering - `basecamp_list_message_types`: Get available message categories - `basecamp_get_message`: Retrieve single message - `basecamp_create_message`: Create new message - `basecamp_update_message`: Update message with content operations 3. **TODOs (5 tools)**: - `basecamp_get_todoset`: Get todo set container - `basecamp_list_todos`: List todos with status filtering - `basecamp_create_todo`: Create new todo - `basecamp_complete_todo`: Mark complete - `basecamp_uncomplete_todo`: Mark incomplete 4. **Comments (3 tools)**: - `basecamp_list_comments`: List comments on any resource - `basecamp_create_comment`: Add comment to resource - `basecamp_update_comment`: Update comment with content operations 5. **People (3 tools)**: - `basecamp_get_me`: Get authenticated user info - `basecamp_list_people`: List people with filtering - `basecamp_get_person`: Get person details 6. **Kanban (7 tools)**: - `basecamp_list_kanban_columns`: List board columns - `basecamp_list_kanban_cards`: List column cards - `basecamp_get_kanban_card`: Get card details - `basecamp_create_kanban_card`: Create card - `basecamp_update_kanban_card`: Update card (title, dates, assignees) - `basecamp_move_kanban_card`: Move between columns - `basecamp_create_kanban_step`: Add checklist step ### Adding New Tools Checklist - [ ] Choose appropriate tool category file (or create new one) - [ ] Define Zod input schema - [ ] Write tool description with examples - [ ] Implement async handler function - [ ] Use `initializeBasecampClient()` for API access - [ ] Wrap in try-catch with `handleBasecampError()` - [ ] Return JSON-formatted response - [ ] Add appropriate MCP annotations - [ ] Test with type checking: `npx tsc --noEmit` - [ ] Test with linting: `npm run check` - [ ] Test manually with MCP client - [ ] Add evaluation test case if applicable - [ ] Update README.md if needed ## Common Patterns and Best Practices ### Pagination Use `asyncPagedToArray` from basecamp-client: ```typescript import { asyncPagedToArray } from "basecamp-client"; const items = await asyncPagedToArray({ fetchPage: client.resource.list, request: { query: {} }, }); ``` ### Filtering Apply regex filtering after fetching: ```typescript if (params.filter) { const regex = new RegExp(params.filter, "i"); filteredItems = items.filter((item) => regex.test(item.name)); } ``` ### Response Truncation Check response size against `CHARACTER_LIMIT`: ```typescript import { CHARACTER_LIMIT } from "../constants.js"; const jsonStr = JSON.stringify(data, null, 2); if (jsonStr.length > CHARACTER_LIMIT) { // Truncate and add metadata } ``` ### Content Operations Use content operations for update tools: ```typescript import { applyContentOperation } from "../utils/contentOperations.js"; const newContent = applyContentOperation( currentContent, params.operation, params.content, ); ``` ### OAuth Token Caching Always use `initializeBasecampClient()` to get authenticated client: ```typescript import { initializeBasecampClient } from "../utils/auth.js"; const client = await initializeBasecampClient(); // Token is cached automatically ``` ## Troubleshooting ### Common Issues **Issue**: `Missing required environment variables` - **Solution**: Check `.env` file or environment has all required variables **Issue**: `Authentication failed (401)` - **Solution**: Refresh token may be expired - generate new one from Basecamp **Issue**: `Module not found` errors - **Solution**: Ensure imports use `.js` extensions (ESM requirement) **Issue**: Type errors after changes - **Solution**: Run `npx tsc --noEmit` to see full error details **Issue**: Biome formatting conflicts - **Solution**: Run `npm run format` to auto-fix formatting issues **Issue**: Evaluation tests fail - **Solution**: Check `evaluation-results.json` for detailed error messages ## Additional Resources - **MCP Documentation**: https://modelcontextprotocol.io - **Basecamp API Docs**: https://github.com/basecamp/bc3-api - **TypeScript Handbook**: https://www.typescriptlang.org/docs/ - **Zod Documentation**: https://zod.dev - **Biome Documentation**: https://biomejs.dev ## Version History - **1.0.1** (Current): Production release with 25 tools across 6 categories - **1.0.0**: Initial public release ## License MIT License - See LICENSE file for details ## Contributing This project follows standard open-source contribution practices: 1. Fork the repository 2. Create a feature branch 3. Make your changes following code style guidelines 4. Run tests and type checking 5. Submit pull request with clear description --- **Last Updated**: 2025-10-28 **Maintained By**: Stefano Verna (stefano.verna@gmail.com)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stefanoverna/basecamp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server