search_issues | jira:issues:read | Search Jira issues using JQL (Jira Query Language). Returns {issues, nextPageToken, isLast} — pass nextPageToken back to fetch the next page (the legacy startAt/total response shape was retired by Atlassian on 2025-05-01). |
get_issue | jira:issues:read | Get a single Jira issue by its key (e.g. ACME-123). STRONGLY recommend passing fields — Atlassian's default response includes 100+ custom-field entries (most null) and runs ~10 KB per issue. A typical agent request only needs a handful: try "summary,status,priority,assignee,reporter,description,issuetype,labels,created,updated". Description bodies come back as ADF (Atlassian Document Format) JSON, not plain text. |
get_transitions | jira:issues:read | List the workflow transitions currently available on a Jira issue. Each entry carries an id (string) you pass to transition_issue. Transition IDs and labels vary per project workflow — "Done" might be "31" in one project, "41" or "61" in another — so always discover via this tool before calling transition_issue instead of guessing. |
create_issue | jira:issues:write | Create a new Jira issue. IMPORTANT: Atlassian Cloud's REST API v3 requires the description field (if present) to be an Atlassian Document Format (ADF) JSON object, NOT a plain string — passing plain text returns HTTP 400 with no useful error. If you don't need a description, omit it entirely (the example below shows the minimal valid shape). If you DO need one, wrap your text in ADF as shown in the second example. |
update_issue | jira:issues:write | Update an existing Jira issue. Two payloads, either or both: fields assigns values, update runs verb-style operations (add/edit/remove) for the things fields cannot express — worklogs above all, since timeSpent is derived from worklogs and is read-only as a field. Log time with update, not fields. Same ADF caveat as create_issue: any description you pass must be an ADF doc, not a plain string, or Atlassian returns HTTP 400. |
add_worklog | jira:issues:write | Log time against a Jira issue. This is the endpoint to use for time tracking: it returns the created worklog (with its id), so the caller can prove the time landed. update_issue's update verb also carries worklog ops, but answers 204 with no body — a worklog the project silently discards is indistinguishable there from one it stored. Note that time tracking must be enabled on the project; if it is not, Jira accepts the call and records nothing. |
transition_issue | jira:issues:write | Transition a Jira issue through a workflow (e.g. Open → In Progress → Done). Discover valid transition IDs first via get_transitions — IDs are workflow-specific and don't match across projects. |
list_link_types | jira:issues:read | List the issue link types available on this Jira site. Returns {issueLinkTypes: [{id, name, inward, outward}]} — e.g. name "Blocks" with inward "is blocked by" and outward "blocks". Call this before link_issues: type names are configured per site ("Blocks", "Relates", "Duplicate", "Cloners", and custom ones), so guessing a name returns HTTP 404. The inward/outward wording also tells you which issue goes in which slot. |
link_issues | jira:issues:write | Create a link between two Jira issues. Direction is carried by the slots, not the type name: with "Blocks", outwardIssue blocks inwardIssue — so {"type":{"name":"Blocks"},"outwardIssue":{"key":"ACME-1"},"inwardIssue":{"key":"ACME-2"}} reads "ACME-1 blocks ACME-2". Discover type names with list_link_types first; an unknown name returns HTTP 404. Succeeds with 201 and an empty body. get_issue omits links unless you pass fields="issuelinks". |
unlink_issues | jira:issues:write | Delete an issue link by its id. Get the id from get_issue with fields="issuelinks" — each entry in the returned issuelinks array carries its own id. This removes the relationship from both issues; it does not touch either issue otherwise. |
list_projects | jira:projects:read | List Jira projects the caller can see. Paginated — returns {values, startAt, maxResults, total, isLast}. Pass query to filter by substring (matches project name + key); pass maxResults to bound the response size (Atlassian default is 50, max 50 server-side). The legacy unpaginated /rest/api/3/project endpoint was retired in favour of this one and would overflow MCP tool-result limits at any non-trivial org size. |