·

Jira MCP With OpenCode

Set up Jira MCP in OpenCode so your AI agent can read and update issues, sprints, and boards right from your editor.

Share:

OpenCode's MCP support lives in its JSON config file, and unlike Claude Code it doesn't distinguish user/project/local scopes as cleanly — everything hangs off a single mcp block, whether that's in ~/.config/opencode/config.json for machine-wide servers or opencode.json at the repo root for project-specific ones. This topic covers wiring Jira into that config, the JQL and sprint queries that work well from OpenCode's chat interface, and a full sprint-planning example.


Installing and Connecting Jira MCP to OpenCode

Add the server under mcp in opencode.json (repo root) or ~/.config/opencode/config.json (global):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "jira": {
      "type": "local",
      "command": ["uvx", "mcp-atlassian"],
      "environment": {
        "JIRA_URL": "https://your-domain.atlassian.net",
        "JIRA_USERNAME": "you@company.com",
        "JIRA_API_TOKEN": "{env:JIRA_API_TOKEN}",
        "JIRA_PROJECTS_FILTER": "PROJ"
      },
      "enabled": true
    }
  }
}

The {env:JIRA_API_TOKEN} interpolation pulls from your shell environment at launch — same principle as Claude Code's ${VAR}, different syntax. Set the actual value in a .env file or your shell profile, never inline in the committed config.

If you'd rather run the server as a persistent process instead of spawning it per-session, use the Docker image with type: "local" and a long-running container, or point OpenCode at a remote SSE endpoint if you've deployed mcp-atlassian behind a reverse proxy for team-wide sharing:

{
  "mcp": {
    "jira": {
      "type": "remote",
      "url": "https://mcp-jira.internal.company.com/sse",
      "enabled": true
    }
  }
}

Start OpenCode and check the server connected by asking directly — there's no separate mcp list command as of the current release, so the fastest sanity check is a trivial tool call:

opencode run "Call the jira_get_agile_boards tool and list what comes back"

If the config is wrong, OpenCode reports a connection error in its startup log rather than failing silently mid-conversation, which makes debugging faster than it sounds — check the terminal output before assuming the model is the problem.

Tips
- Put the Jira server in opencode.json at the repo root, not the global config, if only one project's team needs it — keeps unrelated repos from inheriting credentials they don't need.
- Run the trivial jira_get_agile_boards sanity check immediately after adding the server — it's the fastest way to separate "config is broken" from "prompt is broken."
- {env:VAR} interpolation only works for values set in the environment OpenCode itself launches from — a variable set in a different shell session won't be visible; restart OpenCode after changing .env.


Querying and Updating Issues and Sprints from OpenCode

OpenCode's chat interface handles multi-turn Jira work reasonably well, but it's more literal about tool arguments than Claude Code — vague natural language sometimes needs a follow-up nudge with the exact JQL rather than a rephrase.

> Show me every issue in the active sprint on board 42 that's still In Progress

[tool call: jira_get_sprints_from_board(board_id=42)]
[tool call: jira_get_sprint_issues(sprint_id=118, jql="status = 'In Progress'")]

Found 6 issues in Sprint 24 still In Progress:
- PROJ-501: Fix pagination bug in export endpoint (assignee: J. Torres)
- PROJ-503: Migrate legacy auth middleware (assignee: unassigned)
...

For updates, be explicit about the transition name as it appears in your workflow — OpenCode won't infer "mark it done" maps to a transition literally named "Resolve" if your board uses that wording instead of "Done":

> Transition PROJ-503 through its next valid status and add a comment
> saying the migration was tested against staging

[tool call: jira_get_transitions(issue_key="PROJ-503")]
[tool call: jira_transition_issue(issue_key="PROJ-503", transition_id="21")]
[tool call: jira_add_comment(issue_key="PROJ-503", body="Migration tested against staging.")]

Asking it to call jira_get_transitions first, rather than guessing a transition ID, is a habit worth building into your prompts explicitly — without that instruction, OpenCode will sometimes attempt a transition ID from a previous conversation turn that no longer applies to the current issue's workflow state.

project = PROJ AND sprint in openSprints() AND status = "In Progress"
AND assignee is EMPTY

That query — in-progress work with no assignee — is a genuinely useful daily standup check, and one worth scripting as a saved prompt rather than retyping.

Tips
- Always instruct the agent to call jira_get_transitions before jira_transition_issue in your prompt — it prevents stale transition IDs from a prior turn causing a failed or wrong update.
- Use exact workflow status names ("Resolve," "In Review," "QA") rather than generic phrasing ("mark it done") — OpenCode is less forgiving than Claude Code about inferring workflow-specific terminology.
- Save recurring standup-style queries (unassigned in-progress work, stale review items) as reusable prompt snippets in your project's AGENTS.md or equivalent instruction file.


Practical Example: Sprint Planning Recommendations in OpenCode

Here's a full worked example: feeding OpenCode the backlog and last sprint's velocity, and asking for a sprint plan draft.

> Look at the PROJ backlog (project = PROJ AND status = "Backlog" ORDER BY
> Rank ASC) and the last 3 completed sprints on board 42. Calculate average
> velocity in story points, then recommend which backlog items fit into a
> sprint of that size, respecting priority order.
project = PROJ AND status = "Backlog" ORDER BY Rank ASC
[tool call: jira_search(jql="project = PROJ AND status = 'Backlog' ORDER BY Rank ASC")]
[tool call: jira_get_sprints_from_board(board_id=42)]
[tool call: jira_get_sprint_issues(sprint_id=115)]  -- sprint N-3
[tool call: jira_get_sprint_issues(sprint_id=116)]  -- sprint N-2
[tool call: jira_get_sprint_issues(sprint_id=117)]  -- sprint N-1

Average velocity over last 3 sprints: 34 story points
(Sprint 22: 31 pts, Sprint 23: 38 pts, Sprint 24: 33 pts — all completed
 without significant carryover)

Recommended Sprint 25 scope (34 pts target), by backlog rank:
1. PROJ-612 (8 pts) - Bug: checkout timeout on mobile
2. PROJ-615 (5 pts) - Add rate limiting to public API
3. PROJ-618 (13 pts) - Migrate notification service to new queue
4. PROJ-620 (5 pts) - Fix flaky integration test suite
5. PROJ-623 (3 pts) - Update dependency: requests 2.31 -> 2.32

Total: 34 pts. PROJ-625 (8 pts) is next in rank but would push to 42 pts,
above your 3-sprint average — recommend leaving it for Sprint 26 unless
the team has capacity headroom this cycle.

This is the kind of output worth reviewing line by line before you accept it — the story-point math is only as good as the estimates already in Jira, and the model has no visibility into planned PTO, on-call rotations, or a team member ramping onto a new codebase area. Treat it as a strong first draft for sprint planning, not a final commitment.

Tips
- Always ask for the underlying calculation (velocity numbers, per-sprint totals) alongside the recommendation — it lets you spot-check the math instead of trusting a bare list of ticket keys.
- Cross-reference the AI's sprint plan against known team capacity changes (PTO, on-call, onboarding) before committing — none of that is visible to the model from Jira data alone.
- Rank backlog items in Jira correctly before running this kind of query — ORDER BY Rank ASC reflects your board's actual backlog order only if someone has kept it groomed.


Known Limitations for Jira MCP in OpenCode

A few things to know going in, so you don't burn an afternoon debugging what's actually a platform limitation:

  • No built-in MCP server listing command. Unlike Claude Code's claude mcp list, OpenCode as of the current release doesn't expose a first-class command to inspect connected servers and their tool inventories from the CLI — you confirm connectivity indirectly, by making a tool call and watching the result.
  • Team-managed board sprint tools. Same underlying mcp-atlassian limitation as everywhere else: jira_create_sprint and jira_update_sprint don't reliably work against team-managed (next-gen) Scrum boards. This isn't OpenCode-specific, but it surfaces the same way — a write that silently fails or errors ambiguously.
  • Less forgiving natural language for workflow actions. OpenCode's tool-calling tends to be more literal than Claude Code's about mapping phrases like "close it out" to actual transition names — you'll get better results being explicit about the exact status name from your workflow.
  • No native diffing of Jira issue changes. If you ask OpenCode to update multiple fields on an issue, it won't show you a before/after diff the way it might show a code diff — you're relying on the tool call arguments printed in the conversation to know exactly what changed.

Tips
- Confirm connectivity with a real tool call rather than assuming a clean startup log means the Jira server is reachable — the two aren't always the same thing.
- Before promising sprint automation on a client's board, check whether it's company-managed or team-managed; the setting is under board settings and determines whether sprint-mutation tools will work at all.
- When updating multiple fields at once, ask the agent to state clearly what values it's changing to, in plain text, before the tool call — it's your substitute for a diff view.


Tips

OpenCode is a solid, lightweight client for Jira MCP once you learn to be explicit — it rewards precise JQL and exact workflow terminology more than it rewards conversational phrasing, and that trade-off is worth it for the transparency you get into each tool call.

Tips
- Keep your Jira MCP config at the project (opencode.json) level unless multiple unrelated repos genuinely need the same server.
- Front-load exact JQL and exact transition/status names in prompts — OpenCode performs noticeably better with explicit input than with inferred intent.
- Sanity-check sprint-planning or bulk-update output against real team constraints before treating it as final — the model only knows what's in Jira, not what's in your team's calendar.

Share: