Skip to main content
Glama
README.md
# jira-mcp

Read-only [MCP](https://modelcontextprotocol.io) server for **Jira Server / Data Center** (REST API **v2**) at `https://jira.tiddev.com`.

It wraps Jira's REST API with Model Context Protocol tools so an MCP client (Claude, opencode, etc.) can query projects, issues, comments, transitions and issue types. **No tool mutates data** — every call is a read.

## Tools

| Tool | What it does |
|------|--------------|
| `jira_search_issues` | Search issues with a JQL query |
| `jira_get_issue` | Full details of one issue by key |
| `jira_get_comments` | Read-only comment list for an issue |
| `jira_list_projects` | List visible projects (keys for JQL) |
| `jira_get_issue_types` | List issue types |
| `jira_get_myself` | Current authenticated user (validates token) |
| `jira_get_server_info` | Jira version / instance type |
| `jira_get_transitions` | Allowed status transitions for an issue |

## Setup

1. Build:
   ```
   npm install
   npm run build
   ```
2. Smoke test (build + live checks when `JIRA_TOKEN` is set):
   ```
   npm run smoke
   ```
3. End-to-end MCP protocol test (list tools + live `tools/call` over a real stdio session):
   ```
   node scripts/e2e.mjs
   ```

> **Self-signed cert:** this Jira uses a self-signed internal CA. At runtime set `NODE_TLS_REJECT_UNAUTHORIZED=0` in the MCP client's `env` (see config below) so HTTPS works. That TLS warning is expected on this internal instance.

## Configuration (env)

| Var | Required | Default | Notes |
|-----|----------|---------|-------|
| `JIRA_URL` | No | `https://jira.tiddev.com` | Base URL of the Jira instance |
| `JIRA_TOKEN` | **Yes** | — | Your personal Jira token. Sent as `Authorization: Bearer <token>`. |

> This Jira instance has **Basic user:password auth disabled**; the token-style Bearer auth above is the working auth method (verified against the live server).

## MCP client config (opencode)

```json
{
  "mcpServers": {
    "jira": {
      "command": "node",
      "args": ["D:/Work/usdmf/jira-mcp/dist/index.js"],
      "env": {
        "JIRA_URL": "https://jira.tiddev.com",
        "JIRA_TOKEN": "<your-token>",
        "NODE_TLS_REJECT_UNAUTHORIZED": "0"
      }
    }
  }
}
```

## Example calls

- `jira_search_issues` → `{"jql":"project in (PRD) AND type = Bug AND resolution is empty AND status in (To Do, In Progress) ORDER BY updated DESC","maxResults":10}`
- `jira_get_issue` → `{"key":"PRD-195770"}`
- `jira_get_comments` → `{"key":"PRD-195770"}`
- `jira_get_transitions` → `{"key":"PRD-195770"}`

## Notes

- Transport is **stdio**; no network listener is opened.
- Read-only by construction: the client exposes `get` + `search` (the JQL POST) only.
- The token is read from the environment only and never logged or committed.