Jira Cloud MCP server: every REST operation as a tool, from Atlassian OpenAPI specs
210
A Model Context Protocol server that exposes every operation of the Jira Cloud platform REST API v3, the Jira Software (agile) API and the Jira Service Management API as a tool — 809 operations, generated at start-up from Atlassian's own OpenAPI specifications, so there is no hand-maintained tool list to fall behind. TypeScript, stdio and Streamable HTTP transports, API-token or OAuth 2.0 authentication, operator policy (read-only, method deny-list, tool filters), and a self-contained Docker image with the docs, examples, test harness, mock Jira and test-suite baked in for air-gapped sites.
docker run --rm -i -e JIRA_BASE_URL=https://acme.atlassian.net -e [email protected] -e JIRA_API_TOKEN=... n8500x/mcp-jira
| Operations → tools | 629 platform + 105 software + 75 service management = 809, plus 4 discovery tools |
| Tool names | jira_get_issue, jira_agile_get_all_sprints, jira_jsm_create_customer_request (snake_case operationId, prefixed per API) |
| Modes | full (everything, ~1.5 MB tools/list), compact (~70 essentials + discovery), meta (discovery only) — every operation stays reachable through jira_call_operation |
| Policy | JIRA_READ_ONLY, JIRA_DENY_METHODS, include/exclude globs, tag and API-set filters |
| Auth | email + API token (basic), or OAuth 2.0 bearer via api.atlassian.com |
| Transports | stdio (desktop hosts) and stateless Streamable HTTP (/mcp, /healthz, /docs) |
| Image | n8500x/mcp-jira — node:22-alpine, non-root uid 1001/gid 0 (OpenShift-ready), tini, ~self-contained |
1. Credentials. Create an API token at https://id.atlassian.com/manage-profile/security/api-tokens (ideally for a dedicated service account) — see docs/AUTH.md for OAuth 2.0 and the Atlassian Enterprise / Guard policy notes.
2. Check it works.
docker run --rm -e JIRA_BASE_URL=https://acme.atlassian.net -e [email protected] -e JIRA_API_TOKEN=atatt_... \
n8500x/mcp-jira doctor
doctor reports the configuration, the spec/tool counts, Jira reachability, who you are, your
effective permissions, and whether Jira Software / Service Management exist on the site.
3. Plug into an MCP host (stdio). Claude Desktop / Claude Code / Cursor / any stdio host:
{
"mcpServers": {
"jira": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"JIRA_BASE_URL",
"-e",
"JIRA_EMAIL",
"-e",
"JIRA_API_TOKEN",
"n8500x/mcp-jira"
],
"env": {
"JIRA_BASE_URL": "https://acme.atlassian.net",
"JIRA_EMAIL": "[email protected]",
"JIRA_API_TOKEN": "atatt_..."
}
}
}
}
Ready-made files: examples/claude_desktop_config.json,
examples/claude-code.mcp.json. Hosts that struggle with 800+
tools: add -e JIRA_TOOL_MODE=compact.
4. Or run it as a shared service (HTTP).
cp examples/env.example .env # fill in the site + credentials, set MCP_HTTP_BEARER_TOKEN
docker compose up -d # Streamable HTTP on :3000 — /mcp, /healthz, /docs
MCP_URL=http://localhost:3000 MCP_TOKEN=... examples/curl-http.sh
Kubernetes/OpenShift manifests: examples/k8s.
Tool names are the spec operationId in snake_case with a prefix per API set; arguments use
Jira's own parameter names, the JSON request body goes under body, uploads under files:
jira_get_issue { "issueIdOrKey": "PLAT-123", "fields": ["summary","status"] }
jira_create_issue { "body": { "fields": { "project": {"key":"PLAT"}, "issuetype": {"name":"Task"}, "summary": "…" } } }
jira_do_transition { "issueIdOrKey": "PLAT-123", "body": { "transition": { "id": "31" } } }
jira_add_attachment { "issueIdOrKey": "PLAT-123", "files": [ { "filename": "a.csv", "contentBase64": "…" } ] }
jira_agile_get_issues_for_sprint { "sprintId": 345, "fields": ["summary"] }
jira_jsm_get_customer_requests { "serviceDeskId": "3", "requestStatus": "OPEN_REQUESTS" }
Each tool description carries the HTTP method and path, Atlassian's summary, the OAuth scopes it
needs, [DEPRECATED]/experimental flags and a link to the Atlassian docs page. Results are the
raw Jira JSON (also as structuredContent.data), truncated above a size cap with a visible notice;
errors return the HTTP status, Jira's own messages and a hint (401 → token expired?, 403 → missing
scope X, 404 → no permission, 410 → endpoint removed, …).
Full catalogue: docs/TOOLS.md. Worked examples (JQL, ADF comments, transitions, sprints, JSM, pagination): docs/RECIPES.md.
| Tool | Does |
|---|---|
jira_list_operations | Search all 809 operations by keyword / tag / method / API; shows which are registered |
jira_describe_operation | Every parameter and the deep request-body schema, scopes, docs link — for one operation |
jira_call_operation | Run any operation by tool name or operationId, registered or not |
jira_request | Raw request to any /rest/ path (endpoints newer than the specs) |
So a server configured with 12 tools can still do everything; the model finds and reads the schema of what it needs, then calls it. Hard policy applies to every route.
| Variable | Default | Effect |
|---|---|---|
JIRA_API_SETS | platform,software,servicedesk | Which specs to load (drop servicedesk on sites without JSM) |
JIRA_TOOL_MODE | full | full = all operations; compact = ~70 everyday operations; meta = discovery tools only |
JIRA_TOOL_INCLUDE / JIRA_TOOL_EXCLUDE | — | Comma-separated globs on tool names, e.g. jira_get_*,jira_agile_* |
JIRA_TOOL_TAGS | — | Only operations in these spec groups, e.g. Issues,Issue search,Projects |
JIRA_INCLUDE_DEPRECATED / JIRA_INCLUDE_EXPERIMENTAL | true | Hide what Atlassian flags as deprecated / experimental |
JIRA_READ_ONLY | false | Hard policy: only GET operations run, by any route |
JIRA_DENY_METHODS | — | Hard policy: e.g. DELETE or DELETE,PUT |
JIRA_RAW_TOOL / JIRA_META_TOOLS | true | Turn off jira_request / the discovery tools |
Filters decide what is advertised; JIRA_READ_ONLY and JIRA_DENY_METHODS decide what may
run — including through jira_call_operation and jira_request. Full reference and every
other setting (timeouts, retries, result cap, TLS/proxy, HTTP options, logging):
docs/OPERATIONS.md.
docker run --rm [-i] <env> n8500x/mcp-jira serve (stdio) | ... serve --http (Streamable HTTP)
docker run --rm n8500x/mcp-jira tools [filter] [--all] list registered tools / every operation (no Jira needed)
docker run --rm n8500x/mcp-jira describe jira_edit_issue parameters, body schema, scopes, docs (no Jira needed)
docker run --rm <env> n8500x/mcp-jira call jira_get_issue issueIdOrKey=PLAT-1 'fields=["summary"]'
docker run --rm <env> n8500x/mcp-jira doctor connectivity + auth + permissions report
docker run --rm <env> n8500x/mcp-jira harness scenario /usr/share/mcp-jira/examples/scenarios/smoke.json
docker run --rm n8500x/mcp-jira mock bundled fake Jira for tests (MOCK_HOST/MOCK_PORT)
docker run --rm n8500x/mcp-jira selftest the vitest suite, offline
docker run --rm n8500x/mcp-jira docs [file] | examples | export [dir] | readme | compose | spec
GET /docs on a running HTTP instance serves the same README, docs/ and examples/.
Jira Cloud is evergreen — every tenant runs the same build — so there is nothing to pin. What
matters is the REST API version (platform v3; v2 is legacy) and Atlassian's deprecations:
the vendored specs flag 37 operations, notably the classic GET/POST /rest/api/3/search
(replaced by /search/jql with token pagination) and GET /rest/api/3/project. They are exposed
as [DEPRECATED] tools until JIRA_INCLUDE_DEPRECATED=false. Spec provenance and refresh
procedure: spec/README.md; JIRA_SPEC_DIR can point at newer spec files at run
time without a rebuild.
npm ci && npm run build && npm test # ~70 tests, offline, against the bundled mock Jira
npm run lint && npm run docs:check # eslint (type-aware) + generated TOOLS.md is current
npm run mock # fake Jira on :18080, then: JIRA_BASE_URL=http://127.0.0.1:18080 ... npm run doctor
npm run harness -- tools issue # generic MCP harness: tools | describe | call | scenario | doctor | repl
.\build.ps1 # docker build (tests run in the builder stage) + smoke; .\build.ps1 -Push -Overview to publish
.\test.ps1 # end-to-end against the image: doctor, call, scenarios, HTTP mode, /docs, selftest
Design and layout: docs/ARCHITECTURE.md. Contributing and spec refresh: docs/DEVELOPMENT.md. Layout:
packages/jira @n8500x/mcp-jira server, CLI, mock Jira packages/harness @n8500x/mcp-harness generic MCP client CLI
spec/ vendored Atlassian OpenAPI documents docs/ examples/ baked into the image under /usr/share/mcp-jira
MIT licence for this code; the OpenAPI documents remain Atlassian's and are redistributed unmodified for build reproducibility.
Content type
Image
Digest
sha256:dac9c6fbd…
Size
111.7 MB
Last updated
29 days ago
docker pull n8500x/mcp-jira