Skip to main content
Glama

Tonle OpenProject MCP Server

by liratanak
CLAUDE.md8.87 kB
# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is the **Tonle OpenProject MCP Server** - a Model Context Protocol (MCP) server that provides AI assistants with seamless integration to OpenProject (open-source project management software). The server implements MCP tools that wrap the OpenProject API v3, enabling natural language interactions for project management operations. ## Development Commands ### Running the Server ```bash # Start STDIO server (for local MCP clients like Claude Desktop) bun run start # or bun run index.ts # Start HTTP server (for remote/web clients) bun run start:http # Development mode with auto-reload bun run dev # STDIO transport bun run dev:http # HTTP transport # Test with MCP Inspector bun run inspect # Inspect STDIO server bun run inspect:http # Inspect HTTP server ``` ### Running Tests ```bash # Run all tests bun test # Run HTTP transport tests only bun test tests/mcp-server.test.ts # Run transport comparison tests bun test tests/transport-comparison.test.ts ``` ### Package Management ```bash # Install dependencies bun install # Update dependencies bun update ``` ## Architecture ### Core Components 1. **index.ts** - STDIO MCP server entry point - Uses shared server setup from `src/server-setup.ts` - Implements stdio transport for local integration (Claude Desktop, Cursor) - Best for spawning server as subprocess 2. **http-server.ts** - HTTP MCP server entry point - Uses shared server setup from `src/server-setup.ts` - Implements Streamable HTTP transport for remote clients - Supports session management with UUID-based sessions - Endpoints: `/mcp` (POST/GET/DELETE), `/health` (GET) 3. **src/server-setup.ts** - Shared MCP server configuration - Registers all MCP tools using `@modelcontextprotocol/sdk` - Tool handlers transform user-friendly parameters into API calls - Each tool follows pattern: validate input → call client → format response 4. **src/openproject-client.ts** - OpenProject API client - Type-safe wrapper around OpenProject API v3 - HAL+JSON format handling - Authentication via Basic Auth with API key - Request/response typing with TypeScript interfaces ### Data Flow ``` MCP Client (Claude, Cursor, etc.) Web Client / Remote App ↓ JSON-RPC over stdio ↓ JSON-RPC over HTTP MCP Server (index.ts) HTTP Server (http-server.ts) ↓ ↓ └─────────── Server Setup (src/server-setup.ts) ───────────┘ ↓ Tool registration & handlers OpenProject Client (src/openproject-client.ts) ↓ HTTPS with HAL+JSON OpenProject Instance (API v3) ``` ### Key Architecture Patterns - **HAL+JSON Hypermedia**: OpenProject uses hypermedia format where relationships are represented as `_links` objects containing hrefs - **Link Construction**: Related entities reference each other via links like `/api/v3/projects/123`, constructed using the `createLink()` helper - **Optimistic Locking**: Updates require `lockVersion` parameter to prevent concurrent modification conflicts - **Rich Text Fields**: Description fields use `{ raw: string }` format for markdown content - **Pagination**: List endpoints support `offset` and `pageSize` parameters (max 1000) ## Configuration ### Environment Variables Required for the server to connect to OpenProject: - `OPENPROJECT_URL` - Base URL of OpenProject instance (e.g., `https://example.openproject.com`) - `OPENPROJECT_API_KEY` or `OPENPROJECT_TOKEN` - API key for authentication - `OPENPROJECT_TIMEOUT` - Request timeout in milliseconds (default: 30000) HTTP server specific (optional): - `MCP_HTTP_PORT` - HTTP server port (default: 3100) - `MCP_HTTP_HOST` - HTTP server host (default: 0.0.0.0) ### Claude Desktop Integration (STDIO) Add to `~/.config/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "openproject": { "command": "bun", "args": ["run", "/absolute/path/to/Tonle/index.ts"], "env": { "OPENPROJECT_URL": "https://your-instance.openproject.com", "OPENPROJECT_API_KEY": "your-api-key-here" } } } } ``` ### HTTP Client Integration For remote/web clients, start the HTTP server: ```bash OPENPROJECT_URL=https://your-instance.openproject.com \ OPENPROJECT_API_KEY=your-api-key \ bun run start:http ``` Then connect using the MCP SDK's HTTP transport: ```typescript import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; const transport = new StreamableHTTPClientTransport( new URL('http://localhost:3100/mcp') ); const client = new Client({ name: 'my-client', version: '1.0.0' }); await client.connect(transport); ``` ## Implementing New Tools When adding support for additional OpenProject API endpoints: 1. **Add TypeScript interface** to `src/openproject-client.ts` if needed for the response type 2. **Implement client method** in `OpenProjectClient` class following existing patterns: - Use typed parameters and return types - Handle HAL+JSON link structures - Support optional pagination/filtering parameters 3. **Register MCP tool** in `index.ts`: - Use `server.tool()` with clear name and description - Define Zod schema for input validation - Transform parameters to API format (especially `_links` objects) - Handle errors and format responses consistently - Return `{ content: [{ type: 'text', text: formatResponse(result) }] }` ### Example Pattern for Creating Resources ```typescript // In src/openproject-client.ts async createResource(data: { name: string; projectId: number }): Promise<Resource> { return this.request('POST', '/resources', { name: data.name, _links: { project: { href: `/api/v3/projects/${data.projectId}` } } }); } // In index.ts server.tool( 'create_resource', 'Create a new resource in a project', { name: z.string().describe('Resource name'), projectId: z.number().describe('Project ID'), }, async ({ name, projectId }) => { try { const result = await client.createResource({ name, projectId }); return { content: [{ type: 'text', text: formatResponse(result) }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); ``` ## OpenProject API Specifics ### Authentication - Uses Basic Auth with format: `apikey:{API_KEY}` encoded as base64 - API keys generated in OpenProject under "My account" → "Access tokens" ### HAL+JSON Links Pattern When referencing related resources, use the `_links` structure: ```typescript { _links: { assignee: { href: '/api/v3/users/5' }, project: { href: '/api/v3/projects/demo-project' } } } ``` ### Common Endpoints Currently Implemented - **Projects**: CRUD operations, listing with filters - **Work Packages**: CRUD, activities, project-scoped listing - **Users**: CRUD, lock/unlock, current user - **Types**: List available work package types - **Statuses**: List available statuses - **Priorities**: List available priorities - **Time Entries**: CRUD operations - **Versions**: CRUD operations (milestones/releases) - **Activities**: View journal entries - **Principals**: List users, groups, and placeholder users ### Future Endpoint Categories to Implement See README.md for comprehensive list of 40+ endpoint categories including memberships, roles, relations, queries, notifications, attachments, file links, and more. ## TypeScript Configuration The project uses Bun's modern TypeScript setup: - `module: "Preserve"` - Preserves ES modules - `moduleResolution: "bundler"` - Bundler-style resolution - `allowImportingTsExtensions: true` - Direct .ts imports - `strict: true` - Full strict mode enabled - `noEmit: true` - No compilation output (Bun runs TS directly) ## Error Handling OpenProject API returns structured errors: ```typescript { _type: 'Error', errorIdentifier: 'urn:openproject-org:api:v3:errors:NotFound', message: 'Resource not found', _embedded: { details: { attribute: 'subject' } } } ``` The client extracts and throws readable error messages including the identifier and message. ## Testing Strategy - Use MCP Inspector (`bun run inspect`) to test tools interactively - Verify authentication by testing `get_current_user` tool - Test against a dedicated OpenProject test instance, not production - For work package updates, always retrieve current `lockVersion` first

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/liratanak/openproject-mcp'

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