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

A Model Context Protocol (MCP) server that provides tools for interacting with Jira. Enables Cursor and other MCP clients to fetch tickets, manage linked tickets, and update ticket status.

## Quick Start

### 1. Install Dependencies

```bash
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install project dependencies
uv sync
```

### 2. Configure Jira Credentials

**Recommended: Personal Access Token (PAT)**

1. Log into Jira: https://jira.telekom.de
2. Go to your profile > **Personal Access Tokens**
3. Click "Create token"
4. Give it a name (e.g., "Cursor MCP") and set expiration
5. **Important:** Ensure the token has **"Read"** or **"Browse Projects"** permissions
6. Copy the token immediately (you won't see it again)

Create `.env` file:
```bash
cp .env.example .env
```

Edit `.env` with your credentials:
```env
JIRA_URL=https://jira.telekom.de
JIRA_USERNAME=your.username@telekom.de
JIRA_API_TOKEN=your_personal_access_token_here
JIRA_AUTH_TYPE=bearer
```

**Note:** Kantega SSO API tokens may have IP restrictions or require admin-configured permissions. Personal Access Tokens are recommended for most users.

### 3. Configure in Cursor

1. Open Cursor
2. Go to **Settings > Tools and MCP**
3. Add this configuration:

```json
{
  "mcpServers": {
    "jira": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/jira-mcp",
        "run",
        "-m",
        "src"
      ]
    }
  }
}
```

**Important:** Replace the path and credentials with your actual values!

4. Restart Cursor completely

### 4. Try It Out

In Cursor chat, try:
- "Get details for Jira ticket PROJ-123"
- "Show me all linked tickets for PROJ-456"
- "Update PROJ-789 status to In Progress"

## Features

### Available Tools

| Tool | Description | Example |
|------|-------------|---------|
| `get_ticket` | Fetch full ticket details | "Get PROJ-123" |
| `get_linked_tickets` | Get related tickets & subtasks | "Show linked tickets for PROJ-123" |
| `update_ticket_status` | Update ticket status | "Move PROJ-123 to In Progress" |

### Authentication Support

- **Bearer Token**: Personal Access Tokens (PAT) - **Recommended**
- **Basic Auth**: Username + API token (Atlassian Cloud)
- **Cookie Auth**: Session-based authentication (fallback option)

## Tool Details

### get_ticket

Fetches complete ticket information.

**Parameters:**
- `ticket_id` (string, required): Ticket ID or key (e.g., "PROJ-123")

**Returns:**
```json
{
  "key": "PROJ-123",
  "summary": "Ticket summary",
  "description": "Detailed description",
  "status": "In Progress",
  "issue_type": "Story",
  "priority": "High",
  "assignee": "John Doe",
  "reporter": "Jane Smith",
  "created": "2024-01-15T10:30:00.000+0000",
  "updated": "2024-01-20T14:45:00.000+0000",
  "comments_count": 3,
  "comments": [...],
  "custom_fields": {...}
}
```

### get_linked_tickets

Fetches all related tickets and subtasks.

**Parameters:**
- `ticket_id` (string, required): Ticket ID or key

**Returns:**
```json
{
  "ticket": "PROJ-123",
  "linked_tickets": [
    {
      "link_type": "Blocks",
      "direction": "blocks",
      "key": "PROJ-124",
      "summary": "Related ticket",
      "status": "To Do"
    }
  ],
  "linked_tickets_count": 1,
  "subtasks": [...],
  "subtasks_count": 2
}
```

### update_ticket_status

Updates ticket status with workflow validation.

**Parameters:**
- `ticket_id` (string, required): Ticket ID or key
- `status` (string, required): Target status (e.g., "In Progress", "Done")

**Returns:**
```
Successfully updated ticket PROJ-123 status from 'To Do' to 'In Progress'
```

**Note:** The tool validates transitions. If invalid, it returns available transitions.

## Testing

### Run Tests

```bash
# Run all tests
.venv/bin/pytest tests/ -v

# Run with coverage
.venv/bin/pytest tests/ --cov=src -v

# Run specific test file
.venv/bin/pytest tests/test_integration/test_real_tickets.py -v
```

### Manual Testing

Test the server directly:
```bash
uv run --env-file .env -m src
```

Press Ctrl+C to stop.

## Troubleshooting

### Authentication Errors

**Symptoms:** "401 Unauthorized" or "403 Forbidden"

**Solutions:**
- **Most common:** Personal Access Token is expired - generate a new one
- Verify your PAT has "Read" or "Browse Projects" permissions  
- Check your username matches your Jira account email
- Ensure `JIRA_URL` includes `https://`
- Confirm `JIRA_AUTH_TYPE=bearer` for Personal Access Tokens

### Ticket Not Found

**Symptoms:** "404 Not Found"

**Solutions:**
- Verify the ticket key is correct (e.g., "PROJ-123")
- Check you have permission to view the ticket
- Ensure you're using the correct Jira instance

### Server Not Appearing in Cursor

**Solutions:**
- Verify the absolute path in your MCP settings
- Check Python 3.12+ is installed: `python3 --version`
- Restart Cursor completely (quit and reopen)
- Check Cursor's developer console for errors

### Cannot Transition Ticket

**Symptoms:** "Invalid status transition"

**Solutions:**
- The error message lists available transitions
- Status names must match exactly (case-insensitive)
- Check your Jira workflow permissions
- Verify the transition is valid for your workflow

## Architecture

This project follows SOLID principles and clean architecture:

```
src/
├── __init__.py
├── __main__.py           # Entry point
├── server.py             # MCP server setup
├── config/               # Configuration management
├── client/               # Jira API client
├── tools/                # 3 MCP tools
├── models/               # Domain models
├── mappers/              # Data transformation
└── utils/                # Error handling, JSON utils
```

**Key Principles:**
- **SOLID**: Single responsibility, dependency inversion
- **DRY**: No duplication, reusable components
- **Type Safety**: Full type hints throughout
- **Testable**: Clean separation of concerns

See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed technical documentation.

## Development

### Project Structure

```
jira-mcp/
├── src/                  # Source code (22 Python files)
├── tests/                # Test suite
├── pyproject.toml        # Project config (includes pytest config)
├── .env.example          # Config template
├── .gitignore
├── README.md             # This file
└── ARCHITECTURE.md       # Technical docs
```

### Adding Dependencies

```bash
uv add package-name
```

### Running with Different Config

```bash
uv run --env-file .env.production -m src
```

### Code Quality

- **Linting errors:** 0
- **Type coverage:** 100%
- **Test coverage:** Integration tests for all 3 tools
- **Architecture:** SOLID + DRY compliant

## Requirements

- Python 3.12+
- Jira account with API access
- Jira API token (Kantega SSO Enterprise or Atlassian Cloud)

## License

This project is provided as-is for use with Cursor and Jira.

---

**Built with best practices following SOLID and DRY principles** 🚀

TDQS

A3.8/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct operation: retrieving a ticket, fetching linked tickets, and updating status. No overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent 'verb_noun' pattern in snake_case (get_ticket, get_linked_tickets, update_ticket_status), making them predictable.

Tool Count4/5

Three tools is on the lower end of the ideal range but still reasonable for a focused Jira server. Each tool serves a clear purpose without feeling sparse.

Completeness2/5

Missing essential CRUD operations such as create_ticket, search_tickets, or add_comment. Agents cannot create new tickets or perform most lifecycle actions.

Maintenance

ActivityInactive
ResponsivenessNo issues