loading…
Search for a command to run...
loading…
Exposes the OpenProject REST API as MCP tools for project management, including creating and managing projects, work packages, relations, attachments, users, no
Exposes the OpenProject REST API as MCP tools for project management, including creating and managing projects, work packages, relations, attachments, users, notifications, watchers, boards, and reference data.
An MCP server that exposes the OpenProject REST API (v3) as tools usable by Claude Desktop, Claude Code, Cursor, and any other MCP client.
Before you start: you need an OpenProject API token. Get one from My account > Access tokens > API in your OpenProject instance.
Pick your MCP client and run one command:
claude mcp add openproject \
--env OPENPROJECT_BASE_URL=https://your-instance.openproject.com \
--env OPENPROJECT_API_KEY=your-token \
-- npx -y github:OliverRhyme/openproject-mcp
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"openproject": {
"command": "npx",
"args": ["-y", "github:OliverRhyme/openproject-mcp"],
"env": {
"OPENPROJECT_BASE_URL": "https://your-instance.openproject.com",
"OPENPROJECT_API_KEY": "your-token"
}
}
}
}
Add to .cursor/mcp.json in your project root:
{
"mcpServers": {
"openproject": {
"command": "npx",
"args": ["-y", "github:OliverRhyme/openproject-mcp"],
"env": {
"OPENPROJECT_BASE_URL": "https://your-instance.openproject.com",
"OPENPROJECT_API_KEY": "your-token"
}
}
}
}
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"openproject": {
"command": "npx",
"args": ["-y", "github:OliverRhyme/openproject-mcp"],
"env": {
"OPENPROJECT_BASE_URL": "https://your-instance.openproject.com",
"OPENPROJECT_API_KEY": "your-token"
}
}
}
}
Run this as the server process:
OPENPROJECT_BASE_URL=https://your-instance.openproject.com \
OPENPROJECT_API_KEY=your-token \
npx -y github:OliverRhyme/openproject-mcp
The server speaks JSON-RPC over stdio. No build step needed — npx fetches, installs, and runs it directly from GitHub.
| Variable | Required | Default | Notes |
|---|---|---|---|
OPENPROJECT_BASE_URL |
yes | -- | e.g. https://community.openproject.org |
OPENPROJECT_API_KEY |
yes | -- | From My account > Access tokens > API |
OPENPROJECT_PAGE_SIZE |
no | 25 |
Default page size for list endpoints |
OPENPROJECT_TIMEOUT_MS |
no | 30000 |
HTTP request timeout in milliseconds |
lockVersion), delete, activity/comment thread, inline file attachments on comments, count/api/v3 directlyhasMore pagination flag, lightweight count toolsAll tools are prefixed op_ to avoid collisions with other MCP servers.
| Tool | Description |
|---|---|
op_list_projects |
List projects with filter/sort/paginate |
op_get_project |
Get project by id or identifier slug |
op_create_project |
Create a new project |
op_update_project |
Patch project fields |
op_delete_project |
Delete a project (destructive, async) |
op_count_projects |
Count projects matching filters |
| Tool | Description |
|---|---|
op_list_work_packages |
List work packages, optionally scoped to a project |
op_get_work_package |
Get a single work package by id |
op_create_work_package |
Create a work package (requires subject, projectId, typeId) |
op_update_work_package |
Patch work package fields (requires lockVersion) |
op_delete_work_package |
Delete a work package (destructive) |
op_list_work_package_activities |
List comments and change history |
op_comment_work_package |
Add a comment, optionally attaching and embedding a file inline |
op_count_work_packages |
Count work packages matching filters |
| Tool | Description |
|---|---|
op_list_relations |
List relations on a work package (blocks, precedes, duplicates, etc.) |
op_get_relation |
Get a single relation by id |
op_create_relation |
Create a relation between two work packages |
op_delete_relation |
Delete a relation |
| Tool | Description |
|---|---|
op_list_attachments |
List attachments on a work package |
op_get_attachment |
Get attachment metadata; optionally download to a local path |
op_upload_attachment |
Upload a local file; optionally embed in a comment or WP description |
op_delete_attachment |
Delete an attachment (destructive) |
| Tool | Description |
|---|---|
op_current_user |
Get the user tied to the configured API key |
op_list_users |
List users with filter/sort/paginate |
op_get_user |
Get a user by id |
| Tool | Description |
|---|---|
op_list_notifications |
List in-app notifications for the current user |
op_get_notification |
Get a single notification by id |
op_mark_notification_read |
Mark one notification as read |
op_mark_all_notifications_read |
Mark all notifications as read |
| Tool | Description |
|---|---|
op_list_watchers |
List users watching a work package |
op_add_watcher |
Add a user as a watcher |
op_remove_watcher |
Remove a user from watching |
| Tool | Description |
|---|---|
op_list_boards |
List Kanban-style boards for a project |
op_get_board |
Get board details including column config |
| Tool | Description |
|---|---|
op_list_types |
List work package types (Task, Bug, Feature, etc.) |
op_list_statuses |
List all work package statuses |
op_list_priorities |
List all priorities |
op_list_versions |
List versions/milestones, optionally per project |
op_api_passthrough |
Raw GET against any /api/v3 path (escape hatch) |
List endpoints accept OpenProject's structured filter format:
{
"projectIdOrIdentifier": "web",
"filters": [
{ "field": "status_id", "operator": "o", "values": null },
{ "field": "assignee", "operator": "=", "values": ["42"] },
{ "field": "type", "operator": "=", "values": ["1"] }
],
"sortBy": [["updatedAt", "desc"]],
"pageSize": 50
}
Common operators:
| Operator | Meaning |
|---|---|
= |
Equals |
! |
Not equals |
~ |
Contains (substring) |
o |
Open statuses |
c |
Closed statuses |
>= |
Greater or equal |
<= |
Less or equal |
* |
Any (not empty) |
!* |
None (empty) |
Filter values are always strings, even for numeric ids: "values": ["42"], not [42].
List tools return summarized output by default. Several options keep responses small:
fields -- Return only specific fields per element:
// op_list_work_packages
{ "fields": ["id", "subject", "status"] }
// -> elements contain only { id, subject, status }
raw -- Get the full HAL+JSON document from OpenProject:
// op_get_work_package
{ "id": 17, "raw": true }
Count tools -- When you only need a number, use op_count_work_packages or op_count_projects instead of listing:
// op_count_work_packages
{ "projectIdOrIdentifier": "web", "filters": [{ "field": "status_id", "operator": "o", "values": null }] }
// -> { "total": 42 }
Pagination -- All list responses include hasMore: true|false so you know if there are more pages. Max pageSize is 100; default is 25.
Truncation -- Project descriptions are truncated to 200 chars in list mode. Activity comments are truncated to 500 chars by default; pass full: true to op_list_work_package_activities for complete text.
OpenProject uses optimistic locking. You must pass the current lockVersion
when updating a work package -- fetch it first with op_get_work_package:
// 1. Get current state
// op_get_work_package { "id": 17 }
// -> { ..., "lockVersion": 4 }
// 2. Update with lockVersion
// op_update_work_package
{
"id": 17,
"lockVersion": 4,
"statusId": 7,
"percentageDone": 50
}
Upload a file and auto-embed it as an image in a comment:
// op_upload_attachment
{
"workPackageId": 17,
"filePath": "/path/to/screenshot.png",
"embedIn": "comment",
"embedText": "Here's the updated design:"
}
Or attach a file when commenting:
// op_comment_work_package
{
"id": 17,
"comment": "Fixed in latest build, see attached screenshot.",
"attachFilePath": "/path/to/screenshot.png"
}
Link work packages with dependency or reference relations:
// op_create_relation
{
"fromId": 17,
"toId": 23,
"type": "blocks"
}
Relation types: relates, duplicates, blocks, precedes, follows,
includes, partOf, requires.
git clone https://github.com/OliverRhyme/openproject-mcp.git
cd openproject-mcp
npm install
npm run dev
| Command | Purpose |
|---|---|
npm install |
Install dependencies |
npm run build |
Compile TypeScript to dist/ |
npm start |
Run the compiled server (requires build) |
npm run dev |
Watch-mode server via tsx (no build) |
npm test |
Run test suite |
npm run test:watch |
Run tests in watch mode |
npm run typecheck |
Type-check without emitting |
Verify the server boots and lists tools without a real OpenProject instance:
OPENPROJECT_BASE_URL=https://example.openproject.com OPENPROJECT_API_KEY=fake \
node dist/index.js <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
EOF
MIT
Выполни в терминале:
claude mcp add openproject-mcp -- npx Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development