jira-mcp

jira-mcp

An MCP server for Jira Data Center that enables searching, analyzing, and managing Jira through its REST API, with permission policy, preview-before-change, audit trail, and reporting tools.

Category
访问服务器

README

jira-mcp

CI Python 3.10+ MCP License: MIT

An MCP server for Jira Data Center. Lets Claude Desktop, Claude Code, or any MCP-compatible client search, analyse and manage Jira through its official REST API — with a permission policy, a preview step, and an audit trail in front of every change.

فارسی · 83 tools · 6 prompts · 6 skills · 579 tests

You:    Is the current sprint going to make it?
Claude: Sprint 14 is at risk. 18 of 24 issues done (32/45 points) with 3 days
        left, but two issues have been blocked for six days. At the current
        rate it projects to 84% completion.

You:    Close it, then
Claude: PREVIEW (nothing changed): would close Sprint 14; 6 issues are not
        done and will be moved out: OPS-14, OPS-22, OPS-31...

Why this exists

Jira's REST API answers questions like "what issues are in sprint 87". People ask questions like "is the sprint going to make it?". This server closes that gap, and tries hard not to lie while doing it:

  • Missing data is reported, not zeroed. No Story Points field configured? The report says "unavailable" rather than showing 0.0, which would read as the team completed nothing.
  • Every number carries its definition. "Velocity" means different things at different companies, so each response says how it was computed — Report.explain_metrics gives the full rule and its caveat.
  • Heuristics name their evidence. Jira has no native "blocked" concept, so detection checks three signals and always reports which one matched. A team that records blockers in comments legitimately shows zero, and is told so.
  • Destructive changes preview first, reading real state rather than restating your request.

Status

Complete and in use. Version 1.0.0 — see the changelog.

Design principles

Principle What it means here
REST API only No direct database access, ever. Upgrade-safe by construction.
Domain tools Tools are named Issue.search, not GET /rest/api/2/search.
One response shape Every tool returns success / message / data / warnings / next_actions / meta.
Permission guard Each tool declares read / write / admin; policy decides what is even visible.
Preview before change Destructive and bulk tools return a dry-run first; the real change needs confirm=true.
Multi-instance Production, staging and dev switch by config, not by code.
Audited Every write is appended to a JSON Lines audit log with secrets redacted.
Tested Every tool has unit tests against a mocked Jira — no live server needed.

Quick start

You need Python 3.10+ and a Jira Data Center Personal Access Token (Jira 8.14+).

git clone https://github.com/Mr-pixle/jira-mcp
cd jira-mcp
uv venv && uv pip install -e ".[dev]"

cp .env.example .env                              # set JIRA_PROD_PAT
cp config/instances.yaml.example config/instances.yaml
$EDITOR config/instances.yaml                     # set your Jira base_url

uv run jira-mcp --check    # validates config and credentials, contacts nothing

Then run it — or let your client run it for you:

uv run jira-mcp                                # stdio, for a local client
uv run jira-mcp --transport http --port 8000   # HTTP, for a shared server

.env and config/instances.yaml are git-ignored. The first holds your token, the second your internal hostname.

Connect Claude Desktop / Claude Code (stdio)

{
  "mcpServers": {
    "jira": {
      "command": "uv",
      "args": ["run", "--directory", "/opt/jira-mcp", "jira-mcp"],
      "env": { "JIRA_PROD_PAT": "your-token-here" }
    }
  }
}

Then ask: "Check the Jira connection" → the client calls jira_system_health.

Available tools

83 tools — 57 read, 26 write. Full details in docs/Tool-Reference.md (generated from the registry).

Domain Read Write
System health, whoami, list_instances, list_tools
Issues search (JQL), get, get_transitions, get_changelog, get_link_types create, update, transition, assign, link
Fields list — find custom field IDs like Story Points
Projects list, get, get_components, get_versions, get_issue_types create_version, release_version
Users search, get, find_assignable
Boards list, get, get_configuration, get_backlog, get_epics
Sprints list, get, get_issues create, start, close, move_issues, move_to_backlog
Comments list add, update, delete
Worklogs list add, update, delete
Attachments list, get_text upload, delete
Filters list_favourites, get, run
Dashboards list, get
Bulk transition, assign, comment, update_labels, update_field, move_to_sprint
Reports sprint_health, velocity, blocked_issues, overdue_issues, workload_balance, release_readiness, team_performance, executive_summary, explain_metrics
eazyBI health, export_report, get_export_url, generate_report_definition, explain_report, plus 8 experimental metadata tools

Regenerate the reference after adding tools:

uv run jira-mcp --generate-docs   # writes docs/Tool-Reference.md

Things you can ask for today

Which issues in OPS have been in progress for more than five days? Show me the current sprint on the platform board and how it's tracking. Create a bug in OPS about the Safari login failure and assign it to Ali. Move OPS-123 to Done with resolution Fixed and log 3 hours against it. Close Sprint 14 — but tell me what's unfinished first. What does the error log attached to OPS-123 say? Is the current sprint going to make it, and why not? What's our velocity over the last six sprints — improving or declining? Give me a status roll-up across OPS, MOB and WEB. Is the work spread fairly this sprint? How exactly do you calculate velocity?

Preview before change

Destructive and high-impact tools return a preview on the first call and change nothing. The preview shows real before/after values read from Jira, not a restatement of the request:

You:    Close sprint 14
Claude: [calls jira_sprint_close]
        PREVIEW (nothing changed): would close sprint 'Sprint 14' (id=87);
        3 issues are not done and will be moved out: OPS-2, OPS-3, OPS-7
You:    Go ahead
Claude: [calls jira_sprint_close with confirm=true]
        Closed sprint 'Sprint 14'.

Which tools preview is a policy decision in config/permissions.yaml, not a property of the tool — routine single-issue edits run in one step by default, while Sprint.close, Sprint.start, *.delete and all bulk operations preview. The audit log records previews and real changes separately.

Bulk operations

Jira Data Center exposes no REST API for bulk edits, so Bulk.* means N individual requests. Three things follow from that, and the engine handles all three:

Blast radius. Issues are selected by explicit keys or by JQL. A JQL matching more than max_issues (default 50, ceiling 200) is refused outright rather than truncated — a half-applied bulk change is worse than none.

Partial failure is normal. Ten issues succeed, one is in a status the transition does not allow, one is in a project the account cannot write to. Every result reports succeeded_keys and a failed list with per-issue reasons, and next_actions hands back the exact retry call:

Bulk.transition: 8 succeeded, 2 failed (OPS-14, OPS-22).
→ To retry only those, call Bulk.transition again with
  issue_keys=['OPS-14', 'OPS-22']

Set stop_on_error=true when the issues must all change together — the run then goes sequentially and halts at the first failure, leaving the rest untouched.

Notifications. Single-issue edits notify watchers. Bulk edits default to notify_users=false: relabelling 80 issues should not send 80 emails. Bulk.comment is the exception — Jira always notifies on a new comment, and the preview says so.

Requests run five at a time: fast enough for 100 issues, polite enough to stay clear of Jira's rate limiter.

Reports and the semantic layer

The report tools answer questions people ask — "is the sprint going to make it?" — rather than questions the API answers. Three ideas make that work.

Custom fields are discovered, not configured. "Story Points" is customfield_10004 on one Jira and customfield_10026 on another. The resolver prefers the board's own estimation field — the field the team's velocity chart already uses, so the report agrees with what they see in Jira — and falls back to matching the field catalogue by name.

Missing data is reported, not zeroed. If no estimation field exists, points-based sections say "unavailable" instead of showing 0.0, which would read as the team completed nothing. Report.velocity refuses outright and points you at the count-based alternative.

Every number carries its definition. "Velocity" and "blocked" mean different things at different companies, so each response includes a methodology block, and Report.explain_metrics returns the full rule and its caveat — in English or Persian:

You:    ولاسیتی رو چطور حساب می‌کنی؟
Claude: [jira_report_explain_metrics term="velocity"]
        Computed as: for each closed sprint, the sum of the estimation field on
        issues whose status category is 'done' at the time of reading...
        Caveat: counts points as they stand now, not as at sprint close.

Jira has no native "blocked" concept, so Report.blocked_issues checks three signals — the Flagged field, the status name, then labels — and always reports which one matched. A team that records blockers only in comments will legitimately show zero, and the response says so rather than implying nothing is stuck.

Each report documents its API cost in its description, since several make one request per issue.

eazyBI

What eazyBI actually offers. It publishes exactly one supported REST endpoint — running a saved report. Its support team has stated publicly that there is no REST API for creating or publishing reports and dashboards, on any deployment. The tools here are shaped around that reality rather than around what would be convenient.

Layer Tools Reliability
Stable export_report, get_export_url The documented endpoint
Experimental list_accounts, list_reports, get_report_definition, list_dashboards, get_dashboard, list_cubes, list_dimensions, list_measures Internal UI routes — usually work on Data Center, degrade to supported: false where they do not
Local generate_report_definition, explain_report No eazyBI call at all

Start with EazyBI.health. It probes what works on your installation and reports it: whether the add-on responds at {jira}/plugins/servlet/eazybi, which credential it accepts, whether the metadata routes are open, and — the part you need before anything else — what account IDs exist.

Credentials are reused, not duplicated. The add-on sits behind Jira's own auth, so the Jira PAT is tried first. eazyBI's docs specify Basic auth, so a PAT may be rejected; the client then falls back to separate credentials if you have configured them, and remembers which one worked. Nothing to set up in the happy case.

Creating reports is a two-step process, honestly. Since eazyBI has no API for it, generate_report_definition designs the report and produces the JSON document you paste into eazyBI's Import report definition dialog. Five templates cover the common shapes. Member names are instance-specific, so reading a similar report first with get_report_definition turns a plausible definition into a valid one.

On 401/403 from an internal route, the error says what it cannot know: the route may be closed to API callers, or the credentials may be wrong, and the response cannot distinguish them. It then names the experiment that resolves it — run export_report with a known ID.

Context management

Jira responses are large — a single issue can be 30 KB of JSON. Two mechanisms keep results usable:

  • detailcompact (default) returns the triage fields; full adds description, components, links and time tracking.
  • Page size capsmax_results is capped at 100 with a default of 25, and the requested fields are trimmed at the Jira end rather than after the fact.

Prompts and skills

Prompts appear in the client's menu as ready-made requests: sprint_report, executive_report, risk_report, release_report, workload_report, team_performance.

Skills (skills/) are multi-step workflows with decision points — the difference being that a prompt has a known answer shape, while a skill's next step depends on what the last one found:

Skill Writes?
sprint-review — classify unfinished work, propose decisions Only if asked
weekly-status — a status update for a manager No
triage-backlog — fill in missing assignee, priority, estimate Behind a preview
stale-work-cleanup — find and clear work that stopped moving Behind a preview
release-checklist — readiness, notes, version closeout Behind a preview
onboard-project — map an unfamiliar project's conventions No

Deployment

sudo ./deploy/install.sh    # systemd service, hardened, loopback-bound

Then TLS via deploy/nginx.conf. Full instructions in the Deployment Guide.

Development

uv run pytest                          # 579 tests, mocked Jira, offline
uv run pytest --live                   # also run tests marked 'live'
uv run python tests/integration/acceptance.py   # every capability over real MCP
uv run ruff check .                    # lint
uv run mypy src                        # type check
uv run jira-mcp --generate-docs        # regenerate the tool reference

Security notes

  • Secrets live only in environment variables; instances.yaml stores variable names.
  • HTTP transport binds to 127.0.0.1 by default. Set JIRA_MCP_HTTP_TOKEN and put a TLS-terminating reverse proxy in front of it before exposing it to a network.
  • Use a dedicated Jira service account with the minimum permissions it needs — not an admin.
  • logs/ and .env are git-ignored. Never commit them.

Documentation

Document Language
Architecture English
Configuration Guide English
Deployment Guide English
Tool Reference English (generated)
Skills English
SECURITY — threat model and credential handling English
CONTRIBUTING English
CHANGELOG English
README فارسی فارسی
راهنمای نصب و راه‌اندازی فارسی
راهنمای پیکربندی فارسی
راهنمای استفاده فارسی

Acknowledgements

Design informed by three prior projects: ultimate-guitar/eazybi-mcp, whose research into eazyBI's API surface shaped this project's eazyBI domain entirely; atlassian/atlassian-mcp-server, whose practice of shipping skills alongside an MCP server is adopted here; and edrich13/mcp-jira-server.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选