Skip to main content
Glama

openproject-mcp

An MCP server over the OpenProject APIv3 — work packages, comments, time entries, documents, versions, categories, memberships, relations, watchers, saved queries, users, and activities. Zero dependencies, stdio transport, one file.

Why this exists

OpenProject ships its own MCP server as of 17.2, but it is an Enterprise add-on (Professional, Premium, Corporate) and is read-only: "Right now OpenProject only offers read-only tools." That rules it out for the job this server does, which is creating and updating work packages.

The community alternatives were surveyed before writing this:

Server

Stack

Stars

Comments

Time entries

Blocker

AndyEverything

Python + uv

72

"Do not use it productively"; 5 delete tools

brunofin

TypeScript

1

4 commits total

Tangaratta

Python + FastMCP

14

SSE-only, fixed port

None combined comments with time entries, and all three carry immaturity warnings. Hence a tightly scoped tool set, with delete tools limited to relations — the one resource where the two linked work packages can't be swapped out, so a full teardown is still the only way to redirect a relation, even though its type/description/lag can now be changed in place.

Related MCP server: OpenProject MCP Server

Tools

Readop_list_projects, op_list_work_packages, op_get_work_package, op_list_reference (types/statuses/priorities/categories/time_activities), op_list_time_entries, op_list_users, op_list_work_package_activities, op_list_documents, op_get_document, op_current_user, op_list_versions, op_list_memberships, op_list_relations, op_list_queries, op_list_work_package_attachments

Writeop_create_work_package, op_update_work_package, op_comment_work_package, op_log_time, op_update_document, op_add_document_attachment, op_create_version, op_update_version, op_create_relation, op_update_relation, op_delete_relation, op_manage_watcher (list/add/remove), op_add_work_package_attachment, op_delete_attachment

15 read tools, 14 write tools. op_list_reference and op_manage_watcher fold what used to be 5 lookup tools and 3 watcher tools into one action/kind-parameterized tool each — fewer entries on every tools/list call, one schema to pick between instead of several near-identical ones.

Lists stay slim — id, subject, status, priority, and the like. op_get_work_package is the one that is genuinely full: description, custom fields, version, category, responsible, the spentTime/estimatedTime/remainingTime aggregates, and createdAt.

Every writable field is writable here

Create and update both take the whole schema-writable set, not a subset: priority, category and version by name; estimatedTime (Work) and remainingTime (Remaining work) as decimal hours, an ISO duration, or null to clear; percentageDone; assignee and responsible (Accountable); and type, which is settable on update, not only at creation. Names are resolved against the instance, and an unknown one fails with the valid values listed — that error is the fallback discovery path when you'd rather not make a separate call; op_list_reference(kind: "categories") and op_list_versions (with op_create_version/op_update_version) cover the same ground up front.

Work, Remaining work and % Complete are one quantity in three views: OpenProject derives the third from the other two, so passing all three at once is refused up front rather than coming back as a 422. Pass at most two.

op_list_projects and op_list_work_packages page via pageSize (capped at 200) and offset, returning total/offset/limit; op_list_time_entries takes pageSize too. On op_list_work_packages, project: "all" searches across every project even when OPENPROJECT_PROJECT_ID is set.

op_list_users resolves assignable principals, and it does not need /api/v3/users — that endpoint answers 403 for an ordinary API key, which used to make assignment unusable. It falls back outwards from the project's available_assignees (which needs only project membership) to /principals to /users, and reports in source which list answered. Because of that, assignee and responsible accept a display name or login as well as an id; a name that matches nothing or matches more than one principal fails with the candidates listed. Groups and placeholder users resolve to their own collections, so assigning a group works.

op_list_work_package_activities reads comments back, the read-your-comments counterpart to op_comment_work_package — named apart from op_list_reference(kind: "time_activities") (time-tracking activity categories) on purpose, since the two used to share a name-collision-prone prefix.

Documents

op_list_documents lists the Documents-module documents, newest first, scoped to the default project (or project: "all"); it filters by search (title) and sorts by sortBy (created_at, updated_at, id) with order. op_get_document is the genuinely full one: title, markdown description, project, dates, and the document's attachments (file name, size, MIME type, upload status, author, download URL).

APIv3 has no document create or deletePOST /api/v3/documents answers 404 on every version, and the official docs call the endpoint "only a stub". Documents are created in the UI; the MCP side covers the rest of the lifecycle: op_update_document (title and/or markdown description — there is no lockVersion on documents, so concurrent edits are last-write-wins) and op_add_document_attachment, which uploads base64 file bytes as multipart/form-data. Uploads are capped at the instance's own maximumAttachmentFileSize from /api/v3/configuration (5 MiB fallback). Both tools need the manage_documents permission; reading needs view_documents.

Attachments

Files can also be attached straight to a work package, without going through a Document. op_list_work_package_attachments/op_add_work_package_attachment are the work-package-scoped twins of op_get_document's embedded attachments and op_add_document_attachment — same base64-as-multipart upload, the same maximumAttachmentFileSize cap. op_delete_attachment is shared by both: DELETE /api/v3/attachments/{id} is keyed by the attachment's own id regardless of which container it was uploaded to, so one delete tool covers document and work-package attachments alike. Uploading needs edit permission on the work package; deleting needs edit permission on the container or authorship of the attachment.

The document API has two quirks the server absorbs. The description {"raw": …} form documented for every other resource corrupts document text on documents — the stored value becomes Ruby's '{raw: "…"}' literal, and on 17.3.1 ASCII-only bodies even 500 the response (verified live; the update contract is unchanged through 17.7, whose OpenAPI spec still documents the same broken form) — so the server sends the plain string the UI itself sends, which stores cleanly on every version. And filters on the collection take numeric project ids only (never identifiers), which is why op_list_documents' project argument is resolved internally, exactly like the time_entries filter.

Writes default to notify=falseop_log_time doesn't even expose the flag — so bulk agent activity does not email the whole project. op_update_work_package fetches lockVersion itself, so a concurrent edit fails loudly instead of silently overwriting; parent: null on an update clears the parent link. Arguments are validated up front: ids must be positive integers, dates must be YYYY-MM-DD, and unknown statuses/activities/ids fail with messages that name the offending value.

Versions, categories, memberships, relations, watchers, queries

op_current_user reports the API key's own account — useful for confirming which principal is acting before a write. op_list_versions returns a project's sprints/milestones with status and dates; status filters the result locally, since the collection takes no server-side filter for it. op_create_version/op_update_version cover the rest of the lifecycle — status is a plain open/locked/closed string, not a link, unlike a work package's status. op_list_reference(kind: "categories") lists a project's categories.

op_list_memberships reports who has which role on a project; like time_entries and documents, the collection's project filter takes only the numeric id, resolved internally.

op_list_relations/op_create_relation/op_update_relation/op_delete_relation manage the links between work packages — blocks, precedes, relates, duplicates, and their inverses. op_create_relation names the "to" work package and a type; op_update_relation and op_delete_relation both take the relation's own id (from op_list_relations), not either work package's id. op_update_relation can change type, description, and lag in place — mirroring the API's own restriction, it cannot repoint a relation at a different pair of work packages, so that still means delete and recreate.

op_manage_watcher (action: "list"|"add"|"remove") manages who is notified on a work package. user is required for add/remove and accepts a display name or login the same way assignee/responsible do, resolved through the same project-scoped principal lookup.

op_list_queries lists saved views, optionally scoped to a project (project: "all" for every project); starred is present only on instances that expose it.

Configuration

Resolution order:

  1. OPENPROJECT_ENV_FILE — path to a .env to read OPENPROJECT_* from. Values in an explicitly named .env win over the ambient environment. Deliberate: a stale exported OPENPROJECT_API_KEY silently shadowing a freshly rotated one in .env cost hours of debugging — the API reports it as 401 You did not provide the correct credentials, indistinguishable from a bad key. Naming a file is a deliberate act; an inherited variable usually is not.

  2. OPENPROJECT_URL (or OPENPROJECT_BASE_URL) + OPENPROJECT_API_KEY + OPENPROJECT_PROJECT_ID from the environment

  3. ~/.config/openproject-mcp/config.json{"url": "...", "apiKey": "...", "defaultProject": "..."} (consulted only when a URL or key is still missing)

OPENPROJECT_PROJECT_ID sets the default project, so most calls need no project argument.

OPENPROJECT_HOURS_DB (optional) points the hours-ledger tap at a SQLite cache; it defaults to ~/Projects/hours/hours.db. An empty value disables the tap.

The hours-ledger tap

This machine runs a second, unrelated tool — the hours tracker at ~/Projects/hours — that keeps the team sheet's side of the time ledger in SQLite (entry rows keyed by OpenProject work package id, statuses draft/approved/pushed, plus a cached task row per package). It also writes OpenProject time entries of its own when a tracked entry carries a task id, which makes it a second writer alongside op_log_time.

So this server peeks at that cache — read-only, always best-effort — and reports the local side where it matters:

  • op_get_work_package returns hoursLedger next to spentTime: the sheet's own minutes for that task, split into draft/approved/pushed, plus the cached task subject/status when known.

  • op_log_time returns hoursLedger alongside the created entry, so the sheet's side of the ledger is visible at the moment of the write.

hoursLedger is present only when the cache is installed and readable; absent otherwise. The two ledgers describe the same work, so they are never summedspentTime and sheet.totalMinutes must be read as alternatives, not added. Nothing here blocks or dedupes a write; the tap exists to inform the caller, and the server is fully functional with the hours tool absent, disabled (OPENPROJECT_HOURS_DB=""), or unreachable. The cache is SQLite in WAL mode, and the tap opens it read-only with short queries, so it is safe to run while the hours CLI, MCP server, or collector daemon are writing. Requires Node ≥ 22.5 (built-in node:sqlite); on older Node the tap stays off and nothing else changes.

When both MCP servers are registered in the same client, the hours server's task_hours {taskId, refresh} tool is the fuller union view (OpenProject's spentTime plus the local ledger in one call), and op_list_time_entries verifies time entries the hours push write-through created.

Auth is HTTP Basic with the literal username apikey and the key as password. The key is never written to stdout, stderr, or any tool result — and the URL must be https (plain http is rejected unless the host is localhost or 127.0.0.1), because the key must not travel in the clear.

OPENPROJECT_TIMEOUT_MS sets the per-request timeout (default 30000). Transient failures (429, 502, 503, 504) are retried twice with backoff, honoring Retry-After — GETs only; writes are never retried, so a timed-out create is not silently replayed.

.env and config.json should be chmod 600 — the server warns on stderr when either is readable by others. An unreadable or missing OPENPROJECT_ENV_FILE prints a stderr warning and falls through to the remaining sources instead of failing silently.

Install

Requires Node.js ≥ 18. The server is a single self-contained file with no dependencies — no build step, nothing to compile. Install it in one line, then register it with your client below.

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/DDeluca06/openproject-mcp/master/scripts/install.sh | bash

Windows (PowerShell):

irm https://raw.githubusercontent.com/DDeluca06/openproject-mcp/master/scripts/install.ps1 | iex

Both download server.mjs into ~/.local/bin (Windows adds an openproject-mcp.cmd shim, since shebangs don't work there) and print the next steps. If ~/.local/bin isn't on your PATH (macOS and Windows by default), the installer tells you how to add it:

export PATH="$HOME/.local/bin:$PATH"   # put this line in ~/.zshrc or ~/.bashrc

GUI-launched apps (VS Code, some terminals) inherit a minimal PATH — if your client can't find openproject-mcp, use the absolute path the installer printed.

Alternative (npm, all three platforms) — installs the same one file with a proper bin entry:

npm install -g --allow-remote https://github.com/DDeluca06/openproject-mcp/tarball/master

--allow-remote is required on npm ≥ 12, which blocks GitHub tarballs by default; older npm versions ignore the flag.

From a clone (development, or if you'd rather not pipe a script into a shell):

git clone https://github.com/DDeluca06/openproject-mcp.git
cd openproject-mcp
cp .env.example .env && chmod 600 .env   # then paste your API key into .env
node server.mjs                          # or: npm start

There is nothing to install — npm install fetches no dependencies. Point your client at the absolute path to server.mjs instead of the openproject-mcp command.

Either way, verify the server starts: openproject-mcp should run and wait on stdin.

Claude Code

claude mcp add openproject -s user \
  -e OPENPROJECT_URL=https://projects.example.com \
  -e OPENPROJECT_PROJECT_ID=your-project-identifier \
  -e OPENPROJECT_ENV_FILE=/path/to/.env \
  -- openproject-mcp

The snippet sets both OPENPROJECT_URL and OPENPROJECT_ENV_FILE; if the .env also holds OPENPROJECT_URL, the -e value is ignored — deliberate, so a freshly rotated .env key wins.

OpenCode

In ~/.config/opencode/opencode.json, under the top-level mcp key — not nested under mcp.servers, which fails schema validation and silently disables every server in the file:

{
  "mcp": {
    "openproject": {
      "type": "local",
      "command": ["openproject-mcp"],
      "enabled": true,
      "environment": {
        "OPENPROJECT_URL": "https://projects.example.com",
        "OPENPROJECT_PROJECT_ID": "your-project-identifier",
        "OPENPROJECT_ENV_FILE": "/path/to/.env"
      }
    }
  }
}

Verify with claude mcp get openproject and opencode mcp list.

Tests

npm test              # mock suite (no credentials needed) + live smoke test
npm test -- --writes  # smoke also creates a real work package, comment, and time entry

npm test runs test/mock.test.mjs (a deterministic fake APIv3 server, 151 checks, no credentials) and then test/smoke.mjs against the live instance; the smoke test self-skips when OPENPROJECT_URL is unset. --writes creates a real work package, comment, and time entry — the work package is clearly marked as a smoke test, then permanently deleted through the APIv3 DELETE endpoint after the run (its time entries go with it). Documents have no APIv3 create, so the write smoke instead renames an existing document to a SMOKE TEST … title, immediately reverts title and description, and uploads a tiny attachment that is then deleted through op_delete_attachment — if the revert or delete is interrupted, the remaining mark is a SMOKE TEST title or a smoke-test-*.txt attachment. If the API key lacks the delete permission the deletion is skipped loudly (DELETE 403), and the work package is left closed for manual cleanup; pass --keep to always leave the records in place.

APIv3 quirks this server absorbs

Each of these was found by a failing call, not from the docs:

  • A parentless work package still returns parent: {href: null} rather than omitting the link, so naive parent.href.split() throws.

  • time_entries rejects a project identifier and demands the numeric id, unlike the work_packages endpoints which take either. Resolved and cached internally.

  • The work-package filter on time_entries is entity, not work_package — the resource was generalised to attach to meetings too, and the old filter name no longer exists.

  • TimeEntriesActivity has no collection endpoint. The server first asks /api/v3/time_entries/schema for activity.allowedValues; instances that omit it fall back to probing /api/v3/time_entries/activities/{id} in parallel batches of 12, stopping after the first fully-missed batch (capped at id 120). The set is cached for 30 minutes. That plural /time_entries/activities/{id} path is an undocumented alias — it works, but it is not in the API docs.

  • hours is an ISO-8601 duration (PT1H30M; day components like P1DT2H parse too). op_log_time accepts decimal hours and converts; reads return both forms plus a decimal total. A duration that will not parse comes back as hoursDecimal: null with a parseWarnings count in op_list_time_entries — not silently as 0.

  • op_log_time's default spentOn is the local calendar date, not UTC — "today" in the server's timezone.

  • Time entries are always attributed to the API key's own user. OpenProject makes that field read-only, so time cannot be logged on someone else's behalf.

  • The Documents endpoint has no create (POST /api/v3/documents → 404) and no delete, and its own docs say "only a stub for now". PATCH writes title/description, attachments upload below.

  • A document's description must be PATCHed as a plain string, not the {"raw": …} hash (see the Documents section) — on 17.3 the hash form stores Ruby's inspected literal and the response can arrive as a 500 with text must be UTF-8 encoded even though the write committed.

  • Uploading a document attachment is multipart, but the metadata part must be a plain form-data string: sending it as a blob makes undici attach filename="blob", Rack treats the part as a file upload instead of JSON, and the API answers 500 no implicit conversion of ActiveSupport::HashWithIndifferentAccess into String.

  • The documents collection filter takes numeric project ids only — an identifier in filters=[{"project":…}] fails, resolved and cached internally like time_entries.

Available Tools

18 tools
op_add_document_attachmentA

Upload a file to a document: the API key needs the manage_documents permission in the document's project. content is the file bytes as base64. The upload is capped at the instance's attachment size limit, read from /api/v3/configuration.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesDocument id to attach to.
contentYesFile bytes, base64-encoded.
fileNameYesFile name, e.g. "quarterly-report.pdf".
contentTypeNoMIME type. Defaults to application/octet-stream.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral context beyond the annotations: it discloses the required API permission, the base64 encoding requirement for content, and the instance-level size limit retrieved from /api/v3/configuration. These details help the agent anticipate constraints and failure conditions. It does not contradict the annotations, which already signal a non-read-only, non-idempotent operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the core action, followed by permission and payload details. Every sentence contributes useful operational information, though the phrase 'content is the file bytes as base64' partially duplicates the schema description. Overall, it is efficient without being bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers the key prerequisites: required permission, encoding of the file content, and the size limit. The input schema handles parameter requirements and defaults. The main gap is that it does not describe the expected response or error behavior, but this is not critical given the schema and annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description restates that content is base64 and adds the size cap, but it does not provide substantial new meaning for id, fileName, or contentType beyond what the schema already says. This meets the baseline but does not rise above it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Upload a file to a document.' This clearly identifies the action and target, and it is distinct from sibling tools like op_get_document and op_update_document, which describe different operations on documents. No ambiguity about what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides useful operational context, such as requiring the manage_documents permission and the attachment size cap. However, it does not explicitly state when to use this tool versus any alternative, nor does it mention exclusions or fallback options. Usage is implied by the tool's name and purpose rather than explicitly guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_comment_work_packageA

Add a markdown comment to a work package. Notifications are off unless notify=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
notifyNoSend email notifications. Default false.
commentYesMarkdown.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a mutating, non-idempotent operation. The description adds valuable behavioral detail beyond the annotations by disclosing that notifications are disabled unless notify=true, which is a meaningful side-effect control for an agent. It does not contradict any annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no filler. The primary action is front-loaded, and the notification caveat earns its place as essential side-effect information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter tool, the description covers the core action, the comment format, and the notification behavior. It does not explain what the response contains or that repeated calls create duplicate comments, but the lack of an output schema and the straightforward nature of the operation keep this from being a major gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67% and the description adds only limited meaning beyond the schema: it restates the notification default behavior and the markdown format already present in the schema. The id parameter remains minimally documented, but this is sufficient for a simple numeric identifier.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Add a markdown comment') with a clear resource ('work package') and format ('markdown'). It is immediately distinguishable from sibling tools like op_update_work_package and op_create_work_package because the intent is to add a comment, not create or update the package itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies when to use the tool but does not explicitly state when not to or name alternatives. The sibling list helps infer that this tool is for commenting rather than creating or updating work packages, but the description itself provides no direct exclusion, alternative, or condition-based selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_create_work_packageA

Create a work package. Returns the created id. Notifications are off unless notify=true. Every change to a tracked project needs one of these before work starts.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoType name, e.g. "Task", "Milestone", "Summary task". Default "Task".
notifyNoSend email notifications. Default false.
parentNoParent work package id.
dueDateNoYYYY-MM-DD.
projectNoProject identifier. Defaults to OPENPROJECT_PROJECT_ID.
subjectYes
versionNoVersion name, e.g. "Sprint 2".
assigneeNoOwner: a user id, or a display name/login from op_list_users.
categoryNoCategory name. Must already exist on the project.
priorityNoPriority name, e.g. "Low", "Normal", "High", "Immediate".
startDateNoYYYY-MM-DD.
descriptionNoMarkdown body.
responsibleNoAccountable: a user id, or a display name/login.
estimatedTimeNoWork: decimal hours (8) or an ISO duration ("PT8H").
remainingTimeNoRemaining work: decimal hours or an ISO duration.
percentageDoneNo0-100. Give at most two of this, estimatedTime, remainingTime.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal a mutating, non-idempotent, non-destructive operation; the description adds the useful fact that notifications are disabled by default unless notify=true, and that the created id is returned. It doesn't overclaim or contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no filler: purpose, return value + notification behavior, and usage context. The most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 16-parameter creation tool with no output schema, the schema plus this description is sufficient: required fields, defaults, and value formats are in the schema, while the description supplies the missing result (created id) and default notification behavior. The tracked-project prerequisite supplies the operational context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 94% schema description coverage, the schema already documents all parameters in detail, so the description carries no extra parameter burden. It only reinforces the notify default already present in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action and resource — 'Create a work package' — and notes the return value. The prerequisite sentence ('Every change to a tracked project needs one of these before work starts') distinguishes creation from the update/comment siblings, so an agent can identify the right verb.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Says creation must precede changes to tracked projects, giving a concrete condition for when this tool is appropriate. It doesn't explicitly state that existing packages should go to op_update_work_package, so the when-not guidance is implied rather than named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_get_documentA
Read-onlyIdempotent

Fetch one document in full detail: title, markdown description, project, dates, and its attachments (file name, size, type, status, download URL).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesDocument id.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive behavior. The description adds value by disclosing what the fetch returns: title, markdown description, project, dates, and attachment details including file name, size, type, status, and download URL. This is useful behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, tightly written sentence that front-loads the core action and resource, then lists the returned content without wasted words. Every element earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-by-id tool with one fully documented parameter, the description adequately covers return values by enumerating the main fields. No output schema exists, but the description supplies enough expectation-setting for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the only parameter 'id' is already described as 'Document id.' The description does not add additional parameter-level meaning beyond confirming that the fetch targets one document by id, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb ('Fetch'), a specific resource ('one document'), and enumerates the returned fields. It clearly distinguishes from op_list_documents, which lists documents, and from mutation siblings like op_update_document.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies use when a single document's full detail is needed, and the sibling list tool is implicitly the alternative for browsing. It does not explicitly state when not to use it or name alternatives, but the context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_get_work_packageA
Read-onlyIdempotent

Fetch one work package in full detail, including custom fields, priority, version, and time aggregates. When the local hours ledger is installed, hoursLedger reports the sheet side of the task's time separately — never summed with spentTime.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesWork package id.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior, so the description's burden is lower. It adds useful behavioral context beyond the schema, especially the hoursLedger caveat explaining that it is reported separately and never summed with spentTime. This goes beyond what annotations alone reveal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The primary purpose and scope are stated first, and the only additional sentence is a specifically valuable behavioral nuance about hoursLedger. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, read-only fetch tool, this is nearly complete: it states what the response will include and highlights an important edge case. There is no output schema, but the description names the major available fields. It does not cover not-found behavior or error cases, but those are less critical given the tool's simplicity and read-only annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully documents the single required parameter 'id' as 'Work package id.', so the description does not need to repeat it. The description adds no extra semantic detail about the id beyond the schema, which aligns with the baseline score for 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Fetch one work package in full detail.' It also enumerates the included content (custom fields, priority, version, time aggregates), which distinguishes it clearly from sibling list and mutation tools such as op_list_work_packages and op_update_work_package.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the right usage context: use this tool when you need a single work package with full detail, as opposed to a list of packages. It does not explicitly name an alternative or state when not to use it, but the 'one' vs. 'list' framing gives an agent sufficient context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_activitiesB
Read-onlyIdempotent

List comments and activities on a work package.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesWork package id.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already cover safety semantics with readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds that the result is a list of comments and activities for a work package, but omits details like pagination, ordering, or permission requirements; it is consistent and adequate, though not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one front-loaded sentence with no filler. Every word contributes to identifying the operation and target resource.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter, read-only tool with comprehensive annotations, the description plus schema is largely sufficient. However, the lack of an output schema and absence of any usage/alternative guidance leave minor gaps about the exact return shape and when to choose this tool over related activities/list tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents 'id' as 'Work package id.' The description references 'a work package,' aligning with the parameter, but does not add further semantics such as required-ness or any additional constraints, which is acceptable for a single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a clear verb ('List') and a specific resource ('comments and activities on a work package'), so an agent can identify the operation. It does not explicitly contrast with sibling tools such as op_list_time_entry_activities or op_list_work_packages, so it stops short of the highest sibling-differentiation standard.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives such as op_get_work_package, op_comment_work_package, or op_list_time_entry_activities. No conditions, exclusions, or prerequisites are stated, so the agent must infer usage from the name and resource.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_documentsA
Read-onlyIdempotent

List documents (the Documents module), newest first. A document is a titled container for attachments with a markdown description. APIv3 has no document create or delete (UI-only), so documents are read and updated only. project: "all" searches every project even when OPENPROJECT_PROJECT_ID is set.

ParametersJSON Schema
NameRequiredDescriptionDefault
orderNoSort direction. Default "desc".
offsetNoPage offset. Default 0.
searchNoFree-text title search.
sortByNoSort key. Default "created_at".
projectNoProject identifier or id. Defaults to OPENPROJECT_PROJECT_ID; "all" for every project.
pageSizeNoDefault 200.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description adds meaningful behavioral facts: APIv3 has no create/delete for documents, documents are read/updated only, 'all' searches every project even when OPENPROJECT_PROJECT_ID is set, and results are newest first. This gives the agent a clear picture of what the operation will and will not do.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three focused sentences: purpose/ordering, entity definition/API constraint, and the project special case. The most actionable information is front-loaded and no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list operation, the description plus fully-documented schema covers purpose, ordering, scoping, and domain semantics. It does not describe the response shape, and there is no output schema, but the phrase 'list documents' plus the document definition makes the expected return sufficiently clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters. The description adds at most the nuance that project:'all' overrides OPENPROJECT_PROJECT_ID and the 'newest first' default behavior, which is useful but not a major addition beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List documents (the Documents module), newest first.' It also clarifies the document entity and notes APIv3's read/update-only scope, which distinguishes it from sibling tools like op_get_document and op_update_document.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (to list documents) and provides useful domain constraints ('no document create or delete (UI-only), so documents are read and updated only'), but it never explicitly names alternatives such as op_get_document for a single document or op_update_document for modifications. Usage guidance is therefore mostly implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_prioritiesA
Read-onlyIdempotent

List priority names, so a create or update can name one that exists.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds that the return value is a list of priority names, but says nothing about ordering, completeness, or failure behavior; with the simple open-world list tool this is acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence with no filler; the action, resource, and purpose are front-loaded. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter read-only list, the description tells the agent what it returns (names) and why it matters (valid value for create/update). It relies on sibling context to infer this means work-package priorities, but no other return details are essential for such a simple tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and an empty input schema, so the baseline is 4; there is no parameter ambiguity for the description to resolve. The phrase 'priority names' clarifies the kind of value the caller will receive but is not parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'List priority names', and states its purpose ('so a create or update can name one that exists'). It clearly differentiates from sibling list tools because it is the only one exposing priority values.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly frames when the tool is useful: before a create or update that needs a valid priority name. It does not name alternatives or exclusions, but the context is clear enough for an agent to select it over status/project/type list siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_projectsA
Read-onlyIdempotent

List the OpenProject projects visible to the API user, with their identifiers. Paginated via pageSize and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
offsetNoPage offset. Default 0.
pageSizeNoDefault 200.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only, open-world, idempotent, and non-destructive. The description adds behavioral value by stating the result is scoped to what the API user can see and that results are paginated through pageSize and offset.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the core action and scope first, followed by pagination. Every sentence earns its place and no redundant wording appears.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, read-only list operation with rich annotations, the description covers purpose, user-visible scope, included data, and pagination. It doesn't describe the response shape, but the absence of an output schema is mitigated by the simplicity and by 'with their identifiers.'

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% parameter coverage, including defaults for offset (0) and pageSize (200). The description only restates that pagination is controlled by these parameters, adding no new semantic detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'List' with the resource 'OpenProject projects' and defines the scope ('visible to the API user') and included data ('identifiers'). This clearly distinguishes it from the work-package and document siblings since the resource is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states the operation's context: listing projects visible to the current API user with pagination. It doesn't explicitly name alternatives or conditions, but no sibling is another project-list operation, so the lack of exclusions is not a material gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_statusesA
Read-onlyIdempotent

List every status name, so an update can name one that exists.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is clear. The description adds that the tool enumerates all status names, but does not disclose details such as pagination, ordering, or whether the return format includes more than names. Still, it adds modest context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, compact sentence that leads with the action and resource, then justifies the purpose. Every word contributes value and there is no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only list tool, the description fully communicates what the agent will get (status names) and why it matters (valid values for updates). The annotations cover safety and mutability, so no further context is necessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and schema coverage is trivially complete. With no parameters to document, a baseline of 4 is appropriate; the description correctly focuses on the tool's output rather than input.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and resource ('every status name'), and clarifies the purpose ('so an update can name one that exists'). This distinguishes it from sibling tools like op_list_types or op_list_priorities, which target different enumerations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a clear usage context: call this before performing an update that needs a valid status name. It does not explicitly name alternatives or exclusions, but the use case is evident and the tool name itself disambiguates from sibling list tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_time_entriesA
Read-onlyIdempotent

List logged time. Hours are returned both as ISO-8601 duration and as a decimal, plus a total, so "how much time went into this" needs no arithmetic downstream.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest spentOn, YYYY-MM-DD. Requires "from".
fromNoEarliest spentOn, YYYY-MM-DD. Requires "to".
userNo"me", or a user id.
projectNoProject identifier. Defaults to OPENPROJECT_PROJECT_ID.
pageSizeNoDefault 200.
workPackageNoOnly entries against this work package id.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is established. The description adds genuinely useful behavioral detail about the return format: both ISO-8601 duration and decimal hours plus a total, which helps the agent understand output without an output schema. This goes beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no fluff. The core purpose is front-loaded, and the second sentence adds practical value about the returned format. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that this is a simple read-only list tool with a fully described schema and read-only annotations, the description is almost complete. It explains the key return-value detail that would otherwise be missing without an output schema. It does not mention pagination or default project behavior, but those are partially covered by parameter descriptions and are minor for this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters are already documented. The description does not add meaning beyond what the schema provides, but it also does not need to. It mentions no parameter-specific behavior, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('List') and the resource ('logged time'). It is distinct enough from siblings like op_log_time (which creates time entries) and op_list_time_entry_activities (which lists activity types). However, it could more explicitly say 'time entries' and distinguish itself as the read-only listing sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance about when to use this tool versus alternatives, such as op_log_time for creating entries or op_list_time_entry_activities for activity types. The description simply states what it does without addressing selection criteria, filter combinations, or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_time_entry_activitiesA
Read-onlyIdempotent

List the time-entry activity categories (Management, Development, …) with their ids. Needed to log time under the right category.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the purpose context ('Needed to log time') but no additional behavioral details such as pagination, ordering, or configuration nature; this is acceptable for a simple list tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no redundancy. The core action and output are stated first, and the purpose sentence adds essential context for when the tool matters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless list tool with strong annotations, the description adequately states what is returned (activity categories with ids) and why it is needed. No output schema exists, but the return content is simple and sufficiently described.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters and schema description coverage is 100%, so there are no parameter semantics for the description to clarify. With no parameters, the baseline is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and resource ('time-entry activity categories'), names example categories, and states the output includes ids. It clearly differentiates from sibling op_list_activities by scoping to time-entry activity categories needed for logging time.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies this tool should be used before logging time, specifically to choose the right category for op_log_time. It does not explicitly name alternatives or state when not to use it, but the context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_typesB
Read-onlyIdempotent

List the work package types available in a project, with their names.

ParametersJSON Schema
NameRequiredDescriptionDefault
projectNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false, so the safety profile is clear. The description adds modest context by saying results are scoped to a project and include names, but it does not disclose ordering, pagination, or behavior when project is omitted. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with no filler; the verb and object are front-loaded and every word contributes. It is appropriately sized for a simple list operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, no-output-schema list tool, the description captures the essential operation and return content, and annotations cover side-effect safety. Missing information about the project parameter's accepted identifier format and any behavior when no project is provided leaves a noticeable but not severe gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single 'project' parameter has no schema description (0% coverage), and the description only says 'in a project,' leaving the value format and optionality unclear. The agent receives no information about whether to pass an ID, slug, or object, so the description does not compensate for the low schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'List' with the resource 'work package types' and narrows scope to 'a project.' Among siblings, this is clearly distinct from op_list_work_packages and other reference-data list tools. The phrase 'with their names' also sets an expectation about the response content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given about when to choose this tool over siblings like op_list_work_packages or op_list_activities, nor any conditions that would make it the appropriate choice. The only implied context is that the caller wants work package types, but exclusions and alternatives are absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_usersA
Read-onlyIdempotent

List the principals that can own a work package, with their ids. Falls back from the project's assignable users to /principals to /users, so it works on a key that cannot read /api/v3/users. source reports which list answered.

ParametersJSON Schema
NameRequiredDescriptionDefault
projectNoProject identifier for assignable users. Defaults to OPENPROJECT_PROJECT_ID; "all" for the instance-wide list.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false. Beyond that, the description discloses the multi-stage fallback resolution order and the 'source' field that reports which list answered — behavior an agent genuinely needs to interpret why result sets differ. This adds meaningful context without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the core function is front-loaded in the first sentence, the second explains the critical fallback behavior, and the third clarifies a response field. There is zero filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter read-only tool whose safety profile is covered by annotations, the description captures the essential complexity: the fallback order, restricted-key compatibility, and the source marker. The only gap is the full response shape, but no output schema exists and the description does reveal the id and source elements, making this near-complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%; the input schema already documents the project parameter, its default (OPENPROJECT_PROJECT_ID), and the 'all' sentinel. The description's phrase 'the project's assignable users' echoes the schema rather than adding new meaning, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('List the principals that can own a work package, with their ids'), which cleanly differentiates it from the sibling list tools (op_list_projects, op_list_work_packages, op_list_types, op_list_statuses). The 'principals that can own a work package' framing is precise and not a generic user-listing tautology.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The fallback chain explanation ('Falls back from the project's assignable users to /principals to /users, so it works on a key that cannot read /api/v3/users') gives clear context on when this tool is the right choice — namely when credentials lack access to the users endpoint. However, it never names an alternative tool or an explicit when-not-to-use condition, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_list_work_packagesA
Read-onlyIdempotent

List work packages, newest-id last. Defaults to open items only in the default project. status must be open, closed, or all — "all" includes closed items. project: "all" searches across every project even when OPENPROJECT_PROJECT_ID is set.

ParametersJSON Schema
NameRequiredDescriptionDefault
offsetNoPage offset. Default 0.
searchNoFree-text subject search.
statusNoDefault "open".
projectNoProject identifier, or "all". Defaults to OPENPROJECT_PROJECT_ID.
pageSizeNoDefault 200.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is known. The description adds meaningful behavioral context beyond that: ordering by newest-id last, default status/project behavior, and the fact that project=all overrides OPENPROJECT_PROJECT_ID. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences and wastes no words. It front-loads the core action and ordering, then supplies the most important defaults and special cases in a compact, readable structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list operation with all parameters optional and fully described in the schema, the description is complete enough to guide correct invocation. It covers defaults, allowed status values, cross-project behavior, and ordering; annotations cover safety, and the schema covers pagination/search parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameters are already documented. The description adds value by clarifying that status=all "includes closed items" and that project=all searches across every project even when OPENPROJECT_PROJECT_ID is set, which goes beyond the schema's concise default-value notes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: "List work packages," which clearly identifies the operation. It further distinguishes the tool from siblings like op_get_work_package by implying a collection-level query and adds useful ordering/scoping details (newest-id last, default project, status filtering).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: it lists work packages with defaults for status and project, and explains special values like status=all and project=all. It does not explicitly mention alternatives such as op_get_work_package for single-resource retrieval, so it stops short of a full when/when-not comparison.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_log_timeA

Log time against a work package. Accepts decimal hours (1.5) or an ISO-8601 duration ("PT1H30M"). The entry is always attributed to the API key's own user — OpenProject makes that field read-only, so time cannot be logged on someone else's behalf. When the local hours ledger is installed, the result includes hoursLedger (the sheet's side for this task) so double-logging across the two ledgers is visible at the moment of the write.

ParametersJSON Schema
NameRequiredDescriptionDefault
hoursYesDecimal hours (1.5) or ISO-8601 duration ("PT1H30M").
commentNoWhat the time went on.
spentOnNoYYYY-MM-DD. Defaults to today.
activityNoActivity name or id. Defaults to the instance default.
workPackageYesWork package id to log against.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds genuinely valuable behavior beyond the annotations: the entry is always attributed to the API key's own user because OpenProject makes that field read-only, and the result includes hoursLedger when the local ledger is installed, making double-logging visible at write time. This is exactly the kind of context (auth constraints, side-effect visibility) that annotations alone do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: the core action, the hours format nuance, the attribution constraint, and the ledger side-effect. The hours-format sentence slightly duplicates the schema's hours description, but it is a critical calling detail worth front-loading. No filler or repetition of annotation flags.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter write tool with no output schema, the description covers the most decision-relevant nuances: accepted hours formats, attribution limits, and the conditional hoursLedger field in the result. It stops short of describing the general return shape or failure behavior, but the coverage is well above the minimum viable level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description restates the hours format (decimal or ISO-8601) that the schema already documents, adding no new meaning for comment, spentOn, activity, or workPackage. The description neither compensates for a gap nor adds semantic depth beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence "Log time against a work package" uses a specific verb and resource, clearly distinguishing this write operation from the sibling listing tool op_list_time_entries and from op_comment_work_package. An agent can determine what this tool does and what it is not without deep schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is strongly implied by the name and first sentence, but the description never explicitly states when to choose this tool over an alternative (e.g., when to use op_list_time_entries to read existing entries, or op_list_time_entry_activities to resolve activity values). No exclusions or routing conditions are given, leaving usage to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_update_documentA
Idempotent

Update a document title and/or description. The description replaces the whole markdown body. Documents carry no lockVersion, so concurrent edits are last-write-wins — unlike work packages, the API offers no optimistic locking. The "description" {"raw": …} form documented for other resources corrupts the stored text on documents (verified on 17.3, contract unchanged through 17.7); a plain string is what the UI itself sends.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
titleNoNew title (max 255 characters).
descriptionNoReplaces the whole markdown body.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false, openWorld=true, idempotent=true, destructive=false. The description adds critical behavioral detail beyond those flags: the description field replaces the entire markdown body, concurrent edits are last-write-wins with no locking, and the {'raw': ...} form corrupts stored text while a plain string is the safe format. This is exactly the kind of context an agent needs before invoking the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, with the core action and scope front-loaded. Every sentence earns its place: the replacement semantics, the concurrency/locking caveat, and the serialization pitfall are all actionable and non-redundant with the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation tool with no output schema and simple annotations, the description covers the key hazards an agent must know: whole-body replacement, last-write-wins concurrency, and the correct string format for description. Nothing essential to calling the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents title and description with 67% coverage. The description adds value by clarifying that title and/or description can be updated and by warning that the description parameter must be a plain string, not the {'raw': ...} object used elsewhere. It does not add meaning for the id parameter or title max-length beyond what the schema already provides, so it stops short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update a document') with a clear scope ('title and/or description'), and further clarifies that the description replaces the whole markdown body. It also contrasts documents with work packages, which distinguishes it from the sibling op_update_work_package even without reading that tool's schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational context: it is for updating document title/description, and it explicitly notes that unlike work packages, documents have no lockVersion and are last-write-wins. This effectively warns against expecting optimistic locking and points to the work-package tool as the one that has it, though it stops short of explicitly naming the alternative tool for work-package edits.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

op_update_work_packageA
Idempotent

Update a work package. lockVersion is fetched automatically, so concurrent edits fail loudly rather than silently overwriting. Notifications are off unless notify=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
typeNoType name, e.g. "Task", "Milestone", "Summary task".
notifyNoSend email notifications. Default false.
parentNoNew parent work package id, or null to clear.
statusNoStatus name, e.g. "In progress", "Closed".
dueDateNo
subjectNo
versionNoVersion name, e.g. "Sprint 2".
assigneeNoOwner: a user id, or a display name/login from op_list_users.
categoryNoCategory name. Must already exist on the project.
priorityNoPriority name, e.g. "Low", "Normal", "High", "Immediate".
startDateNo
descriptionNoReplaces the whole markdown body.
responsibleNoAccountable: a user id, or a display name/login.
estimatedTimeNoWork: decimal hours (8), an ISO duration ("PT8H"), or null to clear.
remainingTimeNoRemaining work: decimal hours, an ISO duration, or null to clear.
percentageDoneNo0-100. Give at most two of this, estimatedTime, remainingTime.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavioral context beyond annotations: automatic lockVersion handling, loud failure on concurrent edits, and notifications-off-by-default. These are non-obvious traits that prevent silent overwrites and surprise emails, going well beyond the structured hints in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with purpose front-loaded. The second sentence packs two high-value behavioral details with no wasted words. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 17-parameter update tool, the description is surprisingly complete: it covers the operation, concurrency behavior, and notification default. There is no output schema and no mention of the return value, but for an update call this is a minor gap since the schema already documents the inputs and the main risks are addressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 76%, and most parameters already carry good descriptions. The description adds a key semantic fact: lockVersion is fetched automatically, so callers should not supply it. This addresses a hidden parameter concern that the schema alone could not convey. The remaining undocumented parameters (id, dueDate, subject, startDate) are still inferable from their names and types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Update a work package.' This clearly differentiates it from sibling tools like op_create_work_package, op_get_work_package, and op_comment_work_package. The concurrency note reinforces that this is the mutation entry point for existing work packages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied by the verb 'Update' and the sibling set, but there is no explicit guidance about when to prefer this tool over op_create_work_package or op_comment_work_package. No exclusions or alternative-selection conditions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 18 tool updatesv1.0.0
    • First observedop_add_document_attachment
    • First observedop_comment_work_package
    • First observedop_create_work_package
    • First observedop_get_document
    • First observedop_get_work_package
    • First observedop_list_activities
    • First observedop_list_documents
    • First observedop_list_priorities
    • First observedop_list_projects
    • First observedop_list_statuses
    • First observedop_list_time_entries
    • First observedop_list_time_entry_activities
    • First observedop_list_types
    • First observedop_list_users
    • First observedop_list_work_packages
    • First observedop_log_time
    • First observedop_update_document
    • First observedop_update_work_package

TDQS

A3.9/5.0

Scored across 18 tools

Disambiguation4/5

Most tools target clearly distinct resource/action pairs, and the descriptions remove most ambiguity. The only slight confusion is among op_list_time_entry_activities, op_list_time_entries, and op_list_activities, but their different subjects are clarified in the descriptions.

Naming Consistency5/5

All tools follow a consistent op_<verb>_<noun> snake_case pattern with predictable verbs like list, get, create, update, and comment. op_log_time and op_add_document_attachment are minor stylistic variations but still fit the overall pattern.

Tool Count4/5

At 18 tools, the server is slightly above the ideal 3-15 range but each tool covers a legitimate OpenProject action across projects, work packages, time tracking, and documents. The breadth is justified by the domain rather than being padded with redundant tools.

Completeness4/5

Core workflows are well covered: listing projects, CRUD-ish work package operations, commenting, time entry logging, reference data, and document read/update. Notable gaps like work-package deletion or time-entry update/delete exist, but they are secondary or documented API limitations, so agents can still complete main workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that connects Claude Desktop to your OpenProject instance, allowing you to manage projects, tasks, and time entries through natural language.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server enabling AI agents to interact with OpenProject API v3 for project management, including creating and managing work packages, projects, comments, time entries, boards, and user dashboards.
    24 npm
    MIT