OpenProject + MCP: Agent Write Access on Community Edition

OpenProject + MCP: Agent Write Access on Community Edition

OpenProject 17.8 shipped on September 2 with a line in the release notes that made me sit up: the MCP server can now create and update work packages, add comments, and manage relations. Read-only MCP integrations are easy. Write access is the interesting part, because that is where you have to decide how much you actually trust an agent with your backlog.

Then I opened the admin guide and found the asterisk. The official MCP server is an Enterprise add-on, available only on Enterprise cloud or Enterprise on-premises with a Professional, Premium or Corporate plan. If you are running Community Edition, which is what most self-hosted OpenProject instances are, that feature is not yours.

So this is the article about what you can do instead, and honestly, the Community Edition path turned out to be the more interesting one.

What is actually gated

To be precise, because this matters before you spend money: the /mcp endpoint, the mcp token scope, and the Administration > Artificial Intelligence > Model Context Protocol settings panel are all Enterprise. Nothing about the MCP server ships in Community Edition.

What does ship in Community Edition is the full API v3. Every work package operation the Enterprise MCP server performs is a REST call underneath, and those endpoints are open to you. The missing piece is not capability. It is the translation layer between your agent and the API.

The Community Edition route

That translation layer exists. openproject-ce-mcp is an MIT-licensed MCP server that wraps API v3 and explicitly targets Community Edition. It exposes 132 tools (106 if you leave admin writes off) covering projects, work packages, memberships, versions, boards and time entries. It runs as a local subprocess of your MCP client over stdio, so there is no extra service to expose. Worth noting: because it wraps API v3 rather than anything new in 17.8, you do not need to be on the latest release to use it.

Being straight with you about what this is: it is a small third-party project, not an OpenProject one. It is MIT licensed, has fourteen releases behind it, and had commits the day I wrote this, so it is maintained rather than abandoned. But you are adding a dependency that is not backed by the vendor, and it does not have a large community around it yet. Read the source before you point it at anything you care about. Its own README tells you to use the official Enterprise MCP instead if you have a license, which is a good sign about the author's intentions.

Getting it running

Deploy OpenProject first. On Elestio it starts at $16/month for a managed instance with backups, SSL and updates handled, which is the boring part you do not want to own.

Then create an API token in OpenProject under your avatar, My Account, Access tokens. The v3 API accepts it either as a bearer token or as basic auth with the literal username apikey and the token as the password. Verify it before you go further:

curl -u apikey:YOUR_TOKEN https://your-openproject.example.com/api/v3/users/me

If that returns your user object, the token works. Then install and configure:

pipx install openproject-ce-mcp
openproject-ce-mcp configure
openproject-ce-mcp --version

The configure wizard collects your instance URL, API token, and project scope, then writes config for whichever MCP clients you pick. Scoping it to a single project is the right default. Restart your client, then ask it to call get_current_user to confirm the connection.

The part that actually matters

Here is what makes this worth writing about. The tool categories are not the security boundary. The project allowlists are.

Read tools are registered by default and the five core write categories are enabled by default, but none of it does anything until you list projects explicitly:

Variable Default What it does
OPENPROJECT_READ_PROJECTS empty Empty denies all project-scoped reads. Accepts identifiers, names or globs.
OPENPROJECT_WRITE_PROJECTS empty Empty disables every write. Always intersected with read scope.
OPENPROJECT_ENABLE_ADMIN_READ false Instance-wide user and group listing. This is PII and it is not project-scoped.
OPENPROJECT_ENABLE_ADMIN_WRITE false User creation, locking, group membership. Leave this off.

Start with one project in OPENPROJECT_READ_PROJECTS, nothing in OPENPROJECT_WRITE_PROJECTS, and live with a read-only agent for a week. Then add that same project to the write allowlist. Resist * on the write side until you have watched it work.

The second guard is the write protocol. Every write is preview-then-confirm: the agent calls a tool once and gets a validated preview, then calls again with confirm=true to execute. Create and update operations validate against OpenProject's own form endpoints before writing, so a malformed work package fails at preview instead of landing half-built. The README states there is no way to bypass this, which is the design decision I would want.

Why not just call the REST API

You can. The reason not to is context. OpenProject's API v3 returns HAL, which means roughly 21 fields and 46 links per work package. The project's own measurements put three representative work packages at about 10,139 tokens raw, versus about 1,100 through list_work_packages, or about 144 with a select narrowing it to five fields. That is the difference between an agent that can hold your sprint in context and one that burns its window on hypermedia links.

Troubleshooting

Tools appear but every call returns nothing. Your allowlists are empty. The categories being enabled is not enough. Put a project identifier in OPENPROJECT_READ_PROJECTS.

Writes silently do nothing. Same cause on the write side, or you confirmed nothing. Check that the project is in OPENPROJECT_WRITE_PROJECTS and that you passed confirm=true on the second call.

401 from the API. Use the literal string apikey as the username with basic auth, not your login. That trips people up constantly.

Writes rejected at preview. That is the form endpoint doing its job. A required custom field is probably missing. Read the preview response, it names the field.

Your config file contains your API token. It does. Treat .mcp.json or .vscode/mcp.json like a password file and add it to .gitignore before your first commit.

One thing to keep in mind

Work package descriptions and comments are user-provided text, and an agent reading them is reading input from anyone who can file a ticket. The server marks that content with <user-content> tags and flags it as untrusted in its instructions, which helps, but prompt injection through a ticket description is a real path. This is another argument for keeping the write allowlist narrow: the blast radius of a successful injection is exactly the set of projects you listed.

Worth doing?

If you have an Enterprise license, use the official MCP server. It is vendor-supported and it follows the same permissions and business rules as the UI.

If you are on Community Edition and you were about to buy an Enterprise plan purely for MCP access, try this first. An agent that can read your backlog, draft work packages, and file them behind a confirm step covers most of what people actually want, and it costs you a pipx install on top of the OpenProject instance you are already running.

Thanks for reading ❤️ See you in the next one 👋