apply_kanban_operations Edit cards atomically. Agent edits require registered agentId (QRAFT_AGENT_ID), on the command or an operation; names alone are rejected. Claim with assign_self(onlyIfUnassigned=true) + move_card; work only after success. patch_card guards expected fields; move_card guards expectedPositionVersion; omit guards to write without a read. Upload attachments once. Prefer archive over deletion; delete_card requires expectedVersion and follows owner policy. Reuse revisionAfter/kanbanVersions; replay lost requests identically. Details: /docs/mcp/apply_kanban_operations. Edit Kanban atomically with conditional merging by default. Attachments: upload once using an existing HTTPS URL (upload_asset_from_url), local binary (create_asset_upload), or base64 only as fallback (upload_asset). add_attachment takes cardId and attachment={id,media:{id:uploadedAssetId,mimeType,filename}}, max 50/card. Reuse uploaded media IDs across cards without uploading again. The first image becomes the cover automatically. set_cover takes cardId, attachmentId (an attached image or null for no cover), expectedAttachmentId (current cover ID or null). remove_attachment takes cardId, attachmentId and the exact expected attachment from a focused card read. Removing the cover chooses the next remaining image or clears it. Removal detaches only; shared files and undo/history retention remain safe. Attachments use existing R2 limits: raster images 8 MiB, general files 16 MiB, plain text 1 MiB. Send multiple attachments and cover selection in one atomic batch. Example: add_attachment(cardId=card_release, attachment={id:attachment_sketch, media:{id:uploadedAssetId, mimeType:image/png, filename:sketch.png}}). add_comment appends to a card's Discussion using cardId, unique commentId and body (1-8000 characters, max 500 messages/card). Agent callers MUST act as someone on every add_comment and assign_self: agentId (your registered Qraft agent persona, env QRAFT_AGENT_ID; records its name and avatar). Free-text agentName identities are rejected. Every Kanban mutation, including add_card and move_card, must include agentId on the command or an operation; the command identity is inherited by comments and self-assignment. Use your registered agent with an active hosting grant; its home project does not limit access authorized by your connection and document membership. Agent identities are always marked AI. Qraft stamps the authenticated user/client identity and creation time; these cannot be supplied by the operation. Concurrent posts merge. To prevent two workers taking the same task, use assign_self with onlyIfUnassigned:true, optionally batched with move_card to a board-specific columnId. Start work only after committed success (not a dry run). Any existing assignee, including yourself, rejects the entire batch with revision_conflict; read the card and choose other work, never retry without the guard. Retry lost responses with the identical requestId/input. This is a claim-time check, not a permanent lock. Without the flag, assign_self adds the authenticated human or named agent without replacing existing assignees (max 30/card). assign_person adds an existing document member by userId; it does not grant access. unassign_card removes only the supplied identityId with its expected identity snapshot from a card read. Stable identityId is the persona for agentId callers, otherwise userId, source, clientId and agentName, so a human and several agents can coexist. Card reads include assignees keyed by identityId; discussion author.identityId matches. Use read_kanban(discussionCardId) for a thread. Reuse the same requestId on retry; do not resubmit the whole thread. patch_board edits the board description (max 2000 characters) and instructions (max 20000) using patches with field, expected, value; missing metadata has expected value ''. Send only changed fields. Rename the board through manage_sheets rename_sheet. patch_card checks each field's expected value, so text edits can merge with unrelated moves or other field edits. Optional branch (max 255) and worktree (max 1000) strings record the git checkout another agent should resume; patch them independently and send '' to clear. move_card takes expectedPositionVersion, destination columnId and optional beforeCardId (null appends), or position:'top'|'bottom' to place it without reading the column (add_card accepts position too). Moves do not invalidate expected-value checks on title, description or other content fields. Whole-card versions include position. Reorder columns with expectedOrderVersion. Archive/restore with a patch to archived. delete_card is permanent and requires expectedVersion plus explicit user intent; prefer archiving. A column must be empty, including archived cards, before deletion. New cards, columns and checklist items need unique IDs. read_kanban provides preconditions. A batch of only add_card and add_comment may omit expectedRevision (no read needed). Reuse revisionAfter and kanbanVersions (cardId:position and order keys); retry lost responses with identical requestId/input. Dry runs do not save or return committed versions.