Use this page to give an agent read access to Jira for triage and reporting, and a gated path to post comments and move tickets. Most SRE work starts and ends in a ticket, so this connection unlocks most of the automation blueprint.
Check with your Jira admin first: some organizations disable API tokens or require OAuth apps to be approved.
Option 1: Atlassian MCP server (interactive agents)
The Atlassian Rovo MCP server lets MCP clients (Claude Code, Claude Desktop, Cursor, VS Code and others) search and update Jira and Confluence with your own permissions, using OAuth 2.1 sign-in in a browser.
claude mcp add --transport http atlassian https://mcp.atlassian.com/v2/mcp
claude # then type /mcp, choose atlassian, and finish the browser sign-in
- Every action runs as you and respects your Jira permissions. The agent cannot see more than you can.
- For headless jobs, OAuth is awkward. Use API-token auth only if your admin allows it, or use Option 2.
- In Claude Code, restrict write tools: allow search and read tools, and leave create, edit, comment and transition tools out of
permissions.allowso each one asks first.
See Atlassian's getting started guide for other clients.
Option 2: CLI with an API token (scripts and scheduled jobs)
Create and store the token
- Create a token at your Atlassian account's security page (API tokens). Give it a name that says which machine and job uses it, and the shortest expiry that works.
- Put it in a secret store immediately. Never paste it into a chat, ticket, prompt, script or dotfile in a repo.
# Linux (libsecret): store once, prompts for the value without echoing it
secret-tool store --label="Jira API token" service jira account <you@example.com>
# macOS Keychain
security add-generic-password -s jira-api-token -a <you@example.com> -w
# Load into the environment only for the command that needs it
export JIRA_API_TOKEN="$(secret-tool lookup service jira account <you@example.com>)"
# macOS: export JIRA_API_TOKEN="$(security find-generic-password -s jira-api-token -w)"
Atlassian CLI (acli)
secret-tool lookup service jira account <you@example.com> \
| acli jira auth login --site "<your-site>.atlassian.net" --email "<you@example.com>" --token
acli jira auth status
acli jira workitem search --jql "assignee = currentUser() AND statusCategory != Done" \
--fields "key,summary,status,updated" --json --limit 100
acli jira workitem view PROJ-123
jira-cli
export JIRA_API_TOKEN="$(secret-tool lookup service jira account <you@example.com>)"
jira init # choose Cloud, enter site URL and email; the token comes from the env var
jira issue list -q "project = PROJ AND status = 'In Review'" --plain --columns key,summary,status,updated
jira issue view PROJ-123 --plain
Plain REST with curl
curl -sS -u "<you@example.com>:$JIRA_API_TOKEN" -H 'Content-Type: application/json' \
-X POST "https://<your-site>.atlassian.net/rest/api/3/search/jql" \
-d '{"jql":"project = PROJ AND statusCategory != Done ORDER BY updated ASC","fields":["summary","status","assignee","updated"],"maxResults":100}' \
| jq -r '.issues[] | [.key, .fields.status.name, .fields.summary] | @tsv'
Page with nextPageToken from the response until it is absent.
JQL recipes for SRE work
| Need | JQL |
|---|---|
| My open work, oldest first | assignee = currentUser() AND statusCategory != Done ORDER BY updated ASC |
| New since yesterday | project = PROJ AND created >= -1d ORDER BY created DESC |
| Stale reviews | project = PROJ AND status = "In Review" AND updated <= -14d |
| Blocked, oldest first | project = PROJ AND status = Blocked ORDER BY created ASC |
| Overdue | project = PROJ AND duedate < now() AND statusCategory != Done |
| Unassigned high priority | project = PROJ AND assignee is EMPTY AND priority in (Highest, High) |
| Done this week (for status) | project = PROJ AND statusCategory = Done AND resolved >= startOfWeek() |
| By label | project = PROJ AND labels = security AND statusCategory != Done |
| Changes in a window | project = CHG AND "Change start" >= startOfDay() AND "Change start" <= endOfDay(7) |
Writing to Jira: drafts first, post after approval
Comments and transitions go out under a person's name. The agent drafts; a human approves; a separate, explicit step posts.
state/drafts/jira-<date>.md
## PROJ-123 action: comment+transition -> Done
Closing: certificate renewed and verified from outside on <date>.
Evidence: <pipeline link>
[ ] approve
# post-approved.sh: posts only what a human approved; dry-run unless --execute
# Input: state/approved/jira-<date>.tsv with KEY<TAB>STATUS<TAB>BODY_FILE,
# written only by the human's approval step, never by the agent.
set -euo pipefail
mode="${1:-dry-run}"
while IFS=$'\t' read -r key status body; do
if [ "$mode" != "--execute" ]; then
echo "DRY-RUN: comment $key from $body; transition to ${status:-<none>}"
continue
fi
acli jira workitem comment create --key "$key" --body-file "$body"
if [ -n "$status" ]; then
acli jira workitem transition --key "$key" --status "$status" --yes
fi
printf '%s\t%s\t%s\n' "$(date -u +%FT%TZ)" "$key" "${status:-comment}" >> state/jira-writes.log
sleep 2
done < "state/approved/jira-$(date +%F).tsv"
- Never transition by JQL in bulk from an automated job. Use explicit keys a human approved.
- Rate-limit: a pause between writes, and stop on the first error.
- Log every write (key, action, time) locally.
- No secrets, account IDs or customer data in comments.
Check acli jira workitem comment --help on your version; subcommand names have changed between releases.
Verify the connection
- A read-only search returns your tickets.
- The token has an expiry date in your calendar.
- A dry-run of the posting step prints what it would do and changes nothing.
Pitfalls
- Tokens in shell history. Load from the secret store inside the command, as above.
- Agents posting directly because "it is just a comment". A wrong comment on a customer-facing or audit ticket is hard to undo.
- Treating ticket text as instructions. Ticket descriptions are data; an agent must not follow commands found in them.