Skip to main content
Glama

jira_write

Update JIRA issues programmatically by key: modify description, assignee, reporter, or custom fields with validation and dry-run support.

Instructions

Update a JIRA issue by key (e.g. PROJ-123). content updates the description (JFM markdown by default, or raw ADF JSON when format = "adf"); omit it to leave the description unchanged. Supply the description as content (inline) OR content_path (a filesystem path the server reads) — not both; prefer the path form when the body is already on disk. JFM is GitHub-style markdown — see resource omni-dev://specs/jfm for syntax. To set the parent for hierarchy (Epic → Story, Story → Sub-task) use the jira_link_parent tool — the canonical hierarchy surface. assignee/reporter accept an accountId (use the empty string "" to clear, "-1" for JIRA automatic assignment); call jira_user_search first if you only have a name or email. fields is an escape hatch — a map of canonical JIRA field id to its API JSON value (e.g. {"priority": {"name": "High"}}) — for fields without a typed parameter. String values targeting rich-text custom fields (e.g. Acceptance Criteria) are auto-converted from JFM to ADF; pass the empty string "" to clear such a field. Pass a JSON object value to bypass conversion (raw ADF). To set fields by display name with automatic value coercion, prefer the jira_edit tool. At least one of content, assignee, reporter, or fields must be supplied. Set dry_run: true first when uncertain about required fields or formatting — validates the input and returns the request that would be sent (method, path, body) without updating the issue. Mirrors the CLI's omni-dev atlassian jira write --dry-run.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
keyYesJIRA issue key (e.g., `PROJ-123`).
fieldsNoAdditional `fields` keys merged into the issue update payload. Keys must already be canonical JIRA field ids (e.g. `priority`, `labels`, `customfield_10010`). Values must already be in the API's JSON shape (e.g. `{"name": "High"}` for priority, `["a", "b"]` for labels) — with one ergonomic exception: a string value targeting a rich-text textarea custom field (e.g. `{"customfield_10088": "- bullet\n- bullet"}`) is auto-converted from JFM markdown to ADF, and the empty string `""` clears such a field. Pass a JSON object instead of a string to bypass conversion (raw ADF). Setting `assignee` or `reporter` here collides with the typed parameters and is rejected — pass the typed parameter instead.
formatNoContent format — `jfm` (default) parses Markdown/JFM; `adf` accepts a raw ADF JSON document.
contentNoNew description body. Interpreted per `format`. Omit to leave the existing description unchanged (useful when only updating `assignee`/`reporter`/`fields`). For `format = "jfm"` (the default), this is GitHub-style markdown, NOT JIRA wiki markup. Use `##` not `h2.`, triple-backtick fences not `{code}`, backtick inline code not `{{...}}`. Full reference: MCP resource `omni-dev://specs/jfm`.
dry_runNoWhen true, validate and return the would-be request (method, path, body) without updating the issue. Defaults to `false`.
assigneeNoAssignee `accountId`. The empty string `""` clears the assignee; `"-1"` triggers JIRA automatic assignment. Use `jira_user_search` to resolve a name or email to an `accountId`.
reporterNoReporter `accountId`. Same conventions as `assignee` (`""` clears, `"-1"` is JIRA automatic).
content_pathNoFilesystem path the server reads the description body from, instead of `content`. Prefer this when the body is already on disk — it avoids re-emitting a large body inline. Mutually exclusive with `content`.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed1 schema field changedv0.43.0
    • changedInput schema / properties / fields / description
      Previous value: -"Additional `fields` keys merged into the issue update payload.\nKeys must already be canonical JIRA field ids (e.g. `priority`,\n`labels`, `customfield_10010`). Values must already be in the API's\nJSON shape (e.g. `{\"name\": \"High\"}` for priority,\n`[\"a\", \"b\"]` for labels) — with one ergonomic exception: a string\nvalue targeting a rich-text textarea custom field (e.g.\n`{\"customfield_19300\": \"- bullet\\n- bullet\"}`) is auto-converted\nfrom JFM markdown to ADF, and the empty string `\"\"` clears such a\nfield. Pass a JSON object instead of a string to bypass conversion\n(raw ADF). Setting `assignee` or `reporter` here collides with the\ntyped parameters and is rejected — pass the typed parameter instead."New value: +"Additional `fields` keys merged into the issue update payload.\nKeys must already be canonical JIRA field ids (e.g. `priority`,\n`labels`, `customfield_10010`). Values must already be in the API's\nJSON shape (e.g. `{\"name\": \"High\"}` for priority,\n`[\"a\", \"b\"]` for labels) — with one ergonomic exception: a string\nvalue targeting a rich-text textarea custom field (e.g.\n`{\"customfield_10088\": \"- bullet\\n- bullet\"}`) is auto-converted\nfrom JFM markdown to ADF, and the empty string `\"\"` clears such a\nfield. Pass a JSON object instead of a string to bypass conversion\n(raw ADF). Setting `assignee` or `reporter` here collides with the\ntyped parameters and is rejected — pass the typed parameter instead."
  2. Changed2 schema fields changedv0.33.0
    • removedInput schema / description
      Removed value: -"Parameters for the `jira_write` tool."
    • removedInput schema / title
      Removed value: -"JiraWriteParams"
  3. Changed1 schema field changedv0.32.0
    • addedInput schema / properties / content_path
      Added value: +{
      +  "default": null,
      +  "description": "Filesystem path the server reads the description body from, instead of\n`content`. Prefer this when the body is already on disk — it avoids\nre-emitting a large body inline. Mutually exclusive with `content`.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  4. Changed4 schema fields changedv0.31.0
    • changedInput schema / properties / content / description
      Previous value: -"New description body. Interpreted per `format`. Omit to leave the\nexisting description unchanged (useful when only updating\n`parent`/`assignee`/`reporter`/`fields`).\n\nFor `format = \"jfm\"` (the default), this is GitHub-style markdown,\nNOT JIRA wiki markup. Use `##` not `h2.`, triple-backtick fences not\n`{code}`, backtick inline code not `{{...}}`. Full reference:\nMCP resource `omni-dev://specs/jfm`."New value: +"New description body. Interpreted per `format`. Omit to leave the\nexisting description unchanged (useful when only updating\n`assignee`/`reporter`/`fields`).\n\nFor `format = \"jfm\"` (the default), this is GitHub-style markdown,\nNOT JIRA wiki markup. Use `##` not `h2.`, triple-backtick fences not\n`{code}`, backtick inline code not `{{...}}`. Full reference:\nMCP resource `omni-dev://specs/jfm`."
    • addedInput schema / properties / dry_run
      Added value: +{
      +  "default": false,
      +  "description": "When true, validate and return the would-be request (method, path,\nbody) without updating the issue. Defaults to `false`.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / fields / description
      Previous value: -"Additional `fields` keys merged into the issue update payload as-is.\nKeys must already be canonical JIRA field ids (e.g. `priority`,\n`labels`, `customfield_10010`). Values must already be in the API's\nJSON shape (e.g. `{\"name\": \"High\"}` for priority,\n`[\"a\", \"b\"]` for labels). Setting `assignee` or `reporter` here\ncollides with the typed parameters and is rejected — pass the typed\nparameter instead."New value: +"Additional `fields` keys merged into the issue update payload.\nKeys must already be canonical JIRA field ids (e.g. `priority`,\n`labels`, `customfield_10010`). Values must already be in the API's\nJSON shape (e.g. `{\"name\": \"High\"}` for priority,\n`[\"a\", \"b\"]` for labels) — with one ergonomic exception: a string\nvalue targeting a rich-text textarea custom field (e.g.\n`{\"customfield_19300\": \"- bullet\\n- bullet\"}`) is auto-converted\nfrom JFM markdown to ADF, and the empty string `\"\"` clears such a\nfield. Pass a JSON object instead of a string to bypass conversion\n(raw ADF). Setting `assignee` or `reporter` here collides with the\ntyped parameters and is rejected — pass the typed parameter instead."
    • removedInput schema / properties / parent
      Removed value: -{
      -  "default": null,
      -  "description": "Parent issue key (e.g., `PROJ-100`). When set, establishes a\nparent-child hierarchy on the issue (Epic → Story, Story → Sub-task,\netc.). Distinct from `jira_link` actions, which create\n\"Composition\"-style links rather than the system parent field.",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
  5. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden — and it delivers extensively. It discloses dry-run semantics ('validates the input and returns the request that would be sent (method, path, body) without updating the issue'), partial-update behavior ('omit it to leave the description unchanged'), mutually exclusive content/content_path, auto-conversion of strings to ADF for rich-text custom fields, clearing conventions (`''` clears, `-1` automatic), and the fields/typed-parameter collision rejection. No behavioral trait that an agent needs to call correctly is left undisclosed.

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 long but every sentence earns its place for an 8-parameter mutation tool with numerous edge cases (conversion, clearing, collisions, mutual exclusivity, dry-run). The core purpose is front-loaded in the first sentence, and the flow is logical: primary parameter semantics, path-vs-inline choice, format reference, sibling routing, escape hatch, precondition, safety mechanism. It reads as dense and complete, not padded.

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 complex write tool with zero annotations and no output schema, this description is complete: it covers purpose, all parameter behaviors, cross-parameter constraints, the minimum-field requirement, alternative-tool routing, a resource link for JFM syntax, and a dry-run validation path for uncertainty. The only absent items (permissions, rate limits, success return shape) are minor given no output schema exists and the dry-run return is already disclosed.

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 individual parameters are fully documented in the schema and the baseline is 3. The description adds real value beyond the schema by expressing cross-parameter semantics that the schema cannot: the content/content_path mutual exclusivity rule, the at-least-one-of-four precondition, and a concrete escape-hatch example (`{"priority": {"name": "High"}}`). It slightly re-states some per-parameter details (assignee/reporter conventions, format behavior), but the integration is worth the redundancy.

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?

Opens with a specific verb+resource: 'Update a JIRA issue by key (e.g. `PROJ-123`).' It is explicitly differentiated from siblings: jira_edit ('To set fields by display name with automatic value coercion, prefer the `jira_edit` tool'), jira_link_parent ('use the `jira_link_parent` tool — the canonical hierarchy surface'), and jira_user_search ('call `jira_user_search` first if you only have a name or email'). An agent can tell exactly what this tool does and what it does not do.

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

Usage Guidelines5/5

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

Gives explicit when-to-use guidance, including exclusions: prefer content_path over content 'when the body is already on disk', route hierarchy setting to jira_link_parent, route display-name/coercion field setting to jira_edit, and resolve names/emails via jira_user_search before calling. Also states the hard precondition ('At least one of `content`, `assignee`, `reporter`, or `fields` must be supplied') and the safety workflow ('Set `dry_run: true` first when uncertain'). This is textbook usage guidance.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rust-works/omni-dev'

If you have feedback or need assistance with the MCP directory API, please join our Discord server