A small, read-only Model Context Protocol server that exposes a JIRA Data Center / Server (or Cloud) instance to MCP clients such as Claude Code, Cursor, and Open WebUI.
It is stateless — no database, no volumes. It connects out to your JIRA over the REST API and serves over Streamable HTTP at http://<host>:8002/mcp. Every tool is read-only; the server never writes to JIRA.
13 tools across five areas:
Issues
search_issues— search by JQL (weekly summaries, per-person reports, blocked issues, …)get_issue_detail— full issue: description, comments, subtasks, links, changelogget_change_request— a full change request: standard fields plus the custom "Details" panel and attachment metadatasearch_change_requests— list/search change requests in a project, newest first
Worklogs
get_issue_worklogs— all worklogs for one issue (with comments)get_worklogs_updated_since— bulk-fetch worklogs across all projects for the last N days
Sprints
get_active_sprint— the active sprint for a boardget_sprint_issues— all issues in a sprintget_board_sprints— list sprints for a board by state
Users & Groups
get_group_members— members of a JIRA groupfind_user— resolve a name/email to a JIRA accountId
Projects & Metadata
list_projects— projects the token can seeget_project_statuses— valid status names for a project
Copy .env.example to .env and fill in your values:
JIRA_URL=https://jira.example.com # or https://your-domain.atlassian.net for Cloud
JIRA_TOKEN=your-read-only-personal-access-token
JIRA_USERNAME= # leave empty for DC PAT; set for Cloud basic_auth
JIRA_VERIFY_SSL=false # false for internal self-signed certs- JIRA Data Center / Server (8.14+): create a read-only Personal Access Token, put it in
JIRA_TOKEN, and leaveJIRA_USERNAMEempty (Bearer auth). - JIRA Cloud: set
JIRA_USERNAMEto your email andJIRA_TOKENto an API token (basic auth).
The .env file is gitignored — never commit real credentials.
docker compose build
docker compose up -d
docker compose logs -fThe server listens on :8002 (override with JIRA_MCP_PORT). MCP endpoint: http://<host>:8002/mcp.
pip install -r requirements.txt # or: uv sync
python main.py --check # verify JIRA connectivity, then exit
python server.py # serve MCP on :8002python main.py --check runs a connectivity preflight against /rest/api/2/serverInfo and prints the real HTTP status / body on failure — handy for distinguishing a bad token from a wrong URL before the server starts.
Claude Code:
claude mcp add --transport http jira http://<host>:8002/mcpPoint any other Streamable-HTTP MCP client at the same URL.
main.py doubles as a small CLI for ad-hoc queries:
python main.py --check # connectivity preflight
python main.py "alice" --field assignee # issues assigned to a user
python main.py --worklogs --person you@example.com \
--from-date 2026-06-01 --to-date 2026-06-10 # worklogs for a person
python main.py --worklogs --group engineering --per-person # per-person totalspytest -qThe suite is fully mock-driven — no live JIRA connection required.
- All tools are read-only; the server never writes to JIRA.
get_change_requestreturns attachment metadata only (no bytes).- Behind a corporate firewall, build with an internal PyPI mirror:
docker compose build --build-arg PIP_INDEX_URL=https://pypi.example.com/simple
MIT — see LICENSE.