Tracking Jira
Discovery
What discovery provides:
resources: List of accessible Atlassian sites withcloudId,url,namecurrentUser: YouraccountId,name, andemail(for JQL queries likeassignee = currentUser())projects: Available projects withkey,name,projectTypeKey, andissueTypes(id, name, subtask); includesunassignedCount(projects without a lead)hints: API limits (maxResults: 50) and pagination requirements
Why run discovery:
- Get
cloudIdrequired for all Jira API calls - Know available projects and their issue types before creating issues
- Get your
accountIdfor assignment operations - Understand pagination needs (if
total > maxProjects)
Tools
Issues: getJiraIssue(cloudId, issueIdOrKey), createJiraIssue(cloudId, projectKey, issueTypeName, summary, ...), editJiraIssue(cloudId, issueIdOrKey, fields), searchJiraIssuesUsingJql(cloudId, jql, maxResults?, startAt?)
Operations: addCommentToJiraIssue(cloudId, issueIdOrKey, commentBody), transitionJiraIssue(cloudId, issueIdOrKey, transition), addWorklogToJiraIssue(cloudId, issueIdOrKey, timeSpent)
Metadata: getTransitionsForJiraIssue(cloudId, issueIdOrKey), getJiraIssueRemoteIssueLinks(cloudId, issueIdOrKey)
Projects: getVisibleJiraProjects(cloudId, searchString?, maxResults?, startAt?), getJiraProjectIssueTypesMetadata(cloudId, projectIdOrKey), getJiraIssueTypeMetaWithFields(cloudId, projectIdOrKey, issueTypeId)
Users: lookupJiraAccountId(cloudId, searchString), atlassianUserInfo()
Discovery: getAccessibleAtlassianResources()
Quick Patterns
Create issue:
const metadata = await getJiraProjectIssueTypesMetadata({ cloudId, projectIdOrKey: 'PROJ' });
const result = await createJiraIssue({ cloudId, projectKey: 'PROJ', issueTypeName: 'Task', summary: 'Title' });
const url = `${siteUrl}/browse/${result.key}`;
Search issues:
const response = await searchJiraIssuesUsingJql({ cloudId, jql: 'project = PROJ AND status = "In Progress"', maxResults: 50 });
const issues = response.issues; // JiraSearchResult: { issues, total, startAt, maxResults }
Transition issue:
const { transitions } = await getTransitionsForJiraIssue({ cloudId, issueIdOrKey: 'PROJ-123' });
await transitionJiraIssue({ cloudId, issueIdOrKey: 'PROJ-123', transition: { id: transitions[0].id } });
Lookup user and assign issue:
const result = await lookupJiraAccountId({ cloudId, searchString: 'john.doe@example.com' });
const users = result.users.users; // Note: nested structure - result.users.users, not result.users
const accountId = users[0]?.accountId;
await editJiraIssue({ cloudId, issueIdOrKey: 'PROJ-123', fields: { assignee: { accountId } } });
Workflows
Create issue: getJiraProjectIssueTypesMetadata({cloudId, projectIdOrKey}) → createJiraIssue({cloudId, projectKey, issueTypeName, summary}) → return ${siteUrl}/browse/${result.key}
Find my issues: searchJiraIssuesUsingJql({cloudId, jql: 'assignee = currentUser() AND status != Done'})
Transition issue: getTransitionsForJiraIssue({cloudId, issueIdOrKey}) → find target ID → transitionJiraIssue({cloudId, issueIdOrKey, transition: {id}})
JQL Reference
Operators: =, !=, >, <, >=, <=, IN, NOT IN, ~ (contains), IS EMPTY, IS NOT EMPTY
Functions: currentUser(), openSprints(), membersOf("group"), startOfWeek(), endOfMonth()
Time: created >= -7d, updated >= startOfWeek(), duedate <= endOfMonth()
Examples: status = "In Progress", status IN ("To Do", "In Progress"), summary ~ "bug", assignee IS EMPTY, sprint in openSprints()
JQL Best Practices
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
returned unexpected response: null |
OAuth token expired | Re-authenticate |
JQL parse error |
Reserved word project key | Quote the key |
Field 'X' does not exist |
Invalid JQL field | Use standard fields |
UNAUTHENTICATED |
Token expired mid-session | Re-run discovery |
Issue does not exist |
Wrong cloudId or key typo | Verify cloudId from discovery |
| Discovery returns 0 projects | Missing OAuth scopes | Ensure read:jira-work granted |
Connection Resilience
- Always use
cloudIdfrom discovery output, never hardcode - If discovery fails with auth errors, re-authenticate the Atlassian connection and re-run discovery
- For multi-site workspaces, discovery returns all accessible sites in
resources[]— pick the correctcloudIdfor the target site
Output Format
Present results as a structured report:
Tracking Jira Report
════════════════════
Resources discovered: [count]
Resource Status Key Metric Issues
──────────────────────────────────────────────
[name] [ok/warn] [value] [findings]
Summary: [total] resources | [ok] healthy | [warn] warnings | [crit] critical
Action Items: [list of prioritized findings]
Target ≤50 lines of output. Use tables for multi-resource comparisons.
Anti-Hallucination Rules
- NEVER assume resource names — always discover via CLI/API in Phase 1 before referencing in Phase 2.
- NEVER fabricate metric names or dimensions — verify against the service documentation or
--helpoutput. - NEVER mix CLI commands between service versions — confirm which version/API you are targeting.
- ALWAYS use the discovery → verify → analyze chain — every resource referenced must have been discovered first.
- ALWAYS handle empty results gracefully — an empty response is valid data, not an error to retry.
Counter-Rationalizations
| Shortcut | Counter | Why |
|---|---|---|
| "I'll skip discovery and check known resources" | Always run Phase 1 discovery first | Resource names change, new resources appear — assumed names cause errors |
| "The user only asked for a quick check" | Follow the full discovery → analysis flow | Quick checks miss critical issues; structured analysis catches silent failures |
| "Default configuration is probably fine" | Audit configuration explicitly | Defaults often leave logging, security, and optimization features disabled |
| "Metrics aren't needed for this" | Always check relevant metrics when available | API/CLI responses show current state; metrics reveal trends and intermittent issues |
| "I don't have access to that" | Try the command and report the actual error | Assumed permission failures prevent useful investigation; actual errors are informative |