Because the token arrives per request, the running container holds no credentials, and the same instance can serve different users and different OpenProject servers without a redeploy. Version compatibility was handled deliberately rather than generated: the author dropped a generated OpenAPI client because it broke on minor spec differences, and mapped values directly instead, which is why a spread of OpenProject releases works. Pick your transport before you deploy — switching later means restarting with a different protocol setting.
A Java proxy in front of the OpenProject API, packaged as a Docker container. It lets a model list projects, read work packages and write them back, which is what turns 'add acceptance criteria to every epic in this project' into something a model can carry out rather than describe.
- Project and work-package access over the OpenProject API — list projects, pull work packages for a project, analyse them, and write changes back
- Bulk editorial work on a whole project, such as translating every epic or adding INVEST criteria, Gherkin acceptance criteria and a definition of done
- Generating new work packages from a description, so a set of epics can be created from a paragraph about the product
- Authentication per request: your OpenProject API token is sent as a bearer header from the client and is not kept in the container
- Multi-server operation — start the container with `OPENPROJECT_ALLOW_HEADER_BASE_URL` and the target instance travels in an `X-OpenProject-Base-Url` header, so one container serves several OpenProject servers
- Compatibility tested against OpenProject 14, 15, 16.6 and 17.5
Docker, and an OpenProject instance the container can reach — `OPENPROJECT_URL` is set when the container starts and the service listens on port 8080. The client connects over SSE at `/sse` with the API token as an `Authorization: Bearer` header. Spring binds one transport at a time, so a server started for SSE exposes `GET /sse` and `POST /mcp/message`, while the streamable mode exposes a single `/mcp` endpoint instead — the two cannot run together.
One command plus a key — docker run -d -p 0.0.0.0:8080:8080 -e OPENPROJECT_URL=https://${yourOpenProjectUrl} --tmpfs /tmp docker.io/tmskln/spring-openproject-mcp-server:latest, then supply credentials
