Jira Cloud connector

The Jira connector lets an AI agent read issues, comment, and update fields in your Jira Cloud project — without holding your Jira credentials, and with sensitive changes (like moving an issue to "Done") paused for a human. The agent proposes the change; Axtary authorizes the exact payload and makes the Jira call from inside your machine.

What it's for

Say you have an agent that triages incoming bugs: it reads an issue, adds a summary comment, and tweaks the priority. Useful — but you don't want it silently closing tickets or transitioning issues through your workflow without a human glance. This connector lets the everyday actions through and stops to ask before a protected status change, while keeping the Jira token off the agent entirely.

The agent never receives the Jira credential. The Jira REST calls happen in the local enforcement plane, only after the exact action has been authorized.

What an agent can do

ActionWhat it doesDefault treatment
jira.issues.readRead one issue by its keyallowed within your project scope
jira.comments.createAdd a comment (plain text is converted to Jira's format)allowed within your project scope
jira.issues.updateUpdate summary, description, priority, or statuspauses for approval on protected statuses

Status changes are handled carefully. Status isn't just another field in Jira — it's a workflow transition. So when an agent asks to move an issue to, say, "Done", Axtary first reads the issue's available transitions, resolves the requested status to the matching transition, and submits that. If the target isn't reachable from the current state, it fails before changing anything and tells you which statuses were available.

What happens when the agent updates an issue

  1. The agent proposes the change — e.g. set issue SCRUM-1's status to "Done" — and sends it to Axtary.
  2. Policy decides. A comment or priority tweak inside your project is allowed; a protected status like "Done" returns step_up and waits.
  3. A human approves the exact change, bound to its payload hash.
  4. Axtary executes the Jira REST call locally and records a decision plus an outcome in the tamper-evident ledger.
$ # agent tries to move an issue to a protected status
decision: step_up
reasons:  [jira_update_inside_policy, step_up_protected_status]

Connect it

Option 1: API token (simplest, live-verified)

Create an API token for a dedicated Jira Cloud user (not your own admin account) and export it with that account's email:

export JIRA_EMAIL="you@example.com"
export JIRA_API_TOKEN="..."

Point Axtary at your site:

adapters:
  jira:
    mode: rest
    auth: api_token
    emailEnv: JIRA_EMAIL          # the env var names — not the values
    tokenEnv: JIRA_API_TOKEN
    siteUrl: https://your-site.atlassian.net

Option 2: OAuth 2.0 (3LO)

Status: the API-token path above is verified end to end. This OAuth path is implemented and unit-tested but has not yet been exercised against a live Atlassian OAuth app — verify it in your own environment before relying on it in production.

Register an Atlassian OAuth 2.0 integration with scopes read:jira-work, write:jira-work, read:me, and offline_access, then run the browser flow. Like every Axtary OAuth flow, the token is captured and stored locally — Axtary never sees your client secret:

export AXTARY_JIRA_CLIENT_ID="..."
export AXTARY_JIRA_CLIENT_SECRET="..."

axtary connect jira --redirect-uri https://your-tunnel.example/callback

Atlassian requires the callback to match the registered URL, and the HTTPS URL should forward to the local listener on port 7878. Axtary discovers the Jira sites the token can reach and stores the chosen cloud ID and site URL as non-secret metadata; the access and rotating refresh tokens stay in the local credential broker. If the account can reach more than one site, name it:

axtary connect jira \
  --redirect-uri https://your-tunnel.example/callback \
  --cloud-id YOUR_CLOUD_ID
adapters:
  jira:
    mode: rest
    auth: oauth
    tokenEnv: JIRA_OAUTH_TOKEN
    cloudIdEnv: AXTARY_JIRA_CLOUD_ID
    siteUrl: https://your-site.atlassian.net

The broker credential takes precedence over the fallback env vars. Expired access tokens are refreshed locally, and Atlassian's replacement refresh token is saved with the new access token.

Check it before you write

Confirm the credential works without touching any issue — the smoke check only calls GET /rest/api/3/myself (it identifies the authenticated user and nothing else):

axtary doctor connectors --config axtary.yml
axtary smoke --config axtary.yml

Then, before pointing it at real tickets, exercise it in a throwaway project: send a read, a reversible comment, and a non-destructive field update, confirm the outcomes in the ledger, and run axtary attest-ledger followed by axtary verify-export to prove the record is intact.

FAQ

Does the agent ever see my Jira token? No. The token stays in the local credential broker or env; the agent only talks to Axtary, which makes the Jira call for it.

Can the agent close or transition issues on its own? Only if your policy allows that status. Protected statuses return step_up and wait for a human; an unreachable transition fails before anything changes.

What if I ask to move an issue to a status it can't reach? The update fails before mutating the issue and reports which statuses were actually available from the current state.

Atlassian references