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 explicitpublic=falseused to be rewritten to "omitted" for projects outsideJIRA_INTERNAL_ONLY_PROJECTS, so an intended internal JSM note was posted as a customer-visible comment. On a JSM customer request,publicnow 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,publicis ignored and an ordinary comment is posted, as before.public=falsetogether with avisibilityrestriction is still treated as omitted (#1748, #1820, fixes #1726)REQUESTS_CA_BUNDLE/CURL_CA_BUNDLEare now honoured by the Jira and Confluence clients. atlassian-python-api passed its ownverifyvalue 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 withCA bundle configuration is invalid; see server logs.(#1586)- Cloud-only Jira tools are hidden on Server/Data Center.
jira_batch_get_changelogsandjira_move_issueare 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-Afterloop. atlassian-python-api's built-in header retry was unbounded and could loop onRetry-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, honouringRetry-Afterup to 60 s (ATLASSIAN_RETRY_MAX_RETRY_AFTER) and never faster than exponential backoff. 401/403 are never retried. SetATLASSIAN_RETRY_TOTAL=0to 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_pagereports 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
sseandstreamable-httptransports: setMCP_SSL_CERTFILEandMCP_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, withMCP_ATLASSIAN_USE_SYSTEM_TRUSTSTORE=false) (#1586, originally #1536) - Lazy credential resolution through
JIRA_API_TOKEN_COMMAND,JIRA_PERSONAL_TOKEN_COMMAND,CONFLUENCE_API_TOKEN_COMMAND, andCONFLUENCE_PERSONAL_TOKEN_COMMAND. The command (for examplegopass show -o …orop 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 byCREDENTIAL_COMMAND_TIMEOUT(default 30s), and are never triggered by unauthenticated HTTP clients unlessALLOW_GLOBAL_CRED_FALLBACK=true. A plain token variable still takes precedence over its*_COMMANDvariant (#1243)
Jira
jira_update_issuecan now do a whole update in one call.fieldsis optional, and newtransition,comment,comment_visibility,worklog, andworklog_startedparameters run in a fixed order (fields, transition, comment, worklog, re-fetch). Completed and failed steps are reported separately (#1514, #1513)jira_transition_issueaccepts a transition name (case-insensitive, e.g."In Progress") as well as a numeric ID, so you no longer need ajira_get_transitionscall first (#1606)jira_get_issuegainsinclude=epic_summary: for an Epic it returns child counts by status, assignee, and issue type plus a completion percentage. Setepic_summary_children=truefor a compact child list, andmax_epic_children(1–500) to cap the aggregation (#1285)jira_update_issueacceptsattachments_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-basedattachments(#1666, fixes #618)jira_get_user_profile(user_identifier="me")resolves the current credentials in a single/myselfcall, without the global Browse Users permission. An optionalexpandreturnsgroups/applicationRoles(#1571)- Markdown-to-ADF supports inline status lozenges with
{status:color=green|title=Done}. An unknown or missing colour falls back toneutral(#1624) - Issue- and project-key validation is configurable through
JIRA_ISSUE_KEY_PATTERN/JIRA_PROJECT_KEY_PATTERN, so Data Center instances with a customjira.projectkey.pattern(e.g. digit-leading keys like4ME-123) can be reached. An invalid regex logs a warning and keeps the default (#1538)
Confluence
confluence_get_inline_commentsreturns complete review threads: Cloud paginates root comments and every reply level, Server/DC paginates page comments, and each comment carriesparent_comment_id,marker_ref,original_selection, andresolution_statuswhen 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) includeversion_authorandversion_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.4for its OAuth/DCR and HTTP-transport fixes. DCR redirect URIs that point at the proxy's own IdP callback are rejected withinvalid_redirect_uri(#1533, closes #1097) Retry-After: 0from a gateway no longer triggers an endless zero-delay retry storm. SetATLASSIAN_RETRY_IGNORE_RETRY_AFTER=trueto always use exponential backoff (#1544, fixes #1543)- Tool schemas are now deterministic across worker processes. The default
fieldsstring 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_commentkeeps an explicitpublic=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_PROJECTSproject 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_issueon 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_issuereports attachment upload failures: a batch where nothing uploaded is no longersuccess: true, and per-file errors appear underoperations_failed(#1577)- Empty or whitespace-only
fields/additional_fieldsstrings are treated as unset on create, update, and transition instead of raising a JSON error (#1619) - The
environmentsystem field is returned byjira_get_issue/jira_searchwhen 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 likedescription, 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, sojira_get_issue_imagesandjira_download_attachmentsreturn 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 emptyh2.(#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 twono 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
texttrueleaked into the first line and the fence was lost. Storage/HTML output is unchanged (#1527) confluence_update_page_sectionno longer deletes the following section when it sits inside anexcerpt,expand, orlayoutmacro (#1686)content_format="storage"returns the exactbody.storage.value, so elements such asac:figuresurvive a round trip (#1609, fixes #1607)confluence_get_page_childrenpopulatescreated,updated, andauthorby 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.comgateway 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.0dependency 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
mainand part of this release line (#1817) JIRA_INTERNAL_ONLY_PROJECTSfails 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)
cryptographyraised to>=46.0.7,<47for 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