Skip to main content
Glama
abuzo

MCP Atlassian Node Server

by abuzo
README.md
# MCP Atlassian Node Server

Production-ready MCP (Model Context Protocol) server for Atlassian Jira and Confluence built with Node.js + TypeScript.

## Features

- Node 20+ TypeScript ESM server.
- MCP tools for generic Jira/Confluence proxy calls and high-level wrappers.
- Auth modes:
  - Service-specific Basic auth via `JIRA_EMAIL` + `JIRA_API_TOKEN` and `CONFLUENCE_EMAIL` + `CONFLUENCE_API_TOKEN`.
  - Service-specific Bearer auth via `JIRA_BEARER_TOKEN` and `CONFLUENCE_BEARER_TOKEN`.
  - Global fallback auth via `ATLASSIAN_*` when service-specific values are not provided.
- Config validation with clear startup errors.
- HTTP layer powered by `undici`:
  - retries with exponential backoff
  - respects `Retry-After`
  - request/response logging with token redaction
  - configurable timeout (30s)
  - max response size limit (10 MB)
- Security controls:
  - base URL allowlist derived from config (SSRF prevention)
  - path prefix validation for Jira/Confluence APIs
  - optional TLS verification bypass for self-signed corporate cert chains (`SSL_VERIFY=false`)
- Confluence normalization helpers:
  - plain text extraction from storage HTML
  - normalized document object with metadata and attachments

## Requirements

- Node.js `>=20`
- npm

## Install

```bash
npm i
```

## Configuration

Copy `.env.example` and set values:

```bash
ATLASSIAN_SITE=https://company.atlassian.net
JIRA_BASE_URL=https://jira.company.internal
JIRA_API_VERSION=2
CONFLUENCE_BASE_URL=https://wiki.company.internal
CONFLUENCE_API_PREFIX=/rest/api

# Optional global fallback auth
ATLASSIAN_EMAIL=you@company.com
ATLASSIAN_API_TOKEN=global_fallback_token
ATLASSIAN_BEARER_TOKEN=

# Jira auth
JIRA_EMAIL=you@company.com
JIRA_API_TOKEN=jira_api_token
JIRA_BEARER_TOKEN=

# Confluence auth
CONFLUENCE_EMAIL=you@company.com
CONFLUENCE_API_TOKEN=confluence_api_token
CONFLUENCE_BEARER_TOKEN=

SSL_VERIFY=true
USER_AGENT=jira-mcp
```

### Environment variables

- `ATLASSIAN_SITE` (required): base site URL, e.g. `https://company.atlassian.net`
- `JIRA_BASE_URL` (optional): defaults to `ATLASSIAN_SITE`
- `JIRA_API_VERSION` (optional, `2`/`3`, default `2`): Jira REST API version used by Jira tools and relative `jira_request` paths
- `CONFLUENCE_BASE_URL` (optional): defaults to `ATLASSIAN_SITE`
- `CONFLUENCE_API_PREFIX` (optional): Confluence REST prefix.
  - Cloud default: `/wiki/rest/api`
  - Server/Data Center default: `/rest/api`
  - Custom context path example: `/confluence/rest/api`
- `JIRA_BEARER_TOKEN` (optional): Jira Bearer token, takes precedence for Jira requests
- `CONFLUENCE_BEARER_TOKEN` (optional): Confluence Bearer token, takes precedence for Confluence requests
- `JIRA_EMAIL` (optional): Jira Basic auth email
- `JIRA_API_TOKEN` (optional): Jira Basic auth token
- `CONFLUENCE_EMAIL` (optional): Confluence Basic auth email
- `CONFLUENCE_API_TOKEN` (optional): Confluence Basic auth token
- `ATLASSIAN_BEARER_TOKEN` (optional): global Bearer fallback for any service without service-specific bearer token
- `ATLASSIAN_EMAIL` (optional): global Basic auth email fallback
- `ATLASSIAN_API_TOKEN` (optional): global Basic auth token fallback
- `SSL_VERIFY` (optional, `true`/`false`, default `true`)
- `USER_AGENT` (optional, default `jira-mcp`)

## Run

Development:

```bash
npm run dev
```

Build:

```bash
npm run build
```

Start built server:

```bash
npm start
```

Manual smoke test (direct API calls):

```bash
npm run build
npm run manual:test
```

## MCP Tools

### Generic proxy tools

- `jira_request`
- `confluence_request`

`jira_request` uses `JIRA_API_VERSION` when `apiVersion` is not provided.

Both return:

```json
{
  "status": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {}
}
```

### Jira tools

- `jira_search_issues`
- `jira_get_issue`
- `jira_get_project`
- `jira_list_projects`
- `jira_get_transitions`
- `jira_transition_issue`
- `jira_add_comment`
- `jira_get_users`
- `jira_download_attachment`

`jira_download_attachment`:
- input: `attachmentId`, optional `mode` (`base64` or `file`)
- output always uses `{ status, headers, body }`; for non-2xx Jira responses it still returns this shape with error details in `body`

### Confluence tools

- `confluence_get_page`
- `confluence_search`
- `confluence_get_children`
- `confluence_get_page_content`
- `confluence_get_attachments`
- `confluence_download_attachment`

`confluence_get_page_content` returns:
- original Confluence page payload
- normalized `document`

```json
{
  "id": "12345",
  "title": "Page Title",
  "url": "https://company.atlassian.net/wiki/spaces/ENG/pages/12345/Page+Title",
  "spaceKey": "ENG",
  "updatedAt": "2025-01-01T12:00:00.000Z",
  "text": "Plain text extracted from storage HTML",
  "html": "<p>Original storage HTML</p>",
  "breadcrumbs": ["Parent", "Child"],
  "labels": ["runbook"],
  "attachments": [
    {
      "id": "att-1",
      "title": "diagram.png",
      "mediaType": "image/png",
      "fileSize": 10240,
      "downloadUrl": "https://company.atlassian.net/wiki/download/attachments/..."
    }
  ]
}
```

## Authentication examples

Different servers, different tokens:

```bash
JIRA_BASE_URL=https://jira.company.internal
JIRA_API_VERSION=2
CONFLUENCE_BASE_URL=https://wiki.company.internal
CONFLUENCE_API_PREFIX=/rest/api
JIRA_BEARER_TOKEN=jira_bearer_token
CONFLUENCE_BEARER_TOKEN=confluence_bearer_token
```

Different Basic tokens:

```bash
JIRA_EMAIL=you@company.com
JIRA_API_TOKEN=jira_api_token
CONFLUENCE_EMAIL=you@company.com
CONFLUENCE_API_TOKEN=confluence_api_token
```

Global fallback for both services:

```bash
ATLASSIAN_EMAIL=you@company.com
ATLASSIAN_API_TOKEN=global_api_token
# or
ATLASSIAN_BEARER_TOKEN=global_bearer_token
```

## Corporate proxy / self-signed cert support

To disable TLS certificate verification explicitly:

```bash
SSL_VERIFY=false
```

Default is secure verification (`SSL_VERIFY=true`).

## Notes

- Tokens are never printed in logs.
- HTTP logs are emitted to `stderr` so MCP stdio communication remains valid on `stdout`.
- HTTP 3xx redirects are treated as errors (`HTTP_REDIRECT`) to surface auth/login redirect issues explicitly.
- If Confluence returns redirect to `login.action` with `fourohfour.action`, set `CONFLUENCE_API_PREFIX` for your deployment (commonly `/rest/api` for Server/DC).
- If official MCP SDK loading fails, a minimal JSON-RPC stdio adapter starts automatically.

How to add to cursor:

```json
{
  "mcpServers": {
    "atlassian": {
      "command": "node",
      "args": ["/your/path/to/JIRA_MCP/dist/index.js"],
      "env": {
        "ATLASSIAN_SITE": "https://company.atlassian.net",
        "JIRA_BASE_URL": "https://jira.company.internal",
        "JIRA_API_VERSION": "2",
        "CONFLUENCE_BASE_URL": "https://wiki.company.internal",
        "CONFLUENCE_API_PREFIX": "/rest/api",
        "JIRA_BEARER_TOKEN": "jira_token",
        "CONFLUENCE_BEARER_TOKEN": "confluence_token",
        "SSL_VERIFY": "true"
      }
    }
  }
}
```

## Publishing to npm

1. **Имя пакета:** `@alexbuzo/jira-mcp`. Проверка: `npm view @alexbuzo/jira-mcp`.

2. **Вход в npm:** `npm login` (или `npm login --registry=https://registry.npmjs.org/`).

3. **Сборка перед публикацией** выполняется автоматически скриптом `prepublishOnly` (`npm run build`).

4. **Публикация** (в `package.json` задано `publishConfig.access: public`):
   ```bash
   npm publish
   ```
   При необходимости явно: `npm publish --access public`.

5. **После публикации** в Cursor через `npx`:
   ```json
   "command": "npx",
   "args": ["-y", "@alexbuzo/jira-mcp"],
   "env": { ... }
   ```

Или `command`: `jira-mcp`, если пакет установлен глобально (`npm i -g @alexbuzo/jira-mcp` — исполняемый файл по-прежнему называется `jira-mcp`).