Skip to main content
Glama
christojansen75

Jira/Confluence Team Lead MCP

README.md
# Jira / Confluence Team Lead

An MCP server **and** an Angular dashboard that answer the questions a team
lead actually has, and can publish the answer to Confluence:

1. **What's in this sprint, and is it going to land?**
2. **How did each developer do over the last few sprints?** (real
   changelog-derived cycle/lead time, not a guess from current status)
3. **What's not ready for the next refinement session, and who should be in
   the room?**
4. **Who has gone quiet?** — active work with no comment for over a day.

Built and tested against a personal Atlassian Cloud site first; the target
corporate instance is a `.env` change, not a code change.

## Layout

```
src/jira_confluence_mcp/   the report engine (metrics, rendering, Atlassian client)
  server.py                MCP server        — stdio, for Claude
  api.py                   HTTP API          — for the dashboard
frontend/                  Angular dashboard
scripts/demo_server.py     run the dashboard on synthetic data, no Jira needed
```

The MCP tools and the dashboard call the *same* report builders, so a number
shown in the UI and a number quoted in chat can't drift apart.

## See it working without Jira

Two terminals, no credentials required:

```bash
.venv\Scripts\python.exe scripts\demo_server.py
```

```bash
cd frontend && npm start
```

Then open <http://localhost:4200>. The data is invented, but it flows through
the real changelog parsing and metric code.

## Setup

```bash
python -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
```

Copy `.env.example` to `.env` and fill in the base URL, your Atlassian email,
and an API token from <https://id.atlassian.com/manage-profile/security/api-tokens>.

Then register the server (`.mcp.json` in this repo already does it for Claude
Code — adjust the absolute paths if you move the project):

```bash
claude mcp add jira-confluence -- "C:\DEV\Jira Confluence MCP\.venv\Scripts\python.exe" -m jira_confluence_mcp.server
```

First call should always be `check_connection` — it verifies both products,
prints the resolved defaults, and tells you which custom field it picked for
story points.

## The dashboard

```bash
.venv\Scripts\python.exe -m jira_confluence_mcp.api
```

```bash
cd frontend && npm start
```

The dev server proxies `/api` to the backend on port 8000, so there's no CORS
to configure. Four screens:

- **Overview** — completion against time elapsed, points, at-risk count, a
  changelog-derived burndown, load per person, and a filterable issue table.
- **Developers** — the multi-sprint table, one row per developer per sprint.
  Sort any column, filter by developer or sprint, export to CSV. This is the
  thing Confluence's static tables can't do.
- **Refinement** — what's not ready, why, and a copyable attendee list.
- **Quiet work** — active issues with no recent comment, per person.

Every screen has a **Publish to Confluence** button that writes the same
report as the MCP tool would. The browser sends the report *kind*, never
markup — the server regenerates the storage format itself, so the API can't
be used to inject arbitrary content into a Confluence page.

Reports are cached for 120 s so the dashboard doesn't hammer Jira; each page's
Refresh button bypasses the cache.

> **Node version:** the CLI is pinned to Angular 21 because Angular 22 needs
> Node ≥ 22.22.3 and this machine has 22.17.0. Upgrade Node first if you want
> to move to 22.

## Tools

| Tool | What it does |
| --- | --- |
| `check_connection` | Auth check + resolved config. Run this first on a new instance. |
| `list_sprints` | Sprints on a board, so you can find sprint ids. Falls back to listing boards if none is configured. |
| `get_sprint_issues` | Issues in a sprint, filterable by status name or status category. Key, summary, assignee, story points, status. |
| `get_developer_sprint_history` | 2–5 sprint rollup per developer: completed, carried over, avg time in progress, cycle time, lead time. |
| `get_refinement_readiness_report` | Stories missing an estimate or DOR/DOD labels, plus a suggested attendee list. |
| `get_sprint_health` | One-call sprint overview: totals, breakdowns, burndown. Powers the Overview screen. |
| `get_stale_issues` | Active work with no comment for over N days — who's gone quiet. |
| `publish_confluence_page` | Create or overwrite a page from storage-format XHTML. |
| `check_confluence_capabilities` | Cloud vs Data Center, and whether the Table Filter app is available. |

Every report tool returns `rows` (structured), `markdown` (for reading), and —
with `include_confluence_storage=true` — `confluence` (storage format). Pass
`publish=true` to write it straight to a page; re-running overwrites the same
page by title.

## Metric definitions

These are the decisions baked into `metrics.py`. Worth agreeing with the team
before the numbers get used in a retro.

- **Completed** — the issue was in a *Done-category* status at sprint close
  (`completeDate`, else `endDate`, else now for an active sprint). Judged at
  sprint close, so an issue finished the week after the sprint ended counts as
  carried over *for that sprint*. Never evaluated past *now*, so an active
  sprint is measured against today rather than its future end date.
- **Carried over** — everything in the sprint that was not completed.
- **Re-opened work** — an issue that was Done and moved back out is not
  completed. Closed → re-opened → closed again reports the *final* close.
- **Time in progress** — calendar hours in *In Progress-category* statuses,
  summed across visits, capped at completion or sprint close.
- **Cycle time** — first entry into an In Progress-category status → completion.
- **Lead time** — issue created → completion.
- **Grouping** — by the issue's *current* assignee. Reassigned work is credited
  to whoever holds it now; the changelog has the data to split it by holder if
  that turns out to matter.

Status *categories* (`new` / `indeterminate` / `done`) are read from the
instance rather than hard-coded status names, so a workflow that calls it
"Development" instead of "In Progress" still works. Any status the instance
does not report is surfaced in the report's `warnings`.

## Confluence tables

Storage-format tables are static — not sortable or filterable. Options, in the
order worth trying on a target instance:

1. `table_style="table-filter"` — wraps the table in the **Table Filter, Charts
   & Spreadsheet** macro. Run `check_confluence_capabilities` first; reading
   the app inventory needs admin rights, so a `null` result means "ask an
   admin", not "not installed".
2. Confluence Cloud's **database** content type — behaves like an embedded
   spreadsheet, but cannot be created through the REST content API this server
   uses. Manual setup only for now.
3. `table_style="plain"` (default) — static table. Re-run the report grouped or
   sorted differently when another view is needed. Good enough for MVP.

## Switching to another instance

Only `.env` changes:

- `JIRA_BASE_URL` / `CONFLUENCE_BASE_URL` — set both explicitly if Jira and
  Confluence are on different hosts (usual for Data Center).
- `ATLASSIAN_DEPLOYMENT` — leave `auto` unless the URL doesn't give it away.
  Data Center means `/rest/api/2` and offset-paged search; the client handles
  the switch, including falling back from the Cloud-only `/search/jql`.
- `JIRA_STORY_POINTS_FIELD` — auto-discovery looks for "Story Points" /
  "Story point estimate"; pin the custom field id if the instance renamed it.
- `REFINEMENT_DOR_LABELS` / `REFINEMENT_DOD_LABELS` — the team's actual labels.
- `ATLASSIAN_CA_BUNDLE` — corporate root CA, for an internal TLS chain.
  Prefer this over turning `ATLASSIAN_VERIFY_SSL` off.

## Tests

```bash
.venv\Scripts\python.exe -m pytest -q
```

```bash
cd frontend && npm test
```

80 Python tests and 20 Angular tests, no Atlassian instance required — HTTP is
mocked with `respx`, and the metric logic is tested as pure functions over
changelog fixtures.

## Not built yet

- `get_story_comment_summary` — a full per-developer comment timeline within a
  story. `get_stale_issues` covers the "who has gone quiet" half of it; decide
  whether the rest is worth having after a few sprints of real use.
- Push alerting (Slack/Teams) for quiet stories. The detection exists; only the
  delivery channel is missing.
- Postgres sync. Today the dashboard reads Jira live behind a 120 s cache, which
  is fine at team scale. The `rows` payloads are already shaped for a
  table-per-report load if history or cross-team rollups are wanted later.
- Auth on the API. It binds to localhost and assumes whoever reaches it is you.
  Anything beyond your own machine needs real authentication in front of it.

TDQS

A3.7/5.0

Scored across 7 tools

Disambiguation4/5

Each tool has a clear focus: connection verification, sprint listing, sprint issue retrieval, developer history, readiness report, Confluence publishing, and Confluence capability checking. The two 'check' tools are distinct in scope (credentials/config vs. instance capabilities), and the three 'get' tools serve different analytical purposes. Minor potential confusion between get_sprint_issues and get_refinement_readiness_report, but their descriptions clarify.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with snake_case (check_connection, list_sprints, get_sprint_issues, etc.). Verbs are consistent with actions: check for verification, list for enumeration, get for retrieval, publish for writing. No mixed conventions.

Tool Count5/5

Seven tools is well-scoped for a Jira/Confluence reporting server. Each tool fills a distinct role: setup verification, sprint navigation, issue analysis, developer performance, readiness reporting, publishing, and format capability detection. No redundancy or bloat.

Completeness4/5

The tool set covers the full reporting workflow: verify connection, find sprints, analyze issues by sprint or developer, generate readiness report, and publish results to Confluence. Minor gaps like listing boards or projects are handled through configuration defaults rather than requiring tools. No tool for arbitrary JQL queries, but not necessary for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessNo issues