npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jira-universal-server

v0.1.5

Published

Jira MCP server over stdio only (stdin/stdout JSON-RPC). Not HTTP — use command/args in Cursor & Claude.

Readme

jira-universal-server

stdio only — not HTTP. This program does not listen on a port. It speaks MCP by reading stdin and writing stdout (JSON-RPC). You must configure clients with command + args + env (or global jira-universal-server). If you still have a url like http://localhost:3000/mcp in Cursor or Claude, remove it; that was for an older HTTP transport and will not work with this package.

Model Context Protocol server for Jira Cloud and Jira Data Center / Server. It talks to Jira over REST using your instance base URL (no hard‑coded cloud assumptions) and exposes tools for issues, search, projects, users, and Agile boards/sprints.

Transport: StdioServerTransport from @modelcontextprotocol/sdk — standard input/output only. Hosts (Cursor, Claude Desktop, Claude Code, etc.) spawn this process and pipe MCP over stdio.

Running npm start in a terminal will look idle: it is waiting for MCP on stdin, which only the host provides. Use the client config below instead of opening a browser or curling a URL.

Installation

npm install -g jira-universal-server

The CLI on your PATH is jira-universal-server (see package.json bin).

Or use from a checkout:

npm install
npm run build
npm start

Quick start

Pass Jira settings via environment variables (client env block, or a .env next to the working directory when using dotenv — the process loads .env from the current working directory).

Jira Cloud (basic auth — API token)

JIRA_BASE_URL=https://yourcompany.atlassian.net
JIRA_AUTH_TYPE=basic
[email protected]
JIRA_API_TOKEN=your_atlassian_api_token
JIRA_API_VERSION=3

Jira Cloud (PAT)

JIRA_BASE_URL=https://yourcompany.atlassian.net
JIRA_AUTH_TYPE=pat
JIRA_PAT=your_personal_access_token

Jira Data Center (basic)

JIRA_BASE_URL=https://jira.yourcompany.com
JIRA_AUTH_TYPE=basic
[email protected]
JIRA_API_TOKEN=your_password_or_token_as_configured
JIRA_API_VERSION=2

Use API version 2 on many Data Center deployments; try 3 if your platform supports it.

Jira Data Center (PAT)

JIRA_BASE_URL=https://jira.yourcompany.com
JIRA_AUTH_TYPE=pat
JIRA_PAT=your_personal_access_token
JIRA_API_VERSION=2

See .env.example for a template.

Client configuration (stdio)

Claude Desktop

Config path is platform-dependent, e.g. macOS: ~/Library/Application Support/Claude/claude_desktop_config.json.

{
  "mcpServers": {
    "jira": {
      "command": "npx",
      "args": ["-y", "jira-universal-server"],
      "env": {
        "JIRA_BASE_URL": "https://yourcompany.atlassian.net",
        "JIRA_AUTH_TYPE": "basic",
        "JIRA_EMAIL": "[email protected]",
        "JIRA_API_TOKEN": "your_api_token"
      }
    }
  }
}

If the package is installed globally:

{
  "mcpServers": {
    "jira": {
      "command": "jira-universal-server",
      "args": [],
      "env": {
        "JIRA_BASE_URL": "https://yourcompany.atlassian.net",
        "JIRA_AUTH_TYPE": "basic",
        "JIRA_EMAIL": "[email protected]",
        "JIRA_API_TOKEN": "your_api_token"
      }
    }
  }
}

Cursor (.cursor/mcp.json in project or ~/.cursor/mcp.json)

{
  "mcpServers": {
    "jira": {
      "command": "npx",
      "args": ["-y", "jira-universal-server"],
      "env": {
        "JIRA_BASE_URL": "https://yourcompany.atlassian.net",
        "JIRA_AUTH_TYPE": "basic",
        "JIRA_EMAIL": "[email protected]",
        "JIRA_API_TOKEN": "your_api_token"
      }
    }
  }
}

Local build (absolute path)

{
  "mcpServers": {
    "jira": {
      "command": "node",
      "args": ["/absolute/path/to/jira-universal-server/dist/index.js"],
      "env": {
        "JIRA_BASE_URL": "https://yourcompany.atlassian.net",
        "JIRA_AUTH_TYPE": "basic",
        "JIRA_EMAIL": "[email protected]",
        "JIRA_API_TOKEN": "your_api_token"
      }
    }
  }
}

Restart the host app after editing MCP config.

Auth guide

| Strategy | Header | When to use | |----------|--------|-------------| | basic | Authorization: Basic base64(email:token) | Cloud: Atlassian account email + API token. Data Center: Often the same pattern if your admin documents it; some sites use username + password or token — follow your Jira docs. | | pat | Authorization: Bearer <PAT> | Cloud and Data Center when PATs are enabled. Create in Jira under profile/security or admin PAT settings (product‑dependent). | | oauth2 | Bearer (planned) | Stub only in this release; use basic or pat. |

basic is the usual choice for Cloud API tokens. pat avoids embedding the email and matches setups that only issue bearer tokens.

REST API version

Only the core REST path /rest/api/{version} is negotiable (supported 2 and 3). Agile is always /rest/agile/1.0.

With stdio transport, the Jira REST API version is taken from:

  1. Environment variable JIRA_API_VERSION (2 or 3)
  2. If unset, default 3

(resolveApiVersionFromSources in code still supports additional sources for reuse; the running stdio server uses env + default.)

When to use v2 vs v3

  • Jira Cloud today is typically v3 (richer payloads, ADF for some text fields).
  • Data Center often still documents v2 for the platform REST API; use v2 if v3 returns 404 or errors.

Environment variables

| Name | Required | Default | Description | |------|----------|---------|-------------| | JIRA_BASE_URL | Yes | — | Instance root, e.g. https://company.atlassian.net or https://jira.company.com (no trailing slash required). | | JIRA_AUTH_TYPE | No | basic | basic, pat, or oauth2 (oauth2 stub). | | JIRA_EMAIL | If basic | — | Account email (basic). | | JIRA_API_TOKEN | If basic | — | API token or password as required by your server (basic). | | JIRA_PAT | If pat | — | Personal access token (pat). | | JIRA_OAUTH_ACCESS_TOKEN | No | — | Reserved for future OAuth2 support. | | JIRA_API_VERSION | No | 3 | Jira REST API version (2 or 3). |

Rebuild and quick test

npm run build

Smoke test (process should stay alive waiting for MCP messages on stdin; invalid JSON may error — that is expected):

echo '{}' | node dist/index.js

Prefer validating by connecting Cursor or Claude Desktop with the config above and running a tool such as list_projects.

Custom fields

Jira stores custom data under keys like customfield_12345. This server:

  • Requests *all fields from Jira by default for get_issue, search_issues, get_my_issues, and get_sprint_issues. On many Jira Data Center / Server instances, *navigable returns standard fields but omits customfield_* in the JSON even though you can browse the issue in the UI — *all is the reliable way to get custom field values over REST.
  • Adds a customFields object on each flattened issue with every customfield_* entry, values lightly normalized (users, selects, ADF docs, arrays).

If payloads are too large, pass fields: *navigable on get_issue or search_issues.fields: ["*navigable"] only after you have confirmed your Jira actually includes your custom fields in that response.

MCP tools

Responses are JSON text in the MCP content field, with flattened objects (not raw Jira payloads). Jira 401 / 403 are turned into clear messages referencing your configured auth type.

Issues

| Tool | Inputs | Example output (shape) | |------|--------|-------------------------| | get_issue | issueKey, fields? (*all default) | Core fields + customFields. Use *navigable only if you need a smaller response and your Jira still returns customs there. | | create_issue | projectKey, summary, issueType, description? | { id, key, self } | | update_issue | issueKey, fields (map) | { ok: true, issueKey } | | delete_issue | issueKey | { ok: true, issueKey } | | get_transitions | issueKey | { issueKey, transitions: [{ id, name, toStatus }] } | | transition_issue | issueKey, transitionId | { ok: true, issueKey, transitionId } | | add_comment | issueKey, body | { id, author, body, created, … } | | get_comments | issueKey | { issueKey, comments: [...] } | | assign_issue | issueKey, accountId | { ok: true, issueKey, accountId } |

Search

| Tool | Inputs | Example output | |------|--------|----------------| | search_issues | jql, fields? (default [*all]), maxResults?, startAt? | { total, startAt, maxResults, issues: [...] } — each issue includes customFields for customfield_* keys | | get_my_issues | (none) | Same as search with fixed JQL for current user’s unresolved work |

Projects

| Tool | Inputs | Example output | |------|--------|----------------| | list_projects | (none) | { projects: [{ id, key, name, … }], count } | | get_project | projectKey | Project summary object | | get_project_statuses | projectKey | { projectKey, issueTypes: [{ issueTypeName, statuses }] } |

Users

| Tool | Inputs | Example output | |------|--------|----------------| | get_current_user | (none) | { accountId, displayName, email?, … } | | find_users | query | { query, users: [...], count } |

Boards / Sprints (Agile 1.0)

| Tool | Inputs | Example output | |------|--------|----------------| | list_boards | projectKey? | { boards: [{ id, name, type }], count } or agile‑unavailable message | | list_sprints | boardId, state? | { boardId, sprints: [...], count } or agile‑unavailable message | | get_sprint_issues | sprintId | { sprintId, issues: [...], total, … } — issues use *all fields + customFields; or agile‑unavailable message |

On 404 from Agile endpoints, tools return a clear message that Jira Software / Agile REST may not be installed or enabled (common on some Data Center setups).

Data Center notes

  • Prefer JIRA_API_VERSION=2 unless your version documents REST v3.
  • Agile tools require the Jira Software application and REST Agile endpoints. If the plugin is missing or URLs differ, you may see the graceful “agile unavailable” style response instead of a hard crash.

Example JQL (search_issues)

project = PROJ AND status = "In Progress"
assignee = currentUser() AND sprint in openSprints()
created >= -7d ORDER BY created DESC
type = Bug AND priority = High
text ~ "regression" AND updated >= -30d

Development

npm run dev    # tsx src/index.ts
npm run build
npm start

License

MIT