jira-run-mcp
Provides a comprehensive MCP interface for interacting with Jira 8, including tools for issue management (create, read, update, delete, search, transitions, cloning, subtasks), worklogging via Tempo Timesheets, commenting, linking issues, user assignment, attachment handling, and project metadata discovery. Uses SSO authentication via Playwright for secure access.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jira-run-mcpshow me my open issues"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
jira-run-mcp
An internal MCP (Model Context Protocol) server for Jira 8, using SSO session bootstrap via Playwright and HTTP-first tool execution. Uses stdio transport — runs as a local subprocess managed by Claude Desktop, Cursor, or any MCP-compatible client.
Stack
TypeScript — strict, ESM (NodeNext)
@modelcontextprotocol/sdk — MCP server + stdio transport
Playwright — interactive SSO login and session persistence
Zod — config and tool input validation
Axios — Jira REST API HTTP client
Features
🔐 SSO authentication via Playwright (headed browser)
💾 Persistent local session (Playwright storage state / cookies)
🔍
jira_get_issue— fetch a single issue by key🔎
jira_search_issues— execute JQL and return a compact issue list🔎
jira_smart_search— search by issue key, JQL, or natural-language filters⏱️
jira_add_worklog— log work on a Jira issue through Tempo Timesheets📝
jira_create_issue— create an issue using issue-type-specific required and optional fields💬
jira_add_comment— add plain-text or ADF comments to an issue✏️
jira_update_comment/jira_delete_comment— update or remove issue comments🔄
jira_transition_issue— move an issue through workflow transitions by id or name🧭
jira_get_create_meta— inspect static create metadata fromsrc/jira/constants.ts🧭
jira_get_edit_meta— inspect live editable fields for one issue✏️
jira_update_issue_fields— update a curated set of Jira fields safely🛡️
jira_validate_issue_update— validate update payloads without writing🛡️
jira_bulk_update_issue_fields/jira_bulk_transition_issues— bulk operations with explicitdryRun🛡️
jira_preview_create_issue— build create payloads without POSTing🧾
jira_get_audit_context— compact issue audit context for LLM review🔗
jira_link_issues— create links between issues🔗
jira_get_issue_links/jira_bulk_link_issues— inspect or create multiple issue links🧩
jira_get_subtasks/jira_create_subtask— inspect or create sub-tasks🧬
jira_clone_issue— clone an issue with optional field overrides👤
jira_assign_issue— assign issues by name or key👥
jira_find_user— search Jira users for assignment/collaboration flows📋
jira_get_transitions— list currently available transitions for an issue📅
jira_get_my_worklogs— list the authenticated user's Tempo worklogs📅
jira_update_worklog/jira_delete_worklog— correct or remove Tempo worklogs📎
jira_add_attachment— upload workspace files as issue attachments📤
jira_upload_attachment_content— attach AI-generated content (text, CSV, JSON…) directly without a local file🗂️
jira_get_projects/jira_get_components/jira_get_priorities— discover common Jira metadata🛡️ Clean
SESSION_EXPIRED/AUTH_REQUIREDerrors with reauthentication hints🖥️ Three CLI utilities for session management
Requirements
Node.js >= 20
Access to an internal Jira 8 instance (SSO)
Quick Start (End Users)
No cloning or building required. Install via npm or use
npxdirectly.
Step 1 — Install Playwright Chromium
Required once for the SSO browser login flow:
npx -y playwright install chromiumStep 2 — Authenticate with Jira
You must provide your Jira URL when logging in. Replace the URL with your actual Jira instance:
JIRA_BASE_URL=https://jira.yourcompany.com npx -y -p @cuongph.dev/jira-mcp jira-auth-loginA browser window will open. Complete your SSO login manually. The session is saved locally to .jira/session.json (or ~/.jira/jira-mcp/session.json for global npx usage).
Verify the session is active:
JIRA_BASE_URL=https://jira.yourcompany.com npx -y -p @cuongph.dev/jira-mcp jira-auth-checkStep 3 — Add to your MCP client
No separate server process needed — the MCP client spawns and manages the process automatically via stdio.
Gemini CLI
gemini mcp add jira npx -y @cuongph.dev/jira-mcp --env JIRA_BASE_URL=https://jira.yourcompany.comCursor
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json in your project:
{
"mcpServers": {
"jira": {
"command": "npx",
"args": ["-y", "@cuongph.dev/jira-mcp"],
"env": {
"JIRA_BASE_URL": "https://jira.yourcompany.com"
}
}
}
}Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"jira": {
"command": "npx",
"args": ["-y", "@cuongph.dev/jira-mcp"],
"env": {
"JIRA_BASE_URL": "https://jira.yourcompany.com"
}
}
}
}Tip: You can omit the
envblock and placeJIRA_BASE_URL=https://jira.yourcompany.comin a.envfile at your working directory instead.dotenvis loaded automatically at startup.
Restart your MCP client after saving the config.
Session Management
Command | Description |
| Launch SSO browser flow and save session |
| Validate whether the stored session is alive |
| Remove the stored session file |
Development Setup
For contributors and developers working on the source code.
1. Clone and install
git clone <repo-url>
cd jira-run-mcp
npm install2. Install Playwright browsers
npx playwright install chromium3. Configure environment
cp .env.example .envEdit .env:
JIRA_BASE_URL=https://jira.yourcompany.comSee .env.example for all available options.
4. Authenticate
npm run jira-auth-loginA browser window will open. Complete the SSO login manually. Session is saved to .jira/session.json.
npm run jira-auth-check5. Build
npm run build6. Add to MCP client (local build)
Use the local dist/server.js instead of the npm package:
Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"jira": {
"command": "node",
"args": ["/absolute/path/to/jira-run-mcp/dist/server.js"]
}
}
}Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"jira": {
"command": "node",
"args": ["/absolute/path/to/jira-run-mcp/dist/server.js"]
}
}
}The
.envfile in the project root is loaded automatically — no need to duplicate env vars in the MCP config.
CLI Utilities (dev)
Command | Description |
| Launch SSO browser flow and save session |
| Validate whether the stored session is alive |
| Remove the stored session file |
MCP Tools
jira_get_issue
Fetch a single Jira issue by key.
Input:
Field | Type | Description |
|
| Jira issue key, e.g. |
Output: Key, summary, description, status, assignee, reporter, priority, issue type, created/updated timestamps, URL.
jira_search_issues
Execute a JQL query and return a compact issue list.
Input:
Field | Type | Description |
|
| JQL query, e.g. |
|
| Max results (1–50, default 10) |
Output: Total count + list of issues (key, summary, status, assignee, priority, updated, URL).
jira_smart_search
Search by issue key, explicit JQL, or natural-language filters.
Input:
Field | Type | Description |
|
| Issue key, JQL, or natural-language text, e.g. |
|
| Optional: |
|
| Optional Jira project key, e.g. |
|
| Max results (1-50, default 10) |
Output: Direct issue lookup or compact search results with generated/executed JQL.
jira_create_issue
Create a Jira issue for a specific issue type.
Input:
Field | Type | Description |
|
| Jira issue type ID from |
|
| Jira create fields keyed by standard field names or |
Output: Confirmation with created issue key, summary, issue type, and browser URL.
jira_add_worklog
Log work on a Jira issue through Tempo Timesheets.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Duration using |
|
| Optional work date in |
|
| Optional worklog comment |
|
| Optional Tempo Process attribute |
|
| Optional Tempo Type Of Work attribute |
Output: Confirmation with issue details, worker, date, duration, and Tempo worklog IDs.
jira_add_comment
Add a comment to a Jira issue.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Comment body as plain text or raw ADF |
Output: Confirmation with comment id and browser URL.
jira_transition_issue
Transition a Jira issue to a target workflow state.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Optional Jira workflow transition id |
|
| Optional transition name resolved from current available transitions |
|
| Optional plain text or ADF comment |
|
| Optional curated field updates sent with the transition |
Provide exactly one of transitionId or transitionName.
Output: Confirmation with issue key, transition id, and browser URL.
jira_get_create_meta
Return static create metadata for supported Jira issue types.
Input:
Field | Type | Description |
|
| Optional issue type id to narrow the result |
Output: Required fields, optional fields, and known option sets from src/jira/constants.ts.
jira_get_edit_meta
Return live editable fields for a specific issue.
Input:
Field | Type | Description |
|
| Jira issue key |
Output: Field IDs, labels, required flags, schema types, and allowed values returned by Jira.
jira_update_issue_fields
Update a curated set of fields on an existing issue.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Curated set of updateable field ids/values |
Output: Confirmation with updated field ids and browser URL.
jira_validate_issue_update
Validate an issue update without writing.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Curated update fields to validate |
Output: Validation status, normalized update payload, and any fields not editable according to live edit metadata.
jira_bulk_update_issue_fields
Update fields on multiple issues with explicit dry-run control.
Input:
Field | Type | Description |
|
| Required. |
|
| 1-25 items with |
Output: Per-issue status table. Later items continue after per-issue failures.
jira_bulk_transition_issues
Transition multiple issues with explicit dry-run control.
Input:
Field | Type | Description |
|
| Required. |
|
| 1-25 items with |
Output: Per-issue status table with resolved transition ids. Later items continue after per-issue failures.
jira_preview_create_issue
Build and validate a create issue payload without sending it to Jira.
Input:
Field | Type | Description |
|
| Jira issue type ID from |
|
| Jira create fields keyed by standard field names or |
Output: Normalized Jira create payload JSON.
jira_get_audit_context
Fetch compact context for LLM review of one issue.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Include recent comments, default true |
|
| Max comments, 1-100, default 20 |
Output: Issue summary, key fields, description, issue links, subtasks, and optional comments.
jira_link_issues
Create a Jira issue link between two issues.
Input:
Field | Type | Description |
|
| Source issue key |
|
| Target issue key |
|
| Jira link type name |
|
| Optional plain text or ADF comment |
Output: Confirmation with issue keys, link type, and link id.
jira_get_issue_links
List issue links for a Jira issue.
Input:
Field | Type | Description |
|
| Jira issue key |
Output: Link direction, type, relationship, linked issue key, summary, and status.
jira_get_subtasks
List subtasks for a Jira issue.
Input:
Field | Type | Description |
|
| Parent Jira issue key |
Output: Subtask key, summary, status, assignee, priority, and URL.
jira_create_subtask
Create a subtask under a parent issue.
Input:
Field | Type | Description |
|
| Parent Jira issue key |
|
| Jira subtask issue type id for the project |
|
| Jira create fields; |
Output: Confirmation with parent key, created subtask key, and browser URL.
jira_clone_issue
Clone an issue by copying core fields.
Input:
Field | Type | Description |
|
| Source Jira issue key |
|
| Optional prefix, default |
|
| Optional field overrides for the created issue |
Output: Confirmation with source key, cloned issue key, and browser URL.
jira_bulk_link_issues
Create multiple issue links sequentially.
Input:
Field | Type | Description |
|
| 1-25 link requests with |
Output: Per-link status table. If one link fails, later links are still attempted and the MCP result is marked as an error.
jira_assign_issue
Assign a Jira issue to a user.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Optional Jira username/name |
|
| Optional Jira internal user key |
Output: Confirmation with assignee and browser URL.
jira_find_user
Search Jira users for assignment and collaboration flows.
Input:
Field | Type | Description |
|
| Username, display name, or search text |
|
| Max results (1-50, default 10) |
Output: Display name, username, user key, active flag, and email if Jira exposes it.
jira_get_transitions
List the currently available workflow transitions for an issue.
Input:
Field | Type | Description |
|
| Jira issue key |
Output: Transition ids, names, and destination statuses.
jira_update_comment
Update an existing issue comment.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Jira comment id |
|
| Replacement body as plain text or raw ADF |
Output: Confirmation with issue key, comment id, and browser URL.
jira_delete_comment
Delete an issue comment by id.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Jira comment id |
Output: Confirmation with issue key and deleted comment id.
jira_get_my_worklogs
List the authenticated user's Tempo worklogs.
Input:
Field | Type | Description |
|
| Optional start date in |
|
| Optional end date in |
Output: Tempo worklog ids, issue keys, dates, durations, and comments.
jira_update_worklog
Update a Tempo worklog by id.
Input:
Field | Type | Description |
|
| Tempo worklog id |
|
| Optional duration using |
|
| Optional date in |
|
| Optional updated comment |
|
| Optional Tempo Process attribute |
|
| Optional Tempo Type Of Work attribute |
Output: Confirmation with updated Tempo id, issue key, date, and duration.
jira_delete_worklog
Delete a Tempo worklog by id.
Input:
Field | Type | Description |
|
| Tempo worklog id |
Output: Confirmation with deleted Tempo id.
jira_add_attachment
Upload a local file from the allowed workspace directory to an issue.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Path to a file inside the |
Files outside the configured ATTACHMENT_WORKSPACE are rejected. Set the env var to restrict the allowed root directory.
Output: Uploaded attachment ids, filenames, sizes, and issue URL.
jira_upload_attachment_content
Upload in-memory content as a Jira issue attachment — no local file needed.
Input:
Field | Type | Description |
|
| Jira issue key |
|
| Filename with extension, e.g. |
|
| Plain text (utf8) or base64-encoded content |
|
| Default |
|
| Optional MIME type override; inferred from extension if omitted |
Output: Uploaded attachment id, filename, size, MIME type, and issue URL.
jira_get_projects
List Jira projects visible to the authenticated user.
Input: none.
Output: Project keys, names, ids, and browser URLs.
jira_get_components
List components for a Jira project.
Input:
Field | Type | Description |
|
| Jira project key |
Output: Component ids, names, and descriptions.
jira_get_priorities
List Jira priorities configured in the instance.
Input: none.
Output: Priority ids, names, and descriptions.
Project Structure
src/
├── server.ts # MCP server entry point
├── config.ts # Env var validation (Zod)
├── errors.ts # Typed error classes & factories
├── types.ts # Shared TypeScript types
├── auth/
│ ├── session-store.ts # Read/write/clear session.json
│ ├── session-manager.ts # Session validation against Jira
│ └── playwright-auth.ts # Headed SSO browser flow
├── jira/
│ ├── endpoints.ts # URL builders (REST API v2)
│ ├── mappers.ts # Raw payload → typed output shapes
│ ├── adf.ts # ADF type interfaces + low-level builders
│ ├── body-normalizer.ts # normalizeJiraBody (markdown/plain/adf → ADF)
│ ├── markdown-to-adf.ts # Markdown AST → ADF converter (remark)
│ ├── create-meta.ts # Static issue create metadata helpers
│ ├── create-issue.ts # Create-issue validation and payload helpers
│ ├── edit-meta.ts # Live issue edit metadata normalization
│ ├── user-search.ts # User search normalization
│ ├── transition-resolution.ts # Transition name resolution
│ ├── update-issue.ts # Curated field update normalization
│ └── http-client.ts # Cookie-authenticated Jira HTTP client
├── tools/
│ ├── add-attachment.ts # jira_add_attachment handler
│ ├── add-comment.ts # jira_add_comment handler
│ ├── bulk-link-issues.ts # jira_bulk_link_issues handler
│ ├── clone-issue.ts # jira_clone_issue handler
│ ├── create-subtask.ts # jira_create_subtask handler
│ ├── get-issue.ts # jira_get_issue handler
│ ├── get-issue-links.ts # jira_get_issue_links handler
│ ├── get-subtasks.ts # jira_get_subtasks handler
│ ├── find-user.ts # jira_find_user handler
│ ├── get-components.ts # jira_get_components handler
│ ├── get-create-meta.ts # jira_get_create_meta handler
│ ├── get-edit-meta.ts # jira_get_edit_meta handler
│ ├── get-my-worklogs.ts # jira_get_my_worklogs handler
│ ├── get-priorities.ts # jira_get_priorities handler
│ ├── get-projects.ts # jira_get_projects handler
│ ├── get-transitions.ts # jira_get_transitions handler
│ ├── link-issues.ts # jira_link_issues handler
│ ├── assign-issue.ts # jira_assign_issue handler
│ ├── delete-comment.ts # jira_delete_comment handler
│ ├── delete-worklog.ts # jira_delete_worklog handler
│ ├── search-issues.ts # jira_search_issues handler
│ ├── smart-search.ts # jira_smart_search handler
│ ├── add-worklog.ts # jira_add_worklog handler
│ ├── transition-issue.ts # jira_transition_issue handler
│ ├── update-comment.ts # jira_update_comment handler
│ ├── update-issue-fields.ts # jira_update_issue_fields handler
│ ├── update-worklog.ts # jira_update_worklog handler
│ └── create-issue.ts # jira_create_issue handler
├── cli/
│ ├── auth-login.ts # jira-auth-login entry point
│ ├── auth-check.ts # jira-auth-check entry point
│ └── auth-clear.ts # jira-auth-clear entry point
└── tests/ # Unit tests (Vitest)Authentication Flow
Operator
│
▼
npm run jira-auth-login
│
├── Playwright opens browser (headed)
├── Operator completes SSO manually
├── storageState saved → .jira/session.json
└── Session validated immediately
MCP Tool Call
│
├── Load .jira/session.json
├── Validate against /rest/api/2/myself
├── Extract cookies → build HTTP request
└── Return normalized Jira data
Session Expired?
│
└── Returns [SESSION_EXPIRED] error
→ "Run: npm run jira-auth-login"Development Commands
# Type check
npx tsc --noEmit
# Run tests
npm test
# Watch mode
npm run test:watch
# Build for production
npm run build
# Run directly (dev mode, reads .env)
npm run devTesting with MCP Inspector
MCP Inspector is the official GUI tool for interactively testing MCP servers — call tools, inspect inputs/outputs, and debug without an AI client.
Option A — dev mode (no build required):
npx @modelcontextprotocol/inspector tsx src/server.tstsx compiles TypeScript on-the-fly. Changes are picked up on every Inspector session restart without a rebuild step.
Option B — built bundle:
npm run build
npx @modelcontextprotocol/inspector node dist/server.jsBoth options read the .env file in the project root automatically.
After the Inspector starts, open the URL it prints (usually http://localhost:5173) in your browser, select a tool from the sidebar, fill in the inputs, and click Run.
Error Codes
Code | Meaning |
| No session file found — run |
| Session exists but Jira rejected it — rerun |
| Unexpected HTTP error from Jira REST API |
| Jira returned an unexpected response shape |
| Invalid or missing environment variable |
| Tool input or issue-type-specific field set is invalid |
Security Notes
.envand.jira/session.jsonare git-ignored and must never be committed.Session cookies give full Jira access as the authenticated user — treat them like passwords.
The session file is stored locally only; no remote storage is involved.
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cuongph-dev-work/jira8_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server