openproject-mcp
Provides tools for managing OpenProject projects, work packages, relations, attachments, users, notifications, watchers, boards, and reference data via the OpenProject REST API.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openproject-mcpshow open work packages assigned to me"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openproject-mcp
An MCP server that exposes the OpenProject REST API (v3) as tools usable by Claude Desktop, Claude Code, Cursor, and any other MCP client.
Install
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 Code
claude mcp add openproject \
--env OPENPROJECT_BASE_URL=https://your-instance.openproject.com \
--env OPENPROJECT_API_KEY=your-token \
-- npx -y github:OliverRhyme/openproject-mcpClaude Desktop
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"
}
}
}
}Cursor
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"
}
}
}
}Windsurf
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"
}
}
}
}Any other MCP client (generic stdio)
Run this as the server process:
OPENPROJECT_BASE_URL=https://your-instance.openproject.com \
OPENPROJECT_API_KEY=your-token \
npx -y github:OliverRhyme/openproject-mcpThe server speaks JSON-RPC over stdio. No build step needed — npx fetches, installs, and runs it directly from GitHub.
Related MCP server: OpenProject MCP Server
Configuration
Variable | Required | Default | Notes |
| yes | -- | e.g. |
| yes | -- | From My account > Access tokens > API |
| no |
| Default page size for list endpoints |
| no |
| HTTP request timeout in milliseconds |
Features
Projects -- list, get, create, update, delete, count
Work packages -- list, get, create, update (with
lockVersion), delete, activity/comment thread, inline file attachments on comments, countRelations -- list, get, create, delete (blocks, precedes, relates, duplicates, etc.)
Attachments -- list, get (with download), upload (with auto-embed in description or comment), delete
Users -- current user, list, get
Notifications -- list, get, mark read, mark all read
Watchers -- list, add, remove watchers on work packages
Boards -- list and get Kanban-style boards
Reference data -- work package types, statuses, priorities, versions
Raw passthrough -- call any GET endpoint under
/api/v3directlyFilter, sort, group, and paginate via OpenProject's native query syntax
Output optimization -- field selection, description truncation,
hasMorepagination flag, lightweight count tools
Tools reference
All tools are prefixed op_ to avoid collisions with other MCP servers.
Projects
Tool | Description |
| List projects with filter/sort/paginate |
| Get project by id or identifier slug |
| Create a new project |
| Patch project fields |
| Delete a project (destructive, async) |
| Count projects matching filters |
Work packages
Tool | Description |
| List work packages, optionally scoped to a project |
| Get a single work package by id |
| Create a work package (requires subject, projectId, typeId) |
| Patch work package fields (requires |
| Delete a work package (destructive) |
| List comments and change history |
| Add a comment, optionally attaching and embedding a file inline |
| Count work packages matching filters |
Relations
Tool | Description |
| List relations on a work package (blocks, precedes, duplicates, etc.) |
| Get a single relation by id |
| Create a relation between two work packages |
| Delete a relation |
Attachments
Tool | Description |
| List attachments on a work package |
| Get attachment metadata; optionally download to a local path |
| Upload a local file; optionally embed in a comment or WP description |
| Delete an attachment (destructive) |
Users
Tool | Description |
| Get the user tied to the configured API key |
| List users with filter/sort/paginate |
| Get a user by id |
Notifications
Tool | Description |
| List in-app notifications for the current user |
| Get a single notification by id |
| Mark one notification as read |
| Mark all notifications as read |
Watchers
Tool | Description |
| List users watching a work package |
| Add a user as a watcher |
| Remove a user from watching |
Boards
Tool | Description |
| List Kanban-style boards for a project |
| Get board details including column config |
Reference data
Tool | Description |
| List work package types (Task, Bug, Feature, etc.) |
| List all work package statuses |
| List all priorities |
| List versions/milestones, optionally per project |
| Raw GET against any |
Usage patterns
Filter syntax
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) |
| Open statuses |
| 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].
Output optimization
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.
Updating work packages (lockVersion)
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
}Uploading and embedding attachments
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"
}Creating relations
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.
Local development
git clone https://github.com/OliverRhyme/openproject-mcp.git
cd openproject-mcp
npm install
npm run devCommand | Purpose |
| Install dependencies |
| Compile TypeScript to |
| Run the compiled server (requires build) |
| Watch-mode server via |
| Run test suite |
| Run tests in watch mode |
| Type-check without emitting |
Smoke test
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"}
EOFLicense
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/OliverRhyme/openproject-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server