OpenProject
91 tools for the OpenProject API v3, with read-only, admin-gate, profile and per-group switches.
Connector by kar-thik · GitHub account verified by the MCP Registry
Chalk Labs
Need help deploying OpenProject?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Codex, VS Code, Cursor, Windsurf, Claude Desktop. Read the repository before you give any tool access to your data.
npx agentmarket install connector/kar-thik-openproject-mcp-server
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: project-management
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this server can do and what it asks for, from its tool list, install config and code. Checked Oct 25, 2026.
- Tools
- 32 read · 32 write · 13 delete · 3 not yet classified
- Secrets
- 2 (API keys, tokens or passwords)
- Install scripts
- None found
- Runs as
- Python package
Tools by what they do 80
Read from the source code; the running server may list different tools.
Read 32 · Look things up without changing anything.
get_documentget_github_pull_requestget_job_statusget_meetingget_newsget_projectget_project_phaseget_project_report_dataget_recurring_meetingget_sprintget_userget_wiki_page
Show 20 more tools
get_work_package_git_activitylist_attachmentslist_budgetslist_documentslist_file_linkslist_meetingslist_membershipslist_newslist_notificationslist_project_phase_definitionslist_projectslist_querieslist_recurring_meetingslist_reminderslist_roleslist_sprintslist_time_entrieslist_versionslist_work_package_commentssearch_principals
Write 32 · Create, change, send or run things.
add_meeting_agenda_itemadd_meeting_outcomeadd_work_package_commentadd_work_package_watcherbulk_update_work_packagescancel_recurring_meeting_occurrencecreate_meetingcreate_membershipcreate_newscreate_projectcreate_recurring_meetingcreate_version
Show 20 more tools
create_work_package_relationdownload_attachmentedit_work_package_commentexecute_custom_actionlog_timemark_all_notifications_readmark_notificationssave_queryset_work_package_remindertoggle_comment_reactionupdate_meetingupdate_meeting_agenda_itemupdate_meeting_outcomeupdate_membershipupdate_newsupdate_projectupdate_time_entryupdate_versionupdate_work_package_relationupload_attachment
Delete 13 · Delete, drop, revoke or wipe things.
delete_attachmentdelete_meetingdelete_meeting_agenda_itemdelete_meeting_outcomedelete_membershipdelete_newsdelete_projectdelete_recurring_meetingdelete_time_entrydelete_versiondelete_work_package_relationremove_work_package_watcher
Show 1 more tools
set_project_favorite
Not yet classified 3 · We could not tell from the name and description.
copy_projectinit_recurring_meeting_occurrencerun_query
Secrets and settings it asks for
Secrets: values you paste in that let it act as you.
OPENPROJECT_API_KEYOPENPROJECT_OAUTH_TOKEN
Other settings (environment variables or headers).
OPENPROJECT_MCP_ADMIN_TOOLSOPENPROJECT_MCP_DISABLEOPENPROJECT_MCP_PROFILEOPENPROJECT_MCP_READ_ONLYOPENPROJECT_URL
Network hosts it talks to 3
github.com· found in codeglama.ai· found in coderaw.githubusercontent.com· found in code
Files it touches
/tmp/mcp-bootstrap.rb- Any path the agent passes to its tools
Tools (80)
Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].
add_meeting_agenda_itemAdd meeting agenda itemAdd one item to a meeting's agenda, optionally pinned to a work package. Use it to build or extend an agenda: "add 'Release readiness' with 15 minutes", or "put #1234 on Thursday's agenda". Linking a work package is also how a ticket learns it was discussed — the link shows up on the work package's Meetings tab. Returns the created item: `{id, title, notes, duration_minutes, position, item_type, presenter, work_package, section, outcomes, meeting, created_at}`. `position` is where it landed in the agenda; items are appended to the meeting's last section. Pitfalls. This needs the 'manage age…
add_meeting_outcomeAdd meeting outcomeRecord an outcome — a decision, a note, a follow-up ticket — against an agenda item. This is how minutes are written through the API: "decision: ship on Friday" becomes `kind='decision'` with the text in `notes`; linking the follow-up work package makes it `kind='work_package'`. Outcomes appear under their agenda item in `get_meeting`. Returns the created outcome: `{id, kind, notes, author, work_package, agenda_item}`. Pitfalls — the timing rule matters most. Outcomes can only be written while the meeting state is exactly 'in_progress': before that, and again once it is closed, every outcom…
add_work_package_commentAdd work package commentPost a comment on a work package. Use this to reply in a ticket's thread, record a decision, or leave a handover note. Returns the created journal entry (activity id, author, markdown text, internal flag, timestamps) — the same shape ``list_work_package_comments`` returns, so the id can be reused. Pitfalls. Every call creates a new comment; it is not idempotent, so do not retry blindly after a timeout — read the thread first. ``internal=true`` is refused on OpenProject below 16.0 because those versions accept the flag and publish the comment anyway; upgrade or post publicly, deliberately. ``…
add_work_package_watcherAdd work package watcherSubscribe a user to a work package's notifications. Use this when someone should be kept in the loop on a ticket without being assigned to it. Watchers receive OpenProject's notifications for comments and changes. Returns the watcher (user id and name), the watch state after the call, and whether this call actually changed anything. Pitfalls. The user must already be able to see the work package; OpenProject answers 422 with a violation on ``user`` otherwise, and adding someone other than yourself needs the add-work-package-watchers permission (adding yourself only needs view access). Callin…
bulk_update_work_packagesPreview or apply work package updatesPreview or apply up to 50 work-package updates, each with its own changes. First call with dry_run=true (default). Review each before/after diff and validation error, then submit the same updates with dry_run=false and each preview's lock_version. Omitted fields remain untouched; null clears clearable fields; target_versions=[] clears version assignments. Status/type/priority accept names or ids, as in update_work_package. All items are validated before any update. If any preflight fails, nothing is applied; correct those items or submit a valid subset. Execution is sequential and NOT atomic…
cancel_recurring_meeting_occurrenceCancel recurring meeting occurrenceCancel one occurrence of a series — skip a slot without touching the schedule. Use it for "no sync next Monday": the slot stays in the occurrences list as 'cancelled' (backed by a cancelled stub meeting) while the series keeps running. A cancelled occurrence is recoverable — `init_recurring_meeting_occurrence` at the same instant restores it to 'open' — but the cancellation itself may email participants when the series has `notify` set, which is why it is confirm-gated. Returns a small confirmation object carrying the normalized instant. Pitfalls. The instant is matched exactly and never va…
copy_projectCopy projectCopy a project — its settings, and optionally its work packages — into a new one. Use it to spin a new engagement or release off a template project, which is the only way to reproduce a project's members, versions, categories and enabled modules in one call. The request goes through ``POST /projects/{id}/copy/form`` first, so a name that derives a taken identifier comes back as ``violations`` naming the attribute instead of a failed background job. Copying is ASYNCHRONOUS: OpenProject queues a job and answers immediately. This tool therefore returns ``{scheduled: true, job_id, status, messag…
create_meetingCreate meetingSchedule a meeting in a project and optionally invite participants. Use it for "book a review on Thursday" style requests. The call goes through `POST /meetings/form` first, so a missing permission, an impossible time or a participant who cannot see the project comes back as `violations` naming the attribute instead of an opaque rejection. Returns the created meeting in the same shape as `get_meeting` (its `agenda_items` are empty — add them with `add_meeting_agenda_item`). Pitfalls. Check `state` in the result: current OpenProject versions create meetings as 'draft', which means participan…
create_membershipGrant project membershipGrant a principal one or more roles in a project (admin-gated). Use it to add somebody to a project, or to add a group so its members inherit access. The payload is validated through OpenProject's own membership form first, so a role id that does not exist or a principal that is already a member comes back as a typed validation error listing what would be accepted, instead of an opaque 422. Returns the created membership: `{id, project, principal, roles, created_at, notes}`. Keep the `id` — it is what `update_membership` and `delete_membership` take. Pitfalls. **No notification is sent unle…
create_newsCreate newsPublish a news announcement in a project. Use it for release notes, a weekly report, a maintenance window — anything the whole project should see on its overview page. The author is the authenticated account and is set by the server; project members watching the project are notified. Returns the created entry ``{id, title, summary, description, project, author, created_at, updated_at, can_manage}``; the ``id`` is what ``update_news`` and ``delete_news`` consume. Pitfalls: this needs the 'manage news' permission in that project, which exists only while the project has the news module enabled…
create_projectCreate projectCreate a project, validated through OpenProject's own form endpoint first. Use it for a new workspace or, with ``parent_id``, for a subproject of an existing one. The call runs ``POST /projects/form`` before committing, so a taken identifier, an unusable parent or a bad status comes back as ``violations`` naming the attribute instead of an opaque failure — and the identifier OpenProject derives from the name is used verbatim on the commit. Returns the created project: ``{id, identifier, name, active, public, parent, status_code, description, status_explanation, created_at, updated_at}``. Kee…
create_recurring_meetingCreate recurring meetingCreate a recurring meeting series: a schedule plus a template the occurrences copy. For "set up a weekly sync Mondays at 9" requests. frequency/end_after combinations are validated locally before anything is sent, rejecting a bad combination with the allowed matrix spelled out. Returns the created series in `get_recurring_meeting`'s shape, including computed next `occurrences` (their `start_time` is what occurrence tools take) and `template_meeting_id`. Pitfalls. The template meeting is created as a DRAFT: `notes` says so, and occurrences can't be initialized until `update_meeting(meeting_i…
create_versionCreate versionCreate a version (release, milestone or sprint) inside a project. Use it to open a new sprint or plan a release before assigning work packages to it. The call goes through ``POST /versions/form`` first, so a duplicate name or an impossible date range comes back as ``violations`` naming the attribute instead of an opaque rejection. Returns the created version ``{id, name, project, status, start_date, end_date, description, sharing, source, created_at, updated_at}``. The ``id`` is what ``update_work_package(version=...)`` and ``update_version`` consume. Pitfalls: ``end_date`` is the version's…
create_work_package_relationCreate work package relationLink two work packages (blocks, follows, duplicates, relates, ...). Use this to record a dependency the schedule or the reader needs to know about: "ship the client layer follows design sign-off", "this duplicates #4321". Returns the created relation with its id, type, reverse_type, both work packages, lag and description. Pitfalls. OpenProject stores one canonical direction per pair, so the passive spellings are rewritten on save: creating ``precedes`` from A to B comes back as B ``follows`` A, with ``from_work_package`` and ``to_work_package`` swapped. That is the same fact, not an error —…
delete_attachmentDelete attachmentPermanently delete one attached file from OpenProject. Use it only on explicit user instruction, for example to remove a file uploaded to the wrong work package or a superseded document. The attachment's metadata is read first so the result names the file and the container it was attached to, and so an unknown id fails before anything is removed. Returns the attachment id, the file name, its container and a confirmation message. Pitfalls: this deletes the file itself, not a link to it — every work package, wiki page or comment that embedded it loses the image or download. Deleting needs *ed…
Show 65 more tools
delete_meetingDelete meetingPermanently delete a meeting, together with its agenda and recorded outcomes. Use only on explicit user instruction. The meeting, its agenda items, their outcomes and its attachments all go with it, and OpenProject offers no API-side undo. If the meeting merely did not happen, `update_meeting(meeting_id=..., state='cancelled')` is the reversible alternative that keeps the record. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. This needs the 'delete meetings' permission, so a 403 is about the account, not the id. A 404 means the id is wrong, the meeting …
delete_meeting_agenda_itemDelete meeting agenda itemPermanently delete one agenda item, with any outcomes recorded against it. Use only on explicit user instruction. The item and its recorded outcomes disappear from the agenda for good; the items after it move up. The meeting itself is untouched. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. A CLOSED meeting's agenda is frozen: the delete answers a validation error, not a 403, until the meeting is reopened with `update_meeting(state='open')`. This needs the 'manage agendas' permission. A 404 means the id is wrong, the item is already gone — or, on OpenP…
delete_meeting_outcomeDelete meeting outcomePermanently delete a recorded outcome from a running meeting's minutes. Use only on explicit user instruction, for an outcome recorded by mistake or against the wrong item. If the text is merely wrong, `update_meeting_outcome` corrects it and keeps the record. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. The outcome timing rule applies to deletion too: it only works while the meeting state is exactly 'in_progress' — a closed meeting's minutes are frozen, and the delete answers a validation error, not a 403. This needs the 'manage outcomes' permission.…
delete_membershipRevoke project membershipRevoke a principal's access to a project (admin-gated, destructive). Use only on explicit user instruction. The principal immediately loses the roles this membership granted, along with any project visibility that depended on them; OpenProject offers no API-side undo. Work packages they authored, commented on or are assigned to are **not** deleted, but an assignee who is no longer a member may need to be reassigned. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. If the principal also belongs to a group that is a member of the project, they keep access t…
delete_newsDelete newsPermanently delete a news entry. Use it for an announcement published by mistake or in the wrong project. For an outdated but real announcement, ``update_news`` is usually the better answer: the entry stays part of the project's record. Returns a small confirmation once OpenProject accepts the deletion. Pitfalls: the entry and every comment left on it are removed for good — API v3 offers no undo and no trash. The 'manage news' permission is required, so a 403 is about the account or a disabled news module; a 404 means the id is wrong or its news is not visible to you. Cross-references: ``l…
delete_projectDelete projectSchedule the permanent deletion of a project and everything inside it. Use only on an explicit, specific instruction. Deletion CASCADES: every subproject, work package, comment, attachment, time entry, version, wiki page and membership of this project goes with it, and OpenProject offers no API-side undo. If the goal is only to get the project out of the way, ``update_project(active=false)`` archives it instead — reversible, and it preserves the data. Deletion is ASYNCHRONOUS upstream: OpenProject accepts the request and runs it as a background job. This tool therefore returns ``{scheduled: …
delete_recurring_meetingDelete recurring meetingPermanently delete a recurring series: template, schedule, and EVERY occurrence. Use only on explicit user instruction, and make sure the user means the whole series: every instantiated meeting of the series — past minutes included — is destroyed with the template, and when the series has `notify` set, participants are emailed cancellations. To drop a single slot instead, `cancel_recurring_meeting_occurrence` is the right tool, and `delete_meeting` removes one instantiated meeting. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. This needs the 'delete me…
delete_time_entryDelete time entryPermanently delete a logged time entry. Use only on explicit user instruction, and only for genuinely wrong entries. Deletion removes the booked hours from every cost report and from the work package's aggregated spent time, with no API-side undo. Returns a small confirmation object once OpenProject accepts the deletion. Pitfalls. If the entry is merely on the wrong day, has the wrong duration or the wrong activity, ``update_time_entry`` is the better answer — it keeps the audit trail. Deleting someone else's entry needs an administrative permission and otherwise fails with ``permission_den…
delete_versionDelete versionPermanently delete a version. Use it only for a version created by mistake. For a finished release or sprint, ``update_version(status='closed')`` is almost always the right answer: it keeps the history and stops new assignments. Returns a small confirmation once OpenProject accepts the deletion. Work packages are NOT deleted — they simply lose their version — but that only happens on instances that allow the deletion at all. Pitfalls: OpenProject refuses (422) to delete a version that work packages still reference; the error hint explains how to find them. Deleting a shared version affects …
delete_work_package_relationDelete work package relationRemove the link between two work packages. Use it when a dependency no longer holds. Neither work package is touched, only the relation between them. Returns a small confirmation object. Pitfalls. Deleting a ``follows`` relation drops the scheduling constraint, so OpenProject may reschedule the work package that was waiting. There is no undo; recreating the relation with ``create_work_package_relation`` is the only way back. A second delete of the same id answers 404. Parent/child hierarchy is not a relation — clear it with ``update_work_package(parent_id=null)``. Cross-references: ``get_wo…
download_attachmentDownload attachmentDownload an attachment's bytes to a file on the machine running this server. Use it once list_attachments (or get_work_package(include=['attachments'])) has given you an attachment_id. Metadata is read first, then the bytes are streamed to disk in chunks with progress notifications, so a large file neither stalls the call nor buffers in memory. Returns path, file_name, size_bytes, content_type and the SHA-256 of the bytes (use it to verify or de-duplicate). With return_image=true an image of at most 1 MB comes back as an inline image block as well. Pitfalls: the file is written on the serve…
edit_work_package_commentEdit work package commentRewrite the text of an existing work-package comment. Use this to fix a typo, correct a wrong statement, or extend a note you just posted. Returns the updated journal entry (activity id, author, markdown text, internal flag, timestamps) in the same shape ``list_work_package_comments`` returns. Pitfalls. Only **comment** entries are editable: the journal also holds field-change entries ("Status changed from New to In progress"), which OpenProject records automatically and refuses to alter — this tool rejects those locally, before any write. Editing needs the edit-work-package-comments permiss…
execute_custom_actionExecute custom actionRun an instance-defined one-click action on a work package. Custom actions are shortcuts an administrator configured — "Accept and assign to me", "Reject", "Move to review" — that apply several field changes at once, sometimes under conditions (role, status, project). Use one when ``get_work_package(include=['custom_actions'])`` offers it, instead of reproducing its effects field by field. Returns the updated work package row (subject, type, status, priority, assignee, project, dates, percentage_done, updated_at). Pitfalls. The action decides what changes; this tool cannot influence it, and …
get_documentGet documentRead one document with its full description text. Use it after `list_documents` when the title is not enough: this adds `description` as markdown, alongside `{id, title, project, created_at, updated_at}`. Pitfalls. The attached files are not part of this result — list them with `list_attachments(container_type='document', container_id=<this id>)`. A document created with OpenProject's block editor keeps its rich content in a field API v3 does not render, so `description` can be empty for a document that clearly has text in the UI; say so rather than reporting the document as blank. Editing d…
get_github_pull_requestGet GitHub pull requestRead one linked GitHub pull request in full, including its CI check runs. Use it after `get_work_package_git_activity` when the summary is not enough: this adds the pull-request `body` (markdown), the diff size (`additions`, `deletions`, `changed_files`), comment counts, who merged it, and every work package the PR is linked to — plus the same `check_runs` with status and conclusion. Pitfalls. `github_pull_request_id` is OpenProject's id, never the GitHub number; the two are unrelated and there is no lookup by GitHub number. The record is a mirror that OpenProject refreshes from GitHub webho…
get_job_statusGet background job statusCheck whether a background job (a project copy, a scheduled deletion) has finished. OpenProject runs copies, deletions and exports asynchronously and hands back a job id. This is the only way to learn what happened to one: call it after ``copy_project`` or ``delete_project`` and wait for a terminal state before reporting an outcome to the user. Returns ``{id, status, finished, successful, message, project, result_url, notes}``. ``status`` is 'in_queue' or 'in_process' while the job runs and 'success', 'failure', 'error' or 'cancelled' once it is over; ``finished`` and ``successful`` are deri…
get_meetingGet meetingRead one meeting in full: participants, the agenda, and any recorded outcomes. This is the "what was discussed / what was decided" call. It returns the meeting fields (`title`, `project`, `start_time`, `end_time`, `duration_hours`, `location`, `state`, `author`, timestamps), the invited `participants` as `{id, name}` refs, and `agenda_items` in agenda order — each with its `title`, `notes` (markdown), `duration_minutes`, `presenter`, the `work_package` it discusses, its `section`, and the `outcomes` recorded against it (`kind`, `notes`, author, linked work package). Pitfalls. A work-package …
get_newsGet news entryRead one news entry in full, including the markdown body. Use it after ``list_news`` when the summary is not enough — this adds ``description``, the announcement's complete text as markdown (html is dropped), plus ``updated_at``. Returns ``{id, title, summary, description, project, author, created_at, updated_at, can_manage}``. ``author`` is the account that published the entry and cannot be changed; ``can_manage`` says whether editing or deleting it would be permitted. Pitfalls: a 404 here means "no such entry, or you may not read news in its project" — the news module is enabled per proje…
get_projectGet projectRead one project in full. Use it after ``list_projects`` when you need the description, the status explanation or the parent of a specific project — or to verify that an id or identifier a user gave you actually resolves. Returns ``{id, identifier, name, active, public, parent, status_code, workspace_type, description, status_explanation, created_at, updated_at}``. Rich text comes back as markdown ``raw``; html is dropped. Pitfalls: ``status_code`` is one of on_track, at_risk, off_track, not_started, finished, discontinued — an empty ``status_code`` means the project has no status set, not …
get_project_phaseGet project phaseRead one project's phase record: name, active flag and its definition. Use it after ``get_work_package`` surfaced a ``project_phase`` reference and you need to know which project and definition that phase belongs to, or whether it is still active. Returns ``{id, name, active, definition, project, created_at, updated_at}``. Pitfalls: the API has no phases index — ids only come from work packages' ``project_phase`` references. Phase dates are not exposed by the API (the ``notes`` say so), so "which projects are in this phase now" goes through ``list_projects(in_phase=...)`` instead. A 404 cov…
get_project_report_dataGet project report dataAggregate everything a status report needs about one project and one date window. Use it for weekly reports, sprint reviews, standups and "what happened in June" — one call replaces a dozen filtered listings. Sections: `created`, `updated` and `closed_updated` work-package buckets, `open` (total plus `by_status` counts computed server-side over the whole open set), `time` (hours with per-activity and per-user breakdowns) and the membership `roster`. Ask only for the `sections` you need. Every section has a `state`: 'complete', 'partial', 'unavailable' or 'not_requested'. A bucket's `total` i…
get_recurring_meetingGet recurring meetingRead one recurring series in full: the schedule plus its next occurrences. This is the step before touching any occurrence: the `occurrences` rows carry the exact `start_time` strings that `init_recurring_meeting_occurrence` and `cancel_recurring_meeting_occurrence` key on, and the `meeting_id` that `get_meeting` / `delete_meeting` take once a slot is instantiated. Returns the series fields (schedule, `duration_hours`, `location`, `author`, `template_meeting_id`) plus `occurrences` in date order: `{start_time, state, meeting_id}`. `state` is 'planned' for a slot that exists only in the sched…
get_sprintGet sprintRead one sprint in full: dates, workspace and lifecycle status. Use it once ``list_sprints`` has given you an id and the row is not enough — this adds ``created_at``/``updated_at`` to the same shape. Pitfalls: sprint ids and version ids are different id spaces — a version id from ``list_versions`` does not resolve here. Cross-references: ``list_sprints`` for the id; ``list_work_packages`` with ``sprint_ids`` for the work planned in this sprint.
get_userGet user detailRead one user's profile: name, login, email, admin flag and status. Use it after `search_principals` when you need more than a name — to confirm an account is `active` before assigning work, to check whether somebody is an instance administrator, or to learn which account the server itself is acting as (`id_or_me='me'`). Returns `{id, name, login, email, admin, status, language, created_at, updated_at}`. The avatar URL is deliberately dropped: it costs tokens and cannot be rendered here. Pitfalls. `email`, `login` and `admin` are visibility-dependent — a null means the authenticated account…
get_wiki_pageGet wiki pageRead a wiki page's identity and project — NOT its content. Two limits define this tool, and both must be passed on to the user rather than worked around. First, `wiki_page_id` comes from a wiki page URL the user supplies: API v3 has no wiki index and no wiki search, so there is no way to look a page up by title or to list a project's pages. Second, the page's CONTENT is not exposed by the API at all — the response carries only `{id, title, project}` plus the page's attachments, and `notes` repeats that in-band. So: use it to confirm which page a URL points at, to get the project a page belon…
get_work_package_git_activityGet work package git activityShow the code behind a work package: commits, pull/merge requests and CI status. Use this for "is this ticket implemented", "what shipped for it", "did CI pass", "which branch/PR is this in". It returns, in one call: `revisions` (commits whose message references the work package, with full SHA, short SHA, author, message and commit time), `github_pull_requests` (title, state, draft, merged/merged_at, labels, author, URL and the CI `check_runs` with status and conclusion), `gitlab_merge_requests` (the same, with `pipelines` instead of check runs) and `gitlab_issues`. `available` says, per sou…
init_recurring_meeting_occurrenceInit recurring meeting occurrenceMaterialize one occurrence of a series as a real meeting, copied from the template. Use it when a specific slot needs its own agenda, minutes or attachments before the day: the occurrence becomes a normal meeting (template agenda and attachments copied) that every meeting tool can work on. Called on a cancelled occurrence it RESTORES it to 'open'; called where an open meeting already exists it idempotently returns that meeting. Returns the instantiated meeting in the same shape as `get_meeting` — its `id` is the meeting id for follow-up calls, distinct from the series id. Pitfalls — the ins…
list_attachmentsList attachmentsList the files attached to one container. Containers are work packages, wiki pages, meetings, documents, budgets and comments. Use this to discover attachment ids before calling download_attachment, or to check what a work package already carries. The upstream collection is not paginated, so it is fetched in full: the envelope always reports has_more=false and a total equal to the row count. Returns the standard list envelope; each row has id, file_name, size_bytes, content_type, description, author, created_at and status. status is the virus-scan state — 'uploaded' and 'scanned' are downloa…
list_budgetsList budgetsList a project's budgets — their ids and names, which is all API v3 exposes. Use it to see whether a project tracks budgets at all and to get a budget id, which is what `list_attachments(container_type='budget', ...)` consumes. Returns the standard list envelope with rows of `{id, subject}`. The collection is fetched in full, so `has_more` is false. Pitfalls — read before answering a money question. API v3's budget representer carries **no amounts**: planned costs, spent costs, labor/material breakdowns and the assigned work packages are simply not there. Do not infer them and do not presen…
list_documentsList documentsList the documents visible to you, across every project. Documents are OpenProject's filing cabinet: a title, a description, and attached files. Use this to find a document id for `get_document` or for `list_attachments(container_type='document', ...)`. Returns the standard list envelope: rows of `{id, title, project, created_at, updated_at}` plus `pagination`. The description is deliberately left out of the rows — `get_document` returns it in full. Pitfalls. This is instance-wide: the endpoint takes no project parameter here, so filter by reading `project` on the rows, and page through rat…
list_file_linksList file linksList the external-storage files (Nextcloud, OneDrive/SharePoint) linked to a work package. File links are OpenProject's other kind of file: instead of living inside OpenProject like an attachment, the document stays in a connected storage and the work package points at it. Use this to answer "which documents belong to this ticket" — and pair it with list_attachments, because the two lists are disjoint and neither implies the other. Returns the standard list envelope, fetched in full (has_more is always false). Each row carries file_name, the storage it lives on, the file's origin_id inside t…
list_meetingsList meetingsList meetings — the schedule side of a project: what is coming up, what already ran. Use it to answer "when do we next meet", "what meetings does this project have", or to find the meeting id that `get_meeting` and `add_meeting_agenda_item` need. Meeting ids are instance-wide and never guessable, so this is the way to get one. Returns the standard list envelope: rows of `{id, title, project, start_time, end_time, duration_hours, location, state}` plus `pagination` and `notes`. Times are ISO 8601 UTC and `duration_hours` is a float (1.5 = 90 minutes). Rows are ordered by start time — ascendin…
list_membershipsList project membershipsList who has access to which project, and with which roles. Use it before granting or revoking access ("does she already have a role here?"), to audit a project's member list, or to see which projects a principal can reach. Called with no arguments it pages through every membership the authenticated account may see, which on a large instance is a lot — filter. Returns the standard list envelope: `items` of `{id, project, principal {id,name,type}, roles[], created_at, updated_at}` plus `pagination{total,page,page_size,has_more}`. Pitfalls. The `id` in each row is the **membership** id — the …
list_newsList newsList project news — the announcements a team publishes on its project overview. Use it to answer "what was announced recently", to find the id of an entry before reading, editing or deleting it, or to check whether a report was already published. Results come back newest first (sorted by creation date descending). Returns the standard list envelope: ``items`` of ``{id, title, summary, project, author, created_at, can_manage}`` plus ``pagination`` and ``notes``. Rows carry the short ``summary`` only — the full markdown body is fetched per entry with ``get_news(news_id=...)``, which keeps a lo…
list_notificationsList notificationsRead the authenticated user's OpenProject inbox. Use this to answer "what needs my attention?", "was I mentioned anywhere?" or "what changed on the things I watch?" — it is the only tool that sees notifications, and it always reports the inbox of the **token owner**, never another user's. Returns the standard list envelope: ``items`` of ``{id, reason, read, created_at, actor, project, resource}`` plus ``pagination`` with ``total``/``page``/``page_size``/``has_more``. ``resource`` is the thing the notification is about — ``{id, type, title}``, usually ``type='WorkPackage'``, so ``resource.id`…
list_project_phase_definitionsList project phase definitionsList the instance-global phase definitions — the vocabulary of the project life cycle. Use it to learn which phases (Initiating, Planning, …) and gates this instance defines, and to get the definition id or name that ``list_projects(in_phase=...)`` accepts. Returns the standard list envelope of ``{id, name, start_gate, start_gate_name, finish_gate, finish_gate_name}`` rows. Gates are the checkpoints a phase can begin or end with; a definition without gates has both flags false. Pitfalls: definitions are the instance-wide *catalog*, not any project's actual phases — a project may deactivate …
list_projectsList projectsList projects, filtered server-side, one page at a time. Use this to turn a project name into the id or identifier that every other tool consumes, to enumerate the sub-projects of a parent, or to review which projects are off track. It is the id-producing path for every ``project_id`` parameter in this server. Returns the standard list envelope: ``items`` of ``{id, identifier, name, active, public, parent, status_code, workspace_type}`` plus ``pagination`` with ``total``/``page``/``page_size``/``has_more``. Nothing is truncated silently — page explicitly until ``has_more`` is false. Pitfall…
list_queriesList saved queriesList the saved work-package views (queries) this user can open. Use it to discover what a team already tracks — "Sprint board", "My open bugs", "Overdue in Platform" — before hand-building filters: running someone's saved view with `run_query` reproduces exactly what they see in the UI, including their grouping and sums. Returns the standard list envelope: rows of `{id, name, project, public, starred, updated_at}` plus `pagination`. `project` is null for a global query (saved outside any project); `public` false means the query is private to its owner, and only the owner's queries are visibl…
list_recurring_meetingsList recurring meetingsList recurring meeting series — the repetition rules, not the individual meetings. Use it to answer "what regular meetings do we have" and to find the series id that `get_recurring_meeting`, the occurrence tools and `delete_recurring_meeting` need. Series ids are their own id space: a series id is never a meeting id, and the weekly occurrences themselves show up in `list_meetings`, not here. Returns the standard list envelope: rows of `{id, title, project, start_time, time_zone, frequency, interval, monthly_day, monthly_ordinal, monthly_weekday, end_after, end_date, iterations, duration_hour…
list_remindersList remindersList your own upcoming work-package reminders. Use this to answer "what have I asked to be reminded about", to check whether a reminder is already set before creating another one, or to find the work packages you deferred. Returns the standard list envelope: ``items`` of ``{id, remind_at, note, work_package, creator}`` plus ``pagination`` and ``notes``. Pitfalls. Reminders are personal — this only ever shows the ones the authenticated account created, never a colleague's, and there is no way to list someone else's. It only shows reminders that are still **upcoming**: once one has fired (or w…
list_rolesList rolesList the roles this instance defines, with their ids. This is the id-producing tool for `create_membership.role_ids` and `update_membership.role_ids` (both admin-gated: hidden unless the server sets `OPENPROJECT_MCP_ADMIN_TOOLS=1`) — role names are never accepted there. Roles are instance-wide definitions ('Member', 'Reader', 'Project admin'); a membership binds one principal to one project with a set of them. Returns the standard list envelope with `has_more: false`: the role list is small and fetched in full. Each item is `{id, name}`, plus `permissions` when `include_permissions=true`. P…
list_sprintsList sprintsList sprints (Scrum timeboxes) you can plan work packages into. Use it to turn "Sprint 11" into the sprint id that ``create_work_package``/``update_work_package`` consume via their ``sprint`` parameter, or to review a project's sprint plan with its ``in_planning``/``active``/``completed`` states. Returns the standard list envelope: ``items`` of ``{id, name, description, start_date, finish_date, workspace, status}`` plus ``pagination`` and ``notes``. A project-scoped listing is fetched in full, so ``has_more`` is false; the instance-wide listing is paginated. Pitfalls: sprints are not versio…
list_time_entriesList time entriesList logged time, filtered server-side, with an optional accurate total. Answers "how much time went into this ticket?" or "how much did the team spend on project X in June?". Filters combine with AND, so `project_id` + `user='me'` + a date range is one call. Returns the standard list envelope: ``items`` of ``{id, hours, spent_on, comment, user, activity, work_package, project}`` plus ``pagination``. ``hours`` is a float (1.5 = 1h30), never an ISO duration. With ``sum_hours=true``, the envelope also carries ``sums.total_hours`` over all matches and a ``groups`` bucket per activity with its o…
list_versionsList versionsList versions (releases, milestones, sprints) you can assign work packages to. Use it to turn "Sprint 12" or "release 2.1" into the version id that ``create_work_package``/``update_work_package`` need, to see which versions are still open, or to review a release plan's dates. With ``project_id`` it answers "what can I target in THIS project", which includes versions shared down from parent projects. Returns the standard list envelope: ``items`` of ``{id, name, project, status, start_date, end_date, description, sharing, source}`` plus ``pagination`` and ``notes``. A project-scoped listing is…
list_work_package_commentsList work package commentsRead the comment thread and change history of a work package. Use this whenever the question is "what did people say about this ticket" or "what changed on it": it returns the full activity journal — comment entries (author, markdown text, internal flag, timestamps) and field-change entries whose details are parsed into ``{field, from, to}`` (for example ``{"field": "Status", "from": "New", "to": "In progress"}``). Returns the standard list envelope: ``items`` plus ``pagination{total,page,page_size,has_more}`` and ``notes``. Pitfalls. OpenProject's activities endpoint is **unpaginated** — t…
log_timeLog timeBook time against a work package or a project. Use it when the user says "log 2 hours on #1234" or "book half a day to project X". The call is validated through OpenProject's own form endpoint first, so an activity this project does not allow, a missing permission or a closed cost-reporting period comes back as a typed error listing what would be accepted — nothing half-written is left behind. Returns the created entry: ``{id, hours, spent_on, comment, user, activity, work_package, project, created_at, updated_at, lock_version}``. ``hours`` comes back as a float. Pitfalls. This is **not** i…
mark_all_notifications_readMark all notifications readMark **everything** matching the filters as read — the whole inbox by default. Use it for "clear my notifications" or "I have dealt with everything in project X". Called with no arguments it marks every unread notification of the token owner as read, across all projects; ``reason`` and ``project_id`` narrow that blast radius, they do not create a preview. Check what is about to disappear with ``list_notifications(unread_only=true, ...)`` using the same filters first — there is no undo beyond re-marking individual ids unread. Returns ``{marked, read, message}``, where ``marked`` is how many u…
mark_notificationsMark notifications read or unreadMark specific notifications read (or unread) in one bulk request. Use it after you have actually handled what a notification was about, so the user's inbox reflects reality. It is the id-consuming counterpart of ``list_notifications``: pass the row ``id`` values from that tool. Returns ``{marked, read, ids, message}``. OpenProject answers the bulk endpoint with ``204 No Content``, so ``marked`` is the number of ids the call covered — ids that were already in the requested state, or that belong to someone else's inbox, are simply not changed. Pitfalls. Marking is idempotent, so a retry after…
remove_work_package_watcherRemove work package watcherUnsubscribe a user from a work package's notifications. Use this to stop notifying someone who no longer needs the updates. Returns the user, the watch state after the call (always not watching) and a confirmation message. Pitfalls. OpenProject answers the same 204 whether or not the user was watching, so ``changed`` comes back null — do not report "removed" as proof that they were subscribed. Removing another user needs the delete-work-package-watchers permission; removing yourself only needs view access. A 404 means the *user* id is unknown (or the work package is), not that they were not …
run_queryRun a saved queryRun a saved view and get its work packages — the fastest way to answer with a team's own definition of "the sprint" or "our bugs". OpenProject queries run on read: this returns the rows as they are right now, in the stored order and grouping. The result is the standard list envelope — `items` of compact work-package rows, `pagination`, plus `groups` when the query groups and `sums` when it asks for totals — with one addition: `query` carries the stored definition (name, project, readable `filters`, `group_by`, `sort_by`), so the rows can be interpreted without a second call. Pitfalls. `group…
save_querySave a querySave a filter set as a reusable OpenProject view. Use it to keep a filter combination — "Overdue in Platform", "My open bugs" — instead of rebuilding it each session: the view shows up in the OpenProject UI too, and `run_query` reproduces it exactly. Prove filters with `list_work_packages` first. Validated via `POST /queries/form` first, so an invalid filter name, unsupported operator, or project-scoped filter on a global view comes back as `violations` naming the attribute — nothing is saved. Returns the stored definition: `{id, name, project, public, starred, filters (as readable sentences…
search_principalsSearch users, groups and placeholder usersFind users, groups and placeholder users, and get their ids. This is **the** id-producing tool for every principal parameter in this server: `assignee`/`responsible` on work packages, watcher ids, the `user_id` of a time entry, and `principal_id` for `create_membership` (admin-gated: hidden unless the server sets `OPENPROJECT_MCP_ADMIN_TOOLS=1`). Names are never accepted where an id is wanted — resolve here first, and never guess a numeric id. Use it to answer "who is Grace Hopper's account", "which groups exist", "who is a member of the demo project". Returns the standard list envelope: `it…
set_project_favoriteSet project favoriteAdd or remove a project from the authenticated user's favorites (OpenProject 17+). Favorites are per user, not per project: this changes what the account behind OPENPROJECT_API_KEY sees starred on its own overview page, and nothing about the project itself or about anybody else's view. Use it when the user asks to pin, star or favorite a project they work in. Returns ``{id, favorite, message}`` — ``favorite`` is the state now in effect. The call is idempotent: favoriting an already-favorited project succeeds again. Pitfalls: this endpoint only exists from OpenProject 17. When the instance r…
set_work_package_reminderSet work package reminderSet, change or clear your personal reminder on a work package. Use this when something should resurface later: "remind me about this on Monday", "ping me an hour before the release". Reminders are private — only you see yours, and only you are notified. The tool upserts: it looks for your active reminder on the work package and creates one if there is none, updates it if there is. Returns ``action`` (created/updated/deleted/unchanged) and the resulting reminder. Passing ``remind_at=null`` **deletes** the reminder. That is the documented way to clear it rather than a destructive operation — n…
toggle_comment_reactionToggle comment reactionReact to a work-package comment with an emoji, or take your reaction back. Use this for the lightweight acknowledgement a comment does not deserve: 👍 on a decision, 👀 to say you are looking at it, 🎉 when something shipped. Returns the comment's full reaction state afterwards — every emoji on it with the people who picked it — plus ``reacted``, which says whether you are now among them. Pitfalls. This is a **toggle**, not an add: calling it twice with the same reaction leaves the comment exactly as it started, so it is not safe to retry blindly after a timeout — read ``reacted`` from the r…
update_meetingUpdate meetingChange a meeting's title, time, place or invite list — or move its lifecycle state. Reschedule ("move Thursday's review to 15:00"), publish a draft (`state='open'`), start/wrap up a running one (`state='in_progress'`/`'closed'`), or fix participants. Only passed parameters are sent; omitted fields stay as they are. Returns the updated meeting in the same shape as `get_meeting`, including the fresh `lock_version` for a follow-up edit. Pitfalls. A closed meeting accepts a state-only patch (reopening it) and nothing else; any other change is rejected with a validation error until it is reopene…
update_meeting_agenda_itemUpdate meeting agenda itemEdit one agenda item: retitle it, rewrite its notes, retime, reorder or re-link it. Use it for "give that item 20 minutes", "move it to the top" (`position=1`), "let Grace present it", or to fix a wrong work-package link. Only the parameters you pass are sent; everything else is left exactly as it is. Returns the updated item in the same shape as `add_meeting_agenda_item`, including the fresh `lock_version` for a follow-up edit. Pitfalls. Once the meeting is CLOSED its agenda is frozen — every write answers a validation error until the meeting is reopened with `update_meeting(state='open')`…
update_meeting_outcomeUpdate meeting outcomeCorrect a recorded outcome's kind, text or linked work package. Use it while the meeting still runs: fix a typo in the minutes, upgrade an information note to a decision, or attach the follow-up ticket that was created after the fact. Only the parameters you pass are sent. Returns the updated outcome in the same shape as `add_meeting_outcome`. Pitfalls. The same timing rule as every outcome write: this only works while the meeting state is exactly 'in_progress' — once it is closed, the minutes are what they are, and the write answers a validation error. Outcomes carry no `lock_version` upst…
update_membershipChange membership rolesReplace the roles of an existing membership (admin-gated). Use it to promote or demote somebody inside a project. The project and the principal of a membership cannot be changed: to move access to a different project, delete this membership and create the other one. Runs through the membership form first, so an unknown or non-assignable role comes back with the roles this instance actually offers. Returns the updated membership `{id, project, principal, roles, updated_at}`. Pitfalls. `role_ids` is a **replacement set**, not an addition — read the current roles with `list_memberships` and se…
update_newsUpdate newsCorrect or rewrite a published news entry. Use it to fix a headline, refresh a weekly report in place, or clear a stale teaser. Only the parameters you pass are sent, so a concurrent edit to another field survives. Returns the updated entry in the same shape as ``get_news``. Pitfalls: ``summary`` and ``description`` REPLACE the stored text — there is no append. The entry's project and author are fixed at creation and cannot be updated here; publish a new entry instead. News carries no ``lockVersion`` upstream, so there is nothing to echo and no lock parameter: a simultaneous edit by somebod…
update_projectUpdate projectChange a project's name, description, visibility, parent, status or archived state. Use it to record a status change with its explanation ("at_risk because the vendor slipped"), to rename or re-parent a project, to publish it, or to archive it with ``active=false``. The change is validated through ``POST /projects/{id}/form`` first, so rejected values come back as ``violations`` naming the attribute. Only the parameters you pass are sent — omitted fields are never rewritten, so two agents editing different fields do not clobber each other. Projects carry no ``lockVersion`` upstream, so there…
update_time_entryUpdate time entryCorrect an existing time entry. Use it for the everyday fixes: wrong duration, wrong day, wrong activity, a comment that needs to say what actually happened. Only the parameters you pass are written; everything else is left exactly as it is. Returns the updated entry in the same shape ``log_time`` returns. Pitfalls. What can be moved between entries is limited: the work package and the project a time entry belongs to are **not** editable here — delete the entry and log it again where it belongs. Some instances report a ``lock_version`` for time entries and some do not; this tool reads the e…
update_versionUpdate versionChange a version's name, dates, description, status or sharing. Use it to move a sprint's dates, to close a finished release (``status='closed'``), or to widen sharing so a subproject can use the version. The change is validated through ``POST /versions/{id}/form`` first, so rejected values come back as ``violations`` naming the attribute. Only the parameters you pass are sent, so concurrent edits to other fields survive. Versions carry no ``lockVersion`` upstream, so there is nothing to echo and no lock parameter here — a 409 would mean the resource itself changed, not a stale version. Ret…
update_work_package_relationUpdate work package relationChange an existing relation's type, lag or description. Use it to widen the gap between a predecessor and its successor, to correct a link that was created with the wrong type, or to explain why two work packages are connected. Returns the updated relation. Pitfalls. At least one of type, lag or description must be given. Relations carry no lock version, so this is a plain overwrite with no conflict detection — a concurrent edit is silently replaced; re-read the relation if that matters. The two work packages cannot be changed here: delete the relation and create a new one instead. Raising t…
upload_attachmentUpload attachmentAttach a local file to a work package, wiki page, meeting, document, budget or comment. Use it when a file that already exists on the server's machine should be added to an existing container. The file's existence and its size against this instance's maximumAttachmentFileSize are checked locally first, so an oversized file fails instantly instead of after the transfer. Returns the created attachment row (id, file_name, size_bytes, content_type, description, author, created_at, status) — the id feeds download_attachment. Pitfalls: uploading to a container needs *edit* permission on that cont…
Signals
- Stars
- 5
- Forks
- 1
- Open issues
- 0
- Weekly downloads
- 433
- Last commit
- Oct 20, 2026 (10 days ago)
- Last release
- Oct 20, 2026 (10 days ago)
- Last package publish
- Oct 20, 2026 (10 days ago)
From GitHub (fetched Oct 24, 2026) and the package registry.
Details
- Registry name
io.github.kar-thik/openproject-mcp-server- Version
- 0.4.0
- Auth
- API key
- Packages
- pypi openproject-mcp-server
- License
- MIT
- Repository
- github.com/kar-thik/openproject-mcp
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get OpenProject running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
OpenProject MCP server. Agent Mart. https://agentmart.dev/connectors/kar-thik-openproject-mcp-server (last updated 2026-10-24)