Update any issue fields in one write (requires version)
update_issueUpdate any issue fields in one write (requires version).
One call = one new version, whatever the number of fields (PO 2026-09-25). links replaces the whole list; board-core adds/removes the inverse links on the other issues in the same commit. transition_issue, assign_issue, move_to_sprint and link_issues stay available as single-purpose tools and follow the same rules. fields (custom fields, spec D129) is merged key by key: send only the keys you change, null removes one.
Call get_issue first and pass its version. Change ANY number of fields in ONE call (title, body, type, priority, severity, status, assignee, points, sprint, release, parent, labels, links) — one call makes exactly one new version, so do not split an edit into several calls. links replaces the whole list. Images in body: upload + attach_file first, then  (never base64). severity (bugs, D113): critical / high / medium / low — how bad it is, separate from priority. release: a planned release id, or null — children of an epic follow the epic's release unless they name another; use move_to_release when the user gives a reason. comment is needed when status enters a requires_comment status (see transition_issue). fields (custom fields, D129) is merged key by key: send only the keys you change, null deletes a value; same types and errors as create_issue (400 unknown_field / invalid_field_value / formula_readonly; types of the field must include the issue's type). Sales & Billing installments (D130): "invoiced" = set invoiced_at (+ invoice_no); "paid" = set paid_at and paid_amount (= amount when paid in full) — dates YYYY-MM-DD, today's date unless the user says another. Do not move the deal to Closed on your own: the deal's all_paid flag says when everything is collected — tell the user and move it only when asked. Rollup fields (D131: a goal's progress / linked, a deal's delivery_progress) are computed like formulas — never in fields (400 formula_readonly); read them in computed. links entries take an issue key of this or another project of the company (403 link_target_forbidden when you cannot open the target's project) or {type: "delivers", id: "KEY/R-n"} for a release (404 release_not_found when it does not exist). For a Roadmap & Goals goal, moving start / end is a fields change like any other. Agent work context (D179): working = what you are doing on this card, how and why (markdown, ≤ 600 characters) and touches = the files, modules or APIs you change (≤ 10 entries ≤ 120) — the next agent or person on a linked card reads them before changing the same things. When you START a card, do it in ONE call: status (the in-progress status), working, touches and if_unassigned: true — an unassigned card becomes yours in the same commit; 409 already_assigned (details.assignee) means someone else holds it: nothing was written, pick another card or ask the user. Update working again only when your approach changes — not every step (comments are for decisions people should be emailed about). null clears; entering a done status clears both. working_at / working_by / working_by_agent are set by BoardMark. A result warnings[] item with code: unresolved_blocker means this card is blocked_by a card that is not done (blocker: key, title, status, its working): the move is done — read that card (get_issue_context) and agree the order before you change what it touches. code: touch_overlap (D180) means another in-progress card touches the same files / folders (overlap: key, title, assignee, its touch, yours, its working): the move is done — read its working and agree who changes what first. Body: Optional colour (D137, use sparingly; markdown stays the main format): <mark>text</mark> highlights (yellow; or <mark data-color="green">), <span data-color="red">text</span> colours text; colours yellow, green, red, blue, purple (e.g. green = passed / expected, red = bug / actual, purple = question); any other HTML is shown as plain text; keep the open and close tag in the same paragraph.
WRITE: version = from your latest read (get_issue, list_comments, list_sprints, get_doc, read_file). 409 version_conflict (details.current, details.current_version): re-read, re-apply your change, retry — never overwrite blindly; when the changes disagree, ask the user.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | ||
| type | No | ||
| links | No | The complete new list; inverse links on other issues are kept in step. | |
| title | No | ||
| fields | No | Custom field values (spec D129 (3), (6)), keyed by the project's field ids (get_project `frontmatter.fields`): text / select / customer / url / person = string, number / money = number, date = `YYYY-MM-DD`. Merged key by key with the stored values; `null` deletes a key. Unknown id → 400 `unknown_field` (details.field); wrong type, option not in `options`, bad date or url → 400 `invalid_field_value` (details.field, details.expected); formula field → 400 `formula_readonly`; a `required` field missing on create → 400 `invalid_field_value`. | |
| labels | No | ||
| parent | No | ||
| points | No | ||
| reason | No | Spec D144: why you make this change (≤ 200 characters). Optional, but give it when you act as an agent account — it is shown in the agent's run log ("moved KJ-12 To Do → In Progress because <reason>"). board-mcp records it in `agent.run`; board-core / board-files accept it and ignore it (it never changes the file, the version or the history). | |
| sprint | No | ||
| status | No | Status id; must exist in the project's `project.md` statuses. | |
| as_role | No | AI agents (spec D136): the role you work as in this session (e.g. Developer, QA, BA, DevOps) when the user told you one; else your token's role is used. Only changes lane warnings, never what you may do. Ignored for people. | |
| comment | No | Spec D143 (6): a comment written in the same commit as a status change (same rule as `transition_issue`). Needed when `status` moves into a status with `requires_comment: true` — missing or empty → 400 `comment_required` (`details.status`). Ignored (and refused with 400 `validation_failed`) when the request does not change the status. | |
| release | No | Releases on only (D113); a planned release of this project. | |
| touches | No | Spec D179: the files, modules or APIs your work changes (≤ 10 entries of ≤ 120 characters, e.g. `board-core/internal/engine/`), the complete list. `null` or [] clears it. | |
| version | Yes | Optimistic-lock version of the file; +1 on every write. Every write must send the version it read. | |
| working | No | Spec D179: what you are doing on this card, how and why (markdown, ≤ 600 characters) — read by the next agent or person on a linked card. Write it when you start and again only when your approach changes, not every step. `null` or "" clears it. Stamps `working_at` / `working_by`; cleared by board-core when the issue enters a done status. | |
| assignee | No | A person `usr_…` or an agent account `agt_…` (D144) from list_people. | |
| priority | No | Issue priority, highest first (spec D89). Missing = `medium`. | medium |
| severity | No | Bug severity (D113), every plan. | |
| issue_key | Yes | Issue key `{PROJECT}-{n}`, e.g. `KJ-101`. | |
| project_key | Yes | Project key, e.g. `KJ`. 2–10 chars, uppercase letters and digits, starts with a letter. | |
| if_unassigned | No | Spec D179: claim the issue atomically. true → if someone else holds it (`assignee` set and not you) nothing is written and the answer is `409 already_assigned` (`details.assignee`); otherwise the write goes ahead and, when the issue has no assignee and the request names none, you become the assignee in the same commit. "You" = your agent account `agt_…` (D144), else your user. Use it with `status`, `working` and `touches` in one call when you start a card. |