openproject-mcp
# openproject-mcp
A [Model Context Protocol](https://modelcontextprotocol.io) server for
[OpenProject](https://www.openproject.org). It gives an MCP-capable assistant
read-only access to the projects, work packages and comments that one
OpenProject API key can see.
## Why this exists
OpenProject ships an official MCP server, but it is an Enterprise add-on:
it requires an Enterprise cloud or on-premises plan at the Professional tier or
above. Every Community Edition instance, and every openDesk deployment built on
one, is left without a way to connect an assistant.
This server fills that gap. It talks to the documented, unrestricted
[API v3](https://www.openproject.org/docs/api/) that every OpenProject
instance exposes, using a personal API key.
## Scope and safety
Every tool in this server is read-only. There is no code path that creates,
updates or deletes anything in OpenProject, and no tool that writes to disk or
makes a request to any host other than the configured instance.
The server holds one API key and therefore sees exactly what the user behind
that key sees. OpenProject's own project memberships and role permissions
remain the access boundary; this server does not widen them.
Responses are size-capped before they reach the assistant. A single response
body is read up to a limit and then aborted, and long descriptions and comments
are truncated with an explicit `[truncated]` marker rather than silently cut.
## Requirements
- Node.js 20 or newer
- An OpenProject instance reachable from the machine running the server
- An OpenProject API key
### Creating an API key
1. Sign in to OpenProject.
2. Open your avatar menu and choose "My account".
3. Go to "Access tokens".
4. Under "API", choose "Generate" and copy the key.
The key inherits your permissions. If you want the assistant to see less than
you do, create a dedicated OpenProject user with narrower project memberships
and generate the key as that user.
## Installation
```
git clone https://github.com/Nraitschew/openproject-mcp.git
cd openproject-mcp
npm install
npm run build
```
The build writes an executable entry point to `dist/index.js`.
## Configuration
The server is configured through environment variables. The host application
that starts the server passes them in.
| Variable | Required | Default | Meaning |
| --- | --- | --- | --- |
| `OPENPROJECT_URL` | yes | | Instance URL, for example `https://projects.example.org`. A path prefix is kept, so an instance served under `https://example.org/op` works. `https` is added when the scheme is missing. |
| `OPENPROJECT_API_KEY` | yes | | The API key from "My account", "Access tokens". |
| `OPENPROJECT_TIMEOUT_MS` | no | `15000` | Per-request timeout in milliseconds. |
| `OPENPROJECT_MAX_RESPONSE_BYTES` | no | `4194304` | Hard cap on a single response body. |
| `OPENPROJECT_MAX_TEXT_CHARS` | no | `50000` | Cap on a description or comment handed to the assistant. |
A missing or malformed variable makes the server exit with a message on stderr
that names the variable, rather than starting and failing on the first tool
call.
## Connecting a client
### Claude Desktop
Edit the MCP configuration file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"openproject": {
"command": "node",
"args": ["/absolute/path/to/openproject-mcp/dist/index.js"],
"env": {
"OPENPROJECT_URL": "https://projects.example.org",
"OPENPROJECT_API_KEY": "your-api-key"
}
}
}
}
```
Restart Claude Desktop afterwards.
### Claude Code
```
claude mcp add openproject \
--env OPENPROJECT_URL=https://projects.example.org \
--env OPENPROJECT_API_KEY=your-api-key \
-- node /absolute/path/to/openproject-mcp/dist/index.js
```
### Any other MCP client
The server speaks MCP over stdio. Start it with `node dist/index.js` and the
two required environment variables set; any client that can spawn a stdio
server will work.
## Tools
| Tool | Purpose |
| --- | --- |
| `get_current_user` | Identify the account the API key belongs to. Call this first when a question says "my" or "me". |
| `list_projects` | List visible projects, optionally filtered by name or identifier. Returns the ids that scope a work package search. |
| `search_work_packages` | Full-text search over work packages, optionally scoped to a project or to the current user. Defaults to open work packages, most recently updated first. |
| `get_work_package` | One work package in full, including its description. |
| `get_work_package_comments` | The comments on a work package. Status changes without a comment are omitted. |
| `list_statuses` | The work package statuses configured on the instance. |
| `list_types` | The work package types configured on the instance, for example Task, Bug, Milestone. |
Tool results are JSON. Related resources are flattened out of OpenProject's
HAL envelopes: a work package carries `status`, `assignee` and `project` as
plain names rather than as link objects, so the assistant reads the work rather
than the link structure.
## Errors
A failing tool call returns a result marked as an error whose text starts with
a stable machine code:
| Code | Meaning |
| --- | --- |
| `unauthorized` | The API key was rejected. It may have been revoked. |
| `forbidden` | The key is valid but not permitted to read that resource. |
| `not_found` | No such work package, project or endpoint. |
| `rate_limited` | The instance is rate limiting this client. |
| `unreachable` | The instance did not answer, or the request timed out. |
| `invalid_response` | The response was not the expected document. Usually a wrong `OPENPROJECT_URL`. |
| `http_error` | Any other non-success status, with the status code in the message. |
## Testing against your instance
```
npx @modelcontextprotocol/inspector node dist/index.js
```
The MCP Inspector lists the tools and lets you call them by hand, which is the
fastest way to confirm the URL and key are right.
## Development
```
npm install
npm run typecheck
npm test
npm run build
```
The unit tests cover the configuration parsing and the API v3 filter grammar.
They make no network requests, so they run anywhere.
## Limitations
- Read-only by design. Creating or updating work packages is not implemented.
- Attachments are not downloaded.
- Time and cost entries, budgets, and the BCF endpoints are not exposed.
- `search_work_packages` sorts by last update and pages once. A very large
result set is truncated to the requested limit rather than paged through.
## Related
- [opendesk-mcp](https://github.com/Nraitschew/opendesk-mcp) connects a whole
openDesk instance, including this server's OpenProject tools.
- [xwiki-mcp](https://github.com/Nraitschew/xwiki-mcp) does the same for XWiki.
## License
Apache License 2.0. See [LICENSE](LICENSE).
This project is not affiliated with or endorsed by OpenProject GmbH.
"OpenProject" is a trademark of its respective owner and is used here only to
describe what this software connects to.
TDQS
Scored across 7 tools
Each tool targets a distinct resource or action: current user, projects, work-package search, single work package, comments, statuses, and types. There is no meaningful overlap between search_work_packages and get_work_package because one is full-text search and the other is retrieval by ID.
All tools follow a consistent verb_noun snake_case pattern: get_current_user, list_projects, search_work_packages, get_work_package, and so on. The one longer name, get_work_package_comments, still fits the established convention.
Seven tools is a well-scoped size for a read-oriented OpenProject integration. Each tool has a clear purpose and none are redundant, so the count feels intentional rather than padded or thin.
The surface is entirely read-only: it can search, view, and list work packages, projects, comments, statuses, and types, but it cannot create, update, transition, or comment on work packages. For a project-management domain this is a significant functional gap that prevents agents from completing common workflows.