makeplane / makeplane/plane-mcp-server
Bug: update_work_item state is silently ignored on self-hosted CE (inverse of state_id→state rename)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 325
- Forks
- 178
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 2
Description
Problem
update_work_item (and likely create_work_item) accept a state parameter and the official MCP/plane_sdk serialize it as "state" in the PATCH/POST body. On some Plane deployments that works; on others — including self-hosted Plane Community Edition — the REST API expects "state_id" instead.
When the wrong field name is sent, Plane returns HTTP 200 with an updated updated_at, but the work item's state is unchanged. Agents treat this as success and loop or invent wrong explanations (workflow constraints, parent blocking, etc.).
This is the inverse of the field-name mismatch fixed in community forks such as ZethicTech/plane-mcp-server#13 / #14, which renamed state_id → state for API compatibility. That direction fixes Cloud-style APIs but reintroduces a silent no-op on CE instances that only honor state_id.
Reproduction (self-hosted Plane CE)
Against a self-hosted instance (workspace homelab-ops, MCP plane_mcp_server 0.2.10 / plane_sdk 0.2.19):
- Call MCP
update_work_itemwith a valid full state UUID:{ "project_id": "<project-uuid>", "work_item_id": "<work-item-uuid>", "state": "ba5e07a3-b2a0-4d45-93bf-8b03b0593e13" } - MCP reports success; response still shows the previous state (e.g. Todo).
- Same PATCH via the REST API:
| Body | Result |
|---|---|
{"state": "<In Progress UUID>"} |
200, state unchanged |
{"state_id": "<In Progress UUID>"} |
200, state updated |
Endpoints tested (both behave the same for this field):
PATCH /api/v1/workspaces/<slug>/projects/<id>/issues/<id>/PATCH /api/v1/workspaces/<slug>/projects/<id>/work-items/<id>/
Comments and other updates via MCP work fine on the same token — this is isolated to the state field name.
Root Cause
UpdateWorkItem in plane_sdk exposes state: str | None and serializes that key as "state". The MCP tool mirrors that parameter name. Plane CE's issue/work-item update handler appears to read "state_id" and ignore unknown/extra "state" without erroring.
Cloud (and forks that followed #13-style renames) expect "state". So a single-field rename in either direction breaks the other target.
Suggested Fix
Send both fields when a state UUID is provided, e.g.:
{
"state": "<uuid>",
"state_id": "<uuid>"
}
That should satisfy both Cloud (state) and CE (state_id) without version sniffing. Same pattern is worth considering for any other id/rename pairs that have flipped between API generations (parent / parent_id, etc.) if those show the same silent-ignore behavior.
Alternatively: document which field each Plane edition accepts and branch in the SDK — dual-send is simpler and avoids another silent-break cycle.
Impact
Agent clients (Hermes, Cursor, Claude, etc.) cannot reliably move work items between states via official MCP on self-hosted CE. Reads/list/comments succeed; only state transitions fail silently.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the UpdateWorkItem SDK model and the MCP update_work_item tool, which the issue identifies as serializing the state field. Reproduce the PATCH behavior against the listed issue and work-item endpoints, then verify that state updates work on both CE and Cloud-style APIs without changing other fields.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100