Skip to main content
Glama
README.md
# JIRA MCP Server

A production-grade [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that exposes JIRA sprint data as MCP **Tools** and **Prompts**.

Ships with rich in-memory mock data (30 issues, 8 assignees) and a pluggable `JiraClient` abstraction that makes connecting to a real Atlassian JIRA instance a drop-in upgrade.

---

## Features

| Category | Detail |
|----------|--------|
| Transport | SSE (HTTP) — compatible with Cursor, Claude.ai Web, and any SSE-capable MCP client |
| Tools | `get_active_sprint_issues`, `get_issue_details` |
| Prompts | `format_sprint_progress`, `format_issue_details` |
| Data layer | Abstract `JiraClient` — swap mock ↔ real API via env var |
| Models | Pydantic v2 with full type safety |

---

## Project Structure

```
jira-mcp-server/
├── main.py                         # Entry point (SSE server)
├── pyproject.toml
└── src/
    ├── data/
    │   ├── models.py               # Pydantic v2 models (JiraIssue, Assignee, SprintMeta)
    │   └── mock_issues.py          # 30 mock issues + SPRINT_META
    ├── jira/
    │   ├── __init__.py             # get_jira_client() factory
    │   ├── base.py                 # Abstract JiraClient (ABC)
    │   ├── mock_client.py          # MockJiraClient — in-memory fixture data
    │   └── api_client.py           # ApiJiraClient — real JIRA REST stub
    ├── server/
    │   ├── app.py                  # FastMCP instance + client initialisation
    │   └── tools.py                # @mcp.tool registrations
    └── prompts/
        ├── sprint_progress.py      # @mcp.prompt: format_sprint_progress
        └── issue_details.py        # @mcp.prompt: format_issue_details
```

---

## Quick Start

### Prerequisites

- Python 3.12+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip

### Install dependencies

```bash
uv sync
```

### Run the server

```bash
# Using the installed script:
uv run jira-mcp-server

# Or directly:
uv run python main.py
```

The SSE server starts at **`http://localhost:8000/sse`** by default.

Override host/port via environment variables:
```bash
MCP_HOST=127.0.0.1 MCP_PORT=9000 uv run jira-mcp-server
```

---

## MCP Client Configuration

### Cursor

Add to `.cursor/mcp.json` (project-level) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "jira": {
      "url": "http://localhost:8000/sse"
    }
  }
}
```

### Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "jira": {
      "url": "http://localhost:8000/sse"
    }
  }
}
```

---

## Tools

### `get_active_sprint_issues`

Returns all issues in the active sprint for the provided Scrum board name as a JSON array.

```json
{ "scrum_board_name": "Platform Engineering Scrum Board" }
```

### `get_issue_details`

Returns the full details of a single issue.

```json
{ "issue_id": "PROJ-1" }
```

Raises an error if the issue key does not exist.

---

## Prompts

### `format_sprint_progress`

Generates a comprehensive **scrum master report** in Markdown:

- Sprint Overview table (totals, velocity, completion %)
- Blockers section (table + impact analysis per blocker)
- Risk Analysis (Critical + High items not Done)
- Resource Utilisation table (per-assignee: issues, SP, completion %)
- Bandwidth Analysis (overloaded / under-utilised members + rebalancing suggestions)
- Key Insights (patterns, anomalies)
- Recommended Next Steps (prioritised action list)

```json
{
  "sprint_data_json": "{\"sprint_meta\":{...},\"issues\":[...]}"
}
```

`sprint_data_json` should be the JSON payload returned by tools (metadata + issues),
or an issues-only JSON array.

### `format_issue_details`

Renders a single issue as a structured Markdown document with:

- Header (ID + Summary + Type + Status + Priority)
- Metadata table (all fields)
- Description section
- Acceptance Criteria checklist (auto-checked if status = Done)
- Labels

```json
{
  "issue_json": "{\"id\":\"PROJ-5\",...}"
}
```

`issue_json` should be the JSON object returned by `get_issue_details`.

---

## Connecting to Real JIRA

The `JiraClient` abstraction makes this a configuration-only change:

1. Set the following environment variables:

   ```bash
   JIRA_BASE_URL=https://your-org.atlassian.net
   JIRA_EMAIL=service-account@your-org.com
   JIRA_API_TOKEN=your-atlassian-api-token
   JIRA_BOARD_ID=3
   JIRA_PROJECT_KEY=PROJ
   ```

2. Fill in the `TODO` sections in [src/jira/api_client.py](src/jira/api_client.py):
   - Uncomment the `httpx` import and install `httpx` (`uv add httpx`)
   - Implement `get_sprint_issues`, `get_issue`, and `get_sprint_meta` using the JIRA Agile REST API v1 and REST API v3 endpoints documented inline

3. Restart the server — the factory auto-selects `ApiJiraClient` when `JIRA_API_TOKEN` is present.

No changes to tools, prompts, or server code are required.

---

## Development

### Inspect with MCP Inspector

```bash
uv run mcp dev main.py
```

Opens the interactive MCP Inspector in your browser with all tools and prompts available for testing.

### Static analysis

```bash
uv run mypy src/ main.py
uv run ruff check src/ main.py
```

Maintenance

ActivityInactive
ResponsivenessNo issues