MCP server that integrates AI agents with Jira Server 8.16.1 — search/create/update issues, manage sprints, boards, versions and workflow transitions through MCP tools.
uv sync
cp .env.example .env # then fill in JIRA_BASE_URL and, for stdio mode, credentials
The server supports two transports, controlled by MCP_TRANSPORT. They target
different use cases and authenticate differently.
stdio (default) — local, single userYour MCP client (Claude Desktop, Claude Code, etc.) spawns jira-mcp as a local
subprocess and talks to it over stdin/stdout. There's no network involved, so
this only works on the same machine as the client.
MCP_TRANSPORT=stdio
JIRA_USERNAME=you
JIRA_PASSWORD=your-password-or-pat
JIRA_USERNAME/JIRA_PASSWORD are required in this mode — the server runs
as that one Jira identity for every tool call. Run it with:
make run
streamable-http — remote, multi-userThe server runs as an HTTP service (e.g. in Docker, Kubernetes, or a Portainer
stack) and any number of MCP clients connect to it over the network at
http://<host>:8000/mcp.
There is no shared Jira credential in this mode. Every request must carry its own Jira username + password/PAT via HTTP Basic auth:
Authorization: Basic base64(jira_username:jira_password_or_pat)
The server decodes that header per request and forwards those exact
credentials to Jira, so every tool call runs with the caller's own Jira
permissions — nobody borrows anybody else's access, and nothing is shared. A
request without a valid Authorization header is rejected with 401 before
it ever reaches Jira. JIRA_USERNAME/JIRA_PASSWORD in .env are ignored in
this mode — only JIRA_BASE_URL (plus the optional JIRA_AUTH_METHOD,
LOG_LEVEL, OTEL_* settings) matters.
JIRA_AUTH_METHOD still controls how the decoded credentials are sent to
Jira: basic (default) forwards them as HTTP Basic; bearer sends the
secret half as Authorization: Bearer <token> (required by most Jira
Server/Data Center 8.14+ instances when using a PAT).
In Jira, go to your avatar → Personal Access Tokens → Create token. Use your Jira username together with that token as the Basic auth credentials above (not your account password).
Point the client at http://<host>:8000/mcp and set a custom
Authorization header (or username/password, if the client offers a Basic
auth field) to Basic base64(username:token). Example of building that
header value:
printf '%s' "your-username:your-pat" | base64
A Dockerfile and a jira-mcp service in docker-compose.yml are included,
pre-configured for streamable-http mode (MCP_TRANSPORT=streamable-http,
FASTMCP_HOST=0.0.0.0, listening on port 8000).
docker compose build jira-mcp
docker compose up -d jira-mcp
In Portainer: Stacks → Add stack, point it at this repo (or paste
docker-compose.yml), and set JIRA_BASE_URL as an environment variable on
the stack — no Jira username/password/PAT needs to live on the server, since
each caller supplies their own. The same image runs unchanged on Kubernetes;
just set JIRA_BASE_URL and MCP_TRANSPORT=streamable-http on the
container and expose port 8000.
Health endpoints (unauthenticated, for liveness/readiness probes):
GET /health/live — process is up.GET /health/ready — Jira is reachable (GET /status, no auth needed in
this mode since there's no service-level credential to check).⚠️ The MCP endpoint itself has no transport-level encryption on its own — put it behind TLS (reverse proxy / ingress) before exposing it beyond a trusted network, since Basic auth credentials travel in cleartext over plain HTTP.
jira-ops Claude Code pluginThis repo also hosts a jira-ops Claude Code plugin (.claude-plugin/marketplace.json
plugins/jira-ops/) — a skill for interacting with a running jira-mcp server
from any project, without copying files. It supports two modes:jira_* MCP tool calls.proposal.md/design.md/
tasks.md and creates/updates a Jira Epic plus one Story/Task per task,
tracking the mapping in a jira.md file inside the change directory so
re-running sync updates existing issues instead of duplicating them.To install it in another project (which must already have an MCP client
configured against a jira-mcp server — the plugin itself doesn't start or
configure one):
/plugin marketplace add if-sb/jira-mcp
/plugin install jira-ops
See plugins/jira-ops/skills/jira-ops/SKILL.md for the full behavior.
make test # unit tests
make test-integration # against a real Jira instance, see docs/integration-testing.md
make lint
make format
Traces and logs are emitted via OpenTelemetry; point OTEL_EXPORTER_OTLP_ENDPOINT
at a collector (see docker-compose.yml's otel-collector service, profile
observability).
Content type
Image
Digest
sha256:cef08904a…
Size
63.7 MB
Last updated
3 months ago
docker pull nerd4ever/jira-mcp