github sooperset/mcp-atlassian v0.24.0

2 hours ago

This release adds an HTTPS listener with private-CA support, lazy *_COMMAND credential resolution, a one-call jira_update_issue that can also transition, comment, and log work, epic summaries on jira_get_issue, and complete threaded inline-comment reads in Confluence, plus a large batch of Jira and Confluence content-conversion fixes. A few defaults changed. Please read Behaviour changes before upgrading.

⚠️ Behaviour changes

  • jira_add_comment(public=false) now keeps JSM notes internal. An explicit public=false used to be rewritten to "omitted" for projects outside JIRA_INTERNAL_ONLY_PROJECTS, so an intended internal JSM note was posted as a customer-visible comment. On a JSM customer request, public now always goes through the ServiceDesk API, and a failed call is reported instead of being downgraded to an ordinary comment. On an issue that is definitely not a JSM request, public is ignored and an ordinary comment is posted, as before. public=false together with a visibility restriction is still treated as omitted (#1748, #1820, fixes #1726)
  • REQUESTS_CA_BUNDLE / CURL_CA_BUNDLE are now honoured by the Jira and Confluence clients. atlassian-python-api passed its own verify value on every request, which overrode these variables. If one of them is already set in your environment, PAT and OAuth sessions now trust only that bundle. A bundle without public roots will reject Atlassian Cloud, and a path that does not exist makes the Jira or Confluence client fail on its first tool call with CA bundle configuration is invalid; see server logs. (#1586)
  • Cloud-only Jira tools are hidden on Server/Data Center. jira_batch_get_changelogs and jira_move_issue are no longer listed when the active Jira deployment is Server/DC, whether it comes from startup config or per-request URL headers. Direct calls fail the same way as an unknown tool. If the deployment type cannot be determined, the tools stay listed. Other Cloud-only features (Confluence permissions and page views, ProForma forms) are still listed on Server/DC and return an error when called (#1603, fixes #1082)
  • Bounded retries replace the library's unbounded Retry-After loop. atlassian-python-api's built-in header retry was unbounded and could loop on Retry-After: 0, which showed up as spurious 401s. It is now disabled. Instead, GET/HEAD/OPTIONS requests are retried up to 3 times by default on 429/502/503/504, honouring Retry-After up to 60 s (ATLASSIAN_RETRY_MAX_RETRY_AFTER) and never faster than exponential backoff. 401/403 are never retried. Set ATLASSIAN_RETRY_TOTAL=0 to disable (#1544, #1821, fixes #1543)
  • Clearing an issue's parent: on Cloud, parent: null (or "") now really clears the parent instead of returning the unchanged issue. On Server/DC the same request now fails early with an error that tells you to clear the Epic Link field instead (#1518, fixes #1500)
  • confluence_update_page reports page-property failures. If an emoji or page-width update fails (permission, lock, throttling), the call now raises an error instead of returning a refreshed page as if it had succeeded. Only a 404 on property delete counts as already removed (#1591, fixes #1557)

✨ Features

Server/Transport

  • Built-in HTTPS listener for the sse and streamable-http transports: set MCP_SSL_CERTFILE and MCP_SSL_KEYFILE (both required, unencrypted PEM key) to terminate TLS at the server with modern ciphers. Startup checks the pair before serving and aborts on a half-configured or truststore-incompatible setup. The HTTP transport docs cover the private-CA setup that goes with it (REQUESTS_CA_BUNDLE + SSL_CERT_FILE, with MCP_ATLASSIAN_USE_SYSTEM_TRUSTSTORE=false) (#1586, originally #1536)
  • Lazy credential resolution through JIRA_API_TOKEN_COMMAND, JIRA_PERSONAL_TOKEN_COMMAND, CONFLUENCE_API_TOKEN_COMMAND, and CONFLUENCE_PERSONAL_TOKEN_COMMAND. The command (for example gopass show -o … or op read …) runs on the first tool call for that service, not at startup, so a password manager is unlocked only when Atlassian tools are actually used. Commands run without a shell and with stdin closed, are bounded by CREDENTIAL_COMMAND_TIMEOUT (default 30s), and are never triggered by unauthenticated HTTP clients unless ALLOW_GLOBAL_CRED_FALLBACK=true. A plain token variable still takes precedence over its *_COMMAND variant (#1243)

Jira

  • jira_update_issue can now do a whole update in one call. fields is optional, and new transition, comment, comment_visibility, worklog, and worklog_started parameters run in a fixed order (fields, transition, comment, worklog, re-fetch). Completed and failed steps are reported separately (#1514, #1513)
  • jira_transition_issue accepts a transition name (case-insensitive, e.g. "In Progress") as well as a numeric ID, so you no longer need a jira_get_transitions call first (#1606)
  • jira_get_issue gains include=epic_summary: for an Epic it returns child counts by status, assignee, and issue type plus a completion percentage. Set epic_summary_children=true for a compact child list, and max_epic_children (1–500) to cap the aggregation (#1285)
  • jira_update_issue accepts attachments_base64 (a JSON array of {filename, content_base64}), so remote or containerised servers can attach files without a shared filesystem. It can be combined with path-based attachments (#1666, fixes #618)
  • jira_get_user_profile(user_identifier="me") resolves the current credentials in a single /myself call, without the global Browse Users permission. An optional expand returns groups / applicationRoles (#1571)
  • Markdown-to-ADF supports inline status lozenges with {status:color=green|title=Done}. An unknown or missing colour falls back to neutral (#1624)
  • Issue- and project-key validation is configurable through JIRA_ISSUE_KEY_PATTERN / JIRA_PROJECT_KEY_PATTERN, so Data Center instances with a custom jira.projectkey.pattern (e.g. digit-leading keys like 4ME-123) can be reached. An invalid regex logs a warning and keeps the default (#1538)

Confluence

  • confluence_get_inline_comments returns complete review threads: Cloud paginates root comments and every reply level, Server/DC paginates page comments, and each comment carries parent_comment_id, marker_ref, original_selection, and resolution_status when available. A Cloud read that cannot load a reply collection now fails instead of returning a partial tree (#1626)
  • Page responses (confluence_get_page, confluence_get_page_history) include version_author and version_date (raw ISO 8601), so you can see who last edited a page and when (#1445, fixes #1375)

New environment variables

MCP_SSL_CERTFILE, MCP_SSL_KEYFILE (#1586); JIRA_API_TOKEN_COMMAND, JIRA_PERSONAL_TOKEN_COMMAND, CONFLUENCE_API_TOKEN_COMMAND, CONFLUENCE_PERSONAL_TOKEN_COMMAND, CREDENTIAL_COMMAND_TIMEOUT (#1243); ATLASSIAN_RETRY_IGNORE_RETRY_AFTER (#1544); ATLASSIAN_RETRY_MAX_RETRY_AFTER (#1821); JIRA_ISSUE_KEY_PATTERN, JIRA_PROJECT_KEY_PATTERN (#1538). REQUESTS_CA_BUNDLE / CURL_CA_BUNDLE are now also read by the Jira and Confluence clients (#1586).

🐛 Fixed

Server/Transport

  • With an OAuth provider configured, requests without credentials are passed to FastMCP, which returns the RFC 9728 WWW-Authenticate: Bearer resource_metadata=… challenge. Standards-based clients can now discover the authorization server and register through DCR. Deployments without an OAuth provider still reject these requests (#1528, fixes #1257)
  • FastMCP floor raised to >=3.4.4 for its OAuth/DCR and HTTP-transport fixes. DCR redirect URIs that point at the proxy's own IdP callback are rejected with invalid_redirect_uri (#1533, closes #1097)
  • Retry-After: 0 from a gateway no longer triggers an endless zero-delay retry storm. Set ATLASSIAN_RETRY_IGNORE_RETRY_AFTER=true to always use exponential backoff (#1544, fixes #1543)
  • Tool schemas are now deterministic across worker processes. The default fields string was built from an unordered set, so multi-worker deployments advertised a different schema per process and clients such as Copilot CLI aborted with "tool catalog changed" (#1685, fixes #1662)

Jira

  • jira_add_comment keeps an explicit public=false, so internal JSM notes are no longer posted as customer-visible comments (#1748, fixes #1726; see Behaviour changes)
  • Issues in a JIRA_INTERNAL_ONLY_PROJECTS project that are not JSM customer requests (e.g. an agent-created Task) can be commented on again through the ordinary path (#1582, fixes #1574, originally #1575)
  • jira_assign_issue on Server/DC resolves email addresses, JIRAUSER… keys, and display names. It now picks exact matches instead of the first partial result and falls back to an issue-scoped assignable-user search (#1537, fixes #1535)
  • Epic operations work with localised Epic issue types (e.g. Эпик) on Server/DC. The project's Epic type is found from the Epic Name field schema instead of the English name (#1649, fixes #1552)
  • Fetching an epic's children falls through to the remaining lookup strategies when the first one returns no issues, instead of reporting an empty epic (#1509)
  • jira_update_issue reports attachment upload failures: a batch where nothing uploaded is no longer success: true, and per-file errors appear under operations_failed (#1577)
  • Empty or whitespace-only fields / additional_fields strings are treated as unset on create, update, and transition instead of raising a JSON error (#1619)
  • The environment system field is returned by jira_get_issue / jira_search when requested, in both Server/DC string and Cloud ADF form (#1550, fixes #1540)
  • Markdown in multi-line text (:textarea) custom fields is converted to ADF/wiki markup like description, instead of being sent as literal text (#1510, fixes #554)
  • Attachments uploaded through the JSM customer portal (reported as multipart/form-data) are detected as images by filename, so jira_get_issue_images and jira_download_attachments return them correctly (#1584, fixes #1583)
  • Markdown write fixes: Server/DC code fences use valid formatter names and accept languages like c# / c++ (#1676, fixes #1675). Dash-only and empty table rows are kept when converting to ADF (#1645, fixes #1629). A ---- rule after a blank line no longer turns into an empty h2. (#1590, fixes #1587). Blank-separated ordered lists stay in one list (#1522, fixes #1520)
  • Markdown read fixes: Jira list markers are converted before emphasis, so ** Level two no longer corrupts bold text or nesting (#1653, fixes #1651), and escaped \_ / \* survive every read instead of being rewritten (#1614, fixes #1610)

Confluence

  • Uploading a new version of an existing attachment works on Confluence Cloud again: the file part now carries a Content-Type, which Cloud started requiring (HTTP 415) (#1819)
  • Code and noformat macros convert to fenced Markdown blocks with their language tag and original indentation. Previously parameters such as texttrue leaked into the first line and the fence was lost. Storage/HTML output is unchanged (#1527)
  • confluence_update_page_section no longer deletes the following section when it sits inside an excerpt, expand, or layout macro (#1686)
  • content_format="storage" returns the exact body.storage.value, so elements such as ac:figure survive a round trip (#1609, fixes #1607)
  • confluence_get_page_children populates created, updated, and author by expanding page history (#1605, fixes #1602)
  • Failed page-property deletes are reported instead of returned as success (#1591, fixes #1557)
  • Attachment and image downloads under OAuth 2.0 (3LO) go through the api.atlassian.com gateway instead of the site host (#1580, fixes #1576)
  • Page reads by title, space page listings, and page properties handle the atlassian-python-api 5.x response shapes. The <5.0.0 dependency pin stays in place (#1621, fixes #1601)

Deployment

  • Docker images report the real release version instead of 0.0.0, and manual workflow runs on a tag no longer produce an invalid image tag (#1553)

🔒 Security

  • The SSE transport authentication fix from 0.23.1 is now on main and part of this release line (#1817)
  • JIRA_INTERNAL_ONLY_PROJECTS fails closed for percent-encoded issue keys (e.g. CC%2D1). Keys are classified the same way the HTTP transport decodes them, and non-canonical spellings of guarded keys are rejected before any lookup or write on the add, edit, transition-comment, and link-comment paths (#1582)
  • Each validated OAuth bearer is bound to its own upstream Atlassian token set, so a Jira tool call uses the right user's token and an MCP session cannot be reused by another user (#1528)
  • cryptography raised to >=46.0.7,<47 for CVE-2026-39892 (#1558)

🧰 Also in this release

An opt-in legacy toolset and a docs/migration-v1.md mapping table to prepare the v1 outcome-oriented tool migration. No tools are deprecated yet (#1511, #1512). Docs: the required server-side PAT placeholder for multi-user HTTP mode (#1564), the Jira Cloud transition-comment screen dependency (#1628), response-field reference updates (#1507), and an MCP stdio readiness probe for checking tool discovery without contacting Atlassian (#1555).

Contributors

Thanks to @trevorh (#1285, #1509), @fepape-ionos (#1243), @devnied (#1538), @unwnu (#1666), @ayishasi (#1571), @slinkardbrandon (#1624), @elementlu (#1606), @huyusong10 (#1626), @Wujidadi (#1445), @ningyixi (#1748), @FullYolk (#1603), @kovexison (#1544), @cblacknygc (#1528, #1533, #1555), @ulikoenig (#1685), @DougMidgley (#1537), @GuddXzy (#1649, #1653), @amitvijapur (#1518, #1590), @I3eka (#1577), @barrygfox (#1619, #1614), @Sanjays2402 (#1550, #1522), @beardthelion (#1510), @prabjohns-atex (#1584), @Rayan-and-beyond (#1676), @ConnorMoss02 (#1645), @hacctarr (#1527), @devonpmack (#1686), @Tethys0 (#1609), @Cchena1 (#1605), @koleharv (#1591), @atirna (#1621), @rophy (#1553, #1558), @joenermunch (#1564), @teddiesloco (#1628), and @mhollingsworth-cs (#1595)!

Additional thanks to @endofcake, whose TLS listener and private-CA work (#1536) was carried into #1586; @prabjohns-atex for the original JSM comment fix (#1575) carried into #1582; and @AmirF194 for validating the Cloud-only tool exposure in #1082.

Full Changelog: v0.23.1...v0.24.0

Don't miss a new mcp-atlassian release

NewReleases is sending notifications on new releases.