better-jira-mcp
better-jira-mcp
A thin MCP pass-through to the Jira and Confluence Cloud REST APIs. Built because mcp-atlassian mangles Jira descriptions: it regex-converts markdown into Jira wiki markup and posts that through REST v2, so aws_vpc_endpoint becomes aws*vpc*endpoint, {id} and a + b get eaten as macros, and **bold** comes back escaped.
This server instead parses markdown with a real CommonMark parser (markdown-it-py), emits ADF directly, and talks to Jira REST v3 and Confluence REST v2 (atlas_doc_format), which both speak ADF natively. One converter, no server-side re-interpretation, so bodies round-trip. Every write returns the object re-read so the agent verifies what landed.
Tools
Tool | Description |
| Raw |
Jira | |
| Issue with description (and optionally comments) as markdown |
| JQL search via |
| Markdown description → ADF; component names must match exactly or the call fails; returns the created issue re-read |
| Same, for updates. Refuses |
| Markdown comment → ADF |
| Workflow moves. No inline comment parameter, on purpose |
| Component names and ids for a project |
| Look up accountIds by name or email, for assignee/reporter fields |
Confluence | |
| CQL search |
| Page by id, or space key + title; body (and optionally footer comments) as markdown |
| Direct children of a page |
| Markdown → ADF page under a space (optionally under a parent) |
| Replace body and/or title; handles the version bump |
| Markdown footer comment |
Tool names are prefixed so they don't collide with other MCP servers (GitHub's search_issues, for example).
Quirks from the team guide this addresses directly:
Lossy markdown / paired
_/{}/ paired+– gone; text is text in ADF.Long descriptions break on create – gone; the body is JSON, no newline escaping.
Components fail open – names are resolved to ids against the project and unknown names are rejected with a "did you mean" hint.
Transition comments can be public – transitions don't accept a comment.
Read back what you wrote – done automatically.
Jira's own behaviour (Team field wants a bare UUID, resolution is one-way, status only moves by transition) is documented in the tool descriptions rather than papered over.
Installation
No clone needed — uvx can run it straight from GitHub:
uvx --from git+https://github.com/aviddiviner/better-jira-mcp better-jira-mcpOr, for local development:
git clone https://github.com/aviddiviner/better-jira-mcp
cd better-jira-mcp
uv syncYou'll need an Atlassian API token. One token covers Jira and Confluence on the same site.
Zed MCP configuration
Add to settings.json under "context_servers". Same env var names as mcp-atlassian, so you can copy them across; no separate Confluence variables are needed:
{
"context_servers": {
"better-jira": {
"enabled": true,
"command": "uvx",
"args": ["--from", "git+https://github.com/aviddiviner/better-jira-mcp", "better-jira-mcp"],
"env": {
"JIRA_URL": "https://your.atlassian.net",
"JIRA_USERNAME": "you@example.com",
"JIRA_API_TOKEN": "<token>"
}
}
}
}If you cloned it instead, use "command": "uv" with "args": ["run", "--project", "/path/to/better-jira-mcp", "better-jira-mcp"].
Tests
uv run pytest