jira-confluence-mcp
# Jira + Confluence MCP
A single MCP server that gives the Rapid7 SI Triage agent read/write access to
**Jira Cloud** (tickets, attachments, comments, search) and **Confluence Cloud**
(the historical knowledge base of runbooks and postmortems). Combining both
Atlassian products in one server is natural: they share the same auth and host,
and the triage workflow uses them together.
A key side effect lives here: when the agent fetches a ticket, this server
**auto-downloads log-like attachments** into a shared directory that the
companion **Log Intelligence MCP** then ingests.
---
## Tools
### Jira
| Tool | Purpose |
|------|---------|
| `get_ticket(ticket_id, download_logs?)` | Fetch + normalise a ticket (summary, description, comments, attachments, product/components, environment). Auto-downloads log attachments unless `download_logs=false`. |
| `get_attachment(ticket_id, attachment_id)` | Download a specific attachment by id into the ticket's log dir. |
| `search_tickets(jql, max_results=25)` | JQL search — used to find similar historical defects. |
| `post_comment(ticket_id, body)` | Post a comment (write; guarded). |
| `update_ticket_field(ticket_id, field, value)` | Update one field (write; guarded). |
### Confluence
| Tool | Purpose |
|------|---------|
| `search_confluence(query, max_results=10, cql?)` | CQL/text search of the KB. Returns ranked, normalised results (title, url, excerpt, relevance) — **the same shape as Jira search** so the agent handles both uniformly. |
| `get_page(page_id)` | Fetch a page as clean plain text (storage-format markup stripped) + metadata. Cached. |
| `get_child_pages(page_id)` | List direct child pages (walk a runbook space). |
---
## Auth & configuration
Atlassian Cloud uses **HTTP Basic auth with `email:api_token`** (base64). Secrets
come from the environment only — never hardcoded. Copy `.env.example` to `.env`:
```
ATLASSIAN_BASE_URL=https://asgspratapsingh.atlassian.net
ATLASSIAN_EMAIL=asgspratapsingh@gmail.com
ATLASSIAN_API_TOKEN=<create at id.atlassian.com/manage-profile/security/api-tokens>
SI_DATA_DIR=./si_data
```
`ATLASSIAN_BASE_URL` may be any URL from your site — it's normalised to the site
origin automatically (e.g. `…atlassian.net/jira/for-you?tab=x` →
`https://…atlassian.net`).
**Write safety.** `DRY_RUN=1` refuses all writes (read-only). `ALLOW_WRITES=0`
refuses writes even when not in dry-run. Both `post_comment` and
`update_ticket_field` respect these guards.
**Attachment download.** `AUTO_DOWNLOAD_LOGS=1` (default) downloads attachments
whose name ends in `LOG_ATTACHMENT_SUFFIXES` (`.log,.txt,.gz,.out,.err`) or that
are `text/plain`, up to `MAX_ATTACHMENT_MB` (50). Files land in
`SI_DATA_DIR/logs/<ticket_id>/`.
The HTTP client retries `429`/`5xx` with exponential backoff (honouring
`Retry-After`), controlled by `HTTP_MAX_RETRIES` and `HTTP_TIMEOUT`.
---
## Install & run
```bash
cd jira-confluence-mcp
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e . # installs mcp, httpx, uvicorn
cp .env.example .env # fill in ATLASSIAN_API_TOKEN
# stdio:
python -m jira_confluence_mcp --transport stdio
# HTTP (streamable-http at http://127.0.0.1:8080/mcp):
python -m jira_confluence_mcp --transport http
```
> This server is one of four processes in the SI Triage POC (this + the Log
> Intelligence and Historical KB MCPs + the orchestrator). For the full
> multi-service manual startup sequence, `.env` layout across all four repos,
> and end-to-end test steps, see **`orchestrator-agent/si-triage-automation/README.md`
> → "Running the full system manually"**.
### Register with an MCP client (stdio example)
```json
{
"mcpServers": {
"jira-confluence": {
"command": "python",
"args": ["-m", "jira_confluence_mcp", "--transport", "stdio"],
"env": {
"ATLASSIAN_BASE_URL": "https://asgspratapsingh.atlassian.net",
"ATLASSIAN_EMAIL": "asgspratapsingh@gmail.com",
"ATLASSIAN_API_TOKEN": "…",
"SI_DATA_DIR": "/absolute/path/to/si_data"
}
}
}
}
```
---
## How it coordinates with the Log Intelligence MCP
Set `SI_DATA_DIR` to the **same absolute path** for both servers.
```
si_data/
logs/<ticket_id>/… # THIS server writes downloaded attachments here
# the Log Intelligence MCP reads + indexes them
```
Flow: `get_ticket(EA-123)` here → files appear in `logs/EA-123/` →
`ingest_ticket_logs("EA-123")` on the Log MCP → agent queries logs →
`delete_ticket_logs("EA-123")` cleans up.
---
## Ports
This server's HTTP transport defaults to **8080**; the Log Intelligence MCP uses
**8081**, so both can run simultaneously.
---
## Tests
```bash
pytest # in the POC environment
python tests/_runner.py # offline harness when pytest isn't installed
```
Covers auth-header construction, base-URL normalisation, ADF→text flattening,
ticket normalisation, log-attachment filtering, Confluence storage-format
stripping, search-result normalisation, CQL escaping, and — via a stub HTTP
transport (so no network is needed) — ticket fetch with auto-download, JQL
search normalisation, write guards, Confluence search/get_page/caching, and
child-page listing. 19 tests, all offline.
> Live Jira/Confluence calls and running the MCP over a real transport need
> network access and the `mcp`/`httpx` packages installed, which the build
> sandbox blocks. The tests validate all request-building and
> response-handling logic against real payloads through the stubbed transport.
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: Jira actions target tickets, comments, fields, and attachments, while Confluence actions target pages, child pages, and search. Overlap is minor and resolved by descriptions, such as get_ticket for whole-ticket data and get_attachment for one specific attachment.
All tools follow a consistent snake_case verb_noun pattern: get_*, search_*, post_*, update_*. There are no one-word verbs, version suffixes, or mixed conventions, making the tool set predictable.
Eight tools is well-scoped for a server spanning Jira and Confluence. Each tool serves a distinct purpose and none are redundant, keeping the surface compact while covering meaningful retrieval and update workflows.
The set supports the core investigation workflow: search and read Jira tickets, download attachments, add comments, update fields, and search/read Confluence pages. Missing issue creation, issue deletion, and Confluence write operations are notable as general CRUD gaps, but they appear to be intentionally outside the workflow described by this server.