Your agent, this morning

“I can’t see your project tracker. Could you paste the ticket in here?”

Your agent, patched through to OpenProject.

It reads your work, updates your tasks, and follows your team’s rules.

curl -fsSL https://operator.daer.dev/install.sh | sh

macOS or Linux, x64 or arm64. No Node, no sudo. It checks the SHA-256, then starts the wizard.

The OPerator switchboardSix agents, Claude Code, Claude Desktop, Codex CLI, Gemini CLI, Cursor and opencode, are patched by cables into the jack panel of Op, the operator, and a single line runs from Op to your OpenProject instance.OPERATORSWITCHBOARD · LINE 1LINE OPENClaude CodeClaude DesktopCodex CLIGemini CLICursoropencodeOPyouroperatorOpenProjectopenproject.acme.comThe OPerator switchboardSix agents, Claude Code, Claude Desktop, Codex CLI, Gemini CLI, Cursor and opencode, are patched by cables into the jack panel of Op, the operator, and a single line runs from Op to your OpenProject instance.OPERATORLINE OPENClaude CodeClaude DesktopCodex CLIGemini CLICursoropencodeOPyouroperatorOpenProjectopenproject.acme.com
An illustration of OPerator as a telephone switchboard.

Ask, and it answers from real work.

No more pasting tickets into the chat. Your agent looks the work up, logs the time, and moves the status itself, following the rules your team wrote down.

your agent · openproject.acme.com

you what’s on my plate?

my_work

3 work packages assigned to you in Acme:

Work packages assigned to you
IDTypeStatusSubject
#1284BugIn progressFix login redirect loop
#1301TaskNewMigrate invoice export
#1312TaskNewReview Q3 access audit

A scripted conversation. Acme and its work packages are made up.

About 13 seconds of machine time. The rest is you, pasting a key.

Measured from curl to the wizard’s last card: 4.8 s on a local run, plus about 8 s to download the 49 MiB binary at 50 Mbit/s.

  1. Install

    One line downloads a single binary, checks its SHA-256 against the release, and puts it in ~/.local/bin. Run it again to upgrade; it says what it found.

  2. Answer two questions

    Where your OpenProject lives (a bare openproject.acme.com is fine) and your API key, checked against your instance before anything is saved. Then search for a default project among the ones you can write to.

  3. Ask

    Pick your agents with the arrow keys and each one is patched in. Restart yours and ask it what’s on your plate.

curl -fsSL https://operator.daer.dev/install.sh | sh
▄▄▄▄▄▄
▄▀▀▄▄▄▄▄▄▀▀▄ OPerator installer
▄█▄█▀ ▀█▄█▄ ─────────────────────
███ ██ ██ ███ System Fedora Linux 44 (KDE Plasma Desktop Edition) · x86_64
███▀▀ ▄ ▄ ▀▀███ Installed not yet
█▀▄ ▀▀ ▄▀ Release 1.3.0
▀▄▄▀▀▀▀▀▀▀▀ Into ~/.local/bin
Line check ● ● ● github.com reachable
Dialing ━━━━━━━━━━━━━━━━━━━━━━━━ 100% operator-mcp-linux-x64 · 49.2 MB
Verifying done SHA-256 matches
Patching in done ~/.local/bin/operator-mcp
Connecting you to setup…
▄▄▄▄▄▄
▄▀▀▄▄▄▄▄▄▀▀▄ OPerator setup
▄█▄█▀ ▀█▄█▄ ─────────────────────
███ ██ ██ ███ Profile default
███▀▀ ▄ ▄ ▀▀███ Config ~/.config/operator-mcp/default
█▀▄ ▀▀ ▄▀ Version 1.3.0
▀▄▄▀▀▀▀▀▀▀▀
Where does your OpenProject live? e.g. openproject.acme.com
› https://openproject.acme.com
Your API key. Make one at https://openproject.acme.com/my/access_tokens
(older instances: My account → Access token). It stays on this machine.
› •••••••••••••
Line's open done Ada Lovelace (ada@example.com) · 200 projects
Default project, for when you don't name one Customer Portal
Saved done ~/.config/operator-mcp/default/config.json
Manual done ~/.config/operator-mcp/default/conventions.md · your house rules
Which agents should OPerator patch into? Claude Code, Cursor
Patching in done Claude Code added ~/.claude.json
done Cursor added ~/.cursor/mcp.json
Not installed here: Codex CLI, Gemini CLI, opencode.
Install one later, then run: operator-mcp install
✓ Config file ~/.config/operator-mcp/default/config.json
✓ https://openproject.acme.com is reachable
✓ API key accepted — Ada Lovelace (ada@example.com)
✓ Claude Code runs: ~/.local/bin/operator-mcp
✓ Cursor runs: ~/.local/bin/operator-mcp
╭───────────────────────────────────────────────────────╮
│ │
│ You're patched through. │
│ │
│ Restart Claude Code and Cursor, then ask: │
│ what's on my plate? │
│ │
│ It answers from your real work packages: │
│ #1284 Bug In progress Fix login redirect loop │
│ #1301 Task New Migrate invoice export │
│ #1312 Task New Review Q3 access audit │
│ │
│ Check the line any time: operator-mcp doctor │
│ │
╰───────────────────────────────────────────────────────╯
A recorded run. The instance address is changed for the demo.

Write the house rules once. Every agent follows them.

Each workplace has a short markdown manual that the agent reads at the start of every session. Change the branch rule below and watch the answer change with it.

~/.config/operator-mcp/default/conventions.md

## Git / GitLab

``

- Commit subject: `[#1234] <imperative summary>`

- MR title must contain `#1234` so GitLab links back.

## Workflow

- Move to `In progress` only once a branch exists.

- Never close a work package yourself. QA closes it.

Fill-ins: {type} {wp-id} {slug} {user}. Or try one:

you start on #1284

conventions

Your manual says how to name it, so:

$ git switch -c bug/1284-fix-login-redirect-loop

#1284 moves to In progress now that the branch exists.

20 tools. Each does one job.

This list is what the server itself advertises over MCP, pulled with a real tools/list call when the page was built.

Identity

  • whoamiIdentity and connection state.

    Identity and connection state. Call this first: it tells you which user you are acting as, which OpenProject instance you are on, the default project, whether writes are permitted, and whether this workplace has a conventions manual.

Discovery

  • list_projectsProjects visible to you.

    Projects visible to you. Use the `identifier` value wherever a tool asks for a project.

  • list_usersPeople you can assign work to.

    People you can assign work to. Pass a project to get exactly its assignable members; omit it to search everyone visible to you.

  • get_work_packageFull detail for one work package, including its description and the lockVersion an update needs.

    Full detail for one work package, including its description and the lockVersion an update needs.

  • search_work_packagesFind work packages by project, assignee, status, type, priority, text, or recency.

    Find work packages by project, assignee, status, type, priority, text, or recency. Descriptions are omitted; use get_work_package for one item's full detail.

  • my_workWork packages assigned to you, soonest due first.

    Work packages assigned to you, soonest due first. The usual starting point for a working session.

Tasks

  • create_work_packageCreate a work package in a project.

    Create a work package in a project. Type and subject are required; everything else is optional.

  • update_work_packageChange any subset of a work package's fields.

    Change any subset of a work package's fields. The optimistic lock is handled for you. Pass null for assignee or parent to clear it.

  • comment_work_packageAdd a markdown comment.

    Add a markdown comment. Everyone watching the work package gets a notification.

  • list_activitiesComments and field changes for one work package, oldest first.

    Comments and field changes for one work package, oldest first.

  • link_work_packagesCreate a relation between two work packages, such as one blocking another.

    Create a relation between two work packages, such as one blocking another.

Notifications

  • list_notificationsYour in-app notification feed, newest first.

    Your in-app notification feed, newest first. Each row carries the work package it concerns, so you can triage without a second lookup.

  • mark_notifications_readMark specific notifications read by id, or every notification matching a filter with all: true.

    Mark specific notifications read by id, or every notification matching a filter with all: true. Use this after triaging so the feed stays meaningful.

  • watch_work_packageControl whether you get notified about a work package's future activity.

    Control whether you get notified about a work package's future activity.

Time & metadata

  • list_metadataIds and names for work package types, statuses, priorities, or time entry activities.

    Ids and names for work package types, statuses, priorities, or time entry activities. Call this when a write is rejected for an unknown value, or when you need the exact wording this instance uses.

  • log_timeRecord time spent on a work package.

    Record time spent on a work package. Hours are given as a decimal number; 2.5 means two and a half.

Conventions

  • conventionsThe rules this workplace expects you to follow in OpenProject: branch and commit naming, workflow states, required fields.

    The rules this workplace expects you to follow in OpenProject: branch and commit naming, workflow states, required fields. These are also delivered in the server instructions; re-read them here whenever you are unsure.

  • add_conventionAppend a rule to the workplace manual so it survives this session.

    Append a rule to the workplace manual so it survives this session. Use it when the user states a working rule you would otherwise forget. Appending never removes anything.

  • remove_conventionDelete a rule from the workplace manual.

    Delete a rule from the workplace manual. Set confirm only when the user has explicitly asked you, in this conversation, to remove that rule — never on your own initiative. The file is backed up before any change.

Escape hatch

  • api_requestEscape hatch for anything the other tools do not cover.

    Escape hatch for anything the other tools do not cover. DELETE is refused unless the user set OPENPROJECT_ALLOW_DELETE=1. Returns the raw HAL+JSON response, unflattened. Prefer a dedicated tool when one exists — this one requires you to know APIv3 request shapes, and its responses are large.

Your agent can’t delete anything. By design.

For whoever has to approve the install: each promise below links to the code that keeps it. Read it before you say yes.

  1. There is no delete tool.

    Count them: 20 tools, and not one deletes. An agent can’t remove a work package because it misread a vague instruction.

    Enforced insrc/tools/
  2. The escape hatch refuses DELETE.

    api_request reaches the rest of the API, but it refuses DELETE unless you set OPENPROJECT_ALLOW_DELETE=1 in the server’s environment. An agent can’t set that for itself.

    Enforced insrc/tools/raw.ts
  3. Read-only means read-only.

    With OPENPROJECT_READ_ONLY=1, every create, update, comment, time entry and watch change is refused before a request leaves your machine.

    Enforced insrc/client.ts
  4. It only talks to your instance.

    Every request is built under your instance’s /api/v3 root, and any link that resolves outside it is refused.

    Enforced insrc/client.ts
  5. Your key never travels in plain text.

    A plain http:// address is refused unless the host is your own machine, or you set OPENPROJECT_ALLOW_INSECURE_HTTP=1 yourself. An address without a scheme is taken as https://.

    Enforced insrc/config.ts
  6. Credentials stay in one private file.

    The key is written with 0600 permissions under ~/.config/operator-mcp, never into your agent’s config, so that file stays safe to commit.

    Enforced insrc/config.ts
  7. The installer checks before it installs.

    The binary is checked against the release’s SHA-256 sums. If they don’t match, nothing is installed.

    Enforced ininstall/install.sh

Works with the agent you already use.

The wizard finds the agents on your machine, lets you pick them with the arrow keys, and patches each one in, backing up any file it touches.

Patched in by the wizard

  • Claude Code
  • Claude Desktop
  • Codex CLI
  • Gemini CLI
  • Cursor
  • opencode

Claude Desktop on macOS and Windows; there is no Linux build of it.

One config snippet away

  • VS Code
  • Windsurf
  • Cline
  • Zed
  • anything that speaks MCP over stdio

Two workplaces at once.

Each workplace is a profile with its own key and its own manual. Each registers under its own server name, so both can be connected at the same time and your agent never mixes up one instance with the other.

$ npx operator-mcp setup --profile acme
$ npx operator-mcp setup --profile personal

Questions, answered.

Does my API key leave my machine?

Only to talk to your own OpenProject. It lives in ~/.config/operator-mcp/<profile>/config.json with 0600 permissions, and never appears in your agent’s MCP config.

Do I need Node.js?

Not for the curl install: it fetches a single binary for macOS or Linux, x64 or arm64. The npx route needs Node 22 or newer.

Does it work on Windows?

Yes, through npx operator-mcp setup with Node 22 or newer. The same goes for Alpine.

Can an agent report without changing anything?

Set OPENPROJECT_READ_ONLY=1 in the server’s entry in your MCP config. Reads work normally, and every write is refused before a request leaves your machine.

My agent isn’t on the list.

Any client that runs an MCP server over stdio works. Point it at npx with the arguments -y operator-mcp, or at the installed binary’s absolute path. The README has snippets for VS Code and the common JSON shape.

Can the whole team share one manual?

Set OPENPROJECT_CONVENTIONS_PATH to a file in your repository. The rules are then versioned, reviewed in merge requests, and the same for everyone.

How do I check it’s working, or update it?

operator-mcp doctor runs the same checks as the wizard. To update, run the install line again: it says what it found (an older binary, or a setup that ran through npx), the wizard offers to keep your connection, and each agent is moved onto the binary.

Does it speak Spanish?

The installer, setup, install, doctor and --help do, when your locale is Spanish or you pass --lang es. What your agent reads, tool descriptions and errors, stays in English.

What does it cost? Is it made by OpenProject?

It’s free and MIT-licensed. It is an independent project, not affiliated with OpenProject GmbH.

Patch your agent through.

Run the line, answer two questions, ask what’s on your plate.

curl -fsSL https://operator.daer.dev/install.sh | sh

macOS or Linux, x64 or arm64. No Node, no sudo. It checks the SHA-256, then starts the wizard.