About JIRA MCP Server
JIRA MCP Server lets AI clients read and update Jira issues, sprint tickets, and Atlassian notifications. It also supports issue linking, child issues, attachments, and file-based content editing with version checks to help prevent conflicting updates.
Key features
- 01List active sprint tickets and issue details
- 02Add comments and update descriptions
- 03Link issues and manage child issues
- 04Upload attachments and embed files
- 05Read and filter Atlassian notifications
- 06Check content versions before updates
Use cases
- 01Review tickets in an active sprint
- 02Update issue content from local files
- 03Track blockers by linking related issues
- 04Read or mark selected notifications as read
MCP support
Provides MCP tools for interacting with Jira using the configured Jira host, email, and API token. MCP clients can retrieve and modify issues, manage attachments and links, and access notifications.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
We haven’t collected a package or remote endpoint for this server. Follow the instructions in the project README.
Tools
Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.
Details
From the project READMEJIRA MCP Server
This is a Model Context Protocol (MCP) server that provides tools for interacting with JIRA. It allows you to fetch tickets from active sprints and get detailed ticket information through the MCP interface.
Features
The server provides the following tools:
-
list-sprint-tickets: Gets all tickets in the active sprint for a given project- Required parameter:
projectKey(string)
- Required parameter:
-
get-ticket-details: Gets detailed information about a specific ticket- Required parameter:
issueKey(string)
- Required parameter:
-
add-comment: Adds a comment to a specific ticket- Required parameter:
issueKey(string) - Either
comment(string) orfilePath(string) — see Editing content from a file - Optional parameter:
commentFormat—plain(default),wiki,markdownoradf
- Required parameter:
-
link-issues: Links every outward issue to every inward issue, read as "outward blocks inward"- Required parameters:
outwardIssueKeys,inwardIssueKeys(string arrays) — withlinkType: "Blocks", the outward keys are the blockers - Optional parameter:
linkType— the type's name (Blocks, or3. Blockson sites that number them) or its inward/outward description; defaults toRelates.unlink-issuesaccepts the same values. - Results are reported in words, e.g.
PROJ-1 blocks PROJ-2
- Required parameters:
-
update-description: Updates the description of a specific ticket- Required parameter:
issueKey(string) - Either
description(string) orfilePath(string) — see Editing content from a file - Optional parameter:
descriptionFormat—plain(default),wiki,markdownoradf
- Required parameter:
-
list-child-issues: Gets all child issues of a parent ticket- Required parameter:
parentKey(string)
- Required parameter:
-
create-sub-ticket: Creates a sub-ticket (child issue) for a parent ticket- Required parameter:
parentKey(string) - Required parameter:
summary(string) - Optional parameter:
description(string) orfilePath(string) — see Editing content from a file - Optional parameter:
issueType(string) - The name of the sub-task issue type (e.g., 'Sub-task')
- Required parameter:
-
add-attachment: Uploads local files as attachments to a ticket- Required parameter:
issueKey(string) - Required parameter:
filePaths(string array) — every path is checked before any upload, so a bad path uploads nothing
- Required parameter:
-
notifications: Reads your Atlassian notifications (the bell icon), newest first- Optional parameter:
since/until— an ISO date/time (2026-10-01,2026-10-01T09:00:00Z) or a duration back from now (30m,24h,7d,2w) - Optional parameter:
limit(number) — default 20, max 100 - Optional parameter:
unreadOnly(boolean),category(directorwatching),product(e.g.jira,confluence) - Optional parameter:
ids(string array) — return only these notifications (theID:line of each result); the other filters andlimitare ignored - Optional parameter:
markAsRead(boolean, defaultfalse) — marks the returned unread notifications as read, soids+markAsReadmarks exactly those; grouped notifications are marked as a whole. The API has no way to delete or dismiss a notification. - Notifications come from the Atlassian GraphQL gateway (
/gateway/api/graphql), which accepts the same API token. The feed is requested for the site inJIRA_HOST(its cloud ID is read from the public/_edge/tenant_info); without that routing the gateway returns only platform-wide admin notices.
- Optional parameter:
Setup
-
Install dependencies:
npm install -
Build the TypeScript code:
This step is only needed for Cline on Windows, which currently has an issue executing npx
npm run build
- Configure the MCP settings in your Claude app settings file (usually located at
~/Library/Application Support/Claude/claude_desktop_config.jsonon macOS or%APPDATA%/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.jsonon Windows):
Settings for Claude:
{
"mcpServers": {
"jira": {
"command": "npx",
"args": ["path/to/this/repo/jira.ts"],
"env": {
"JIRA_HOST": "https://your-domain.atlassian.net",
"JIRA_EMAIL": "[email protected]",
"JIRA_API_TOKEN": "your-api-token"
}
}
}
}
Settings for Cline:
{
"mcpServers": {
"jira": {
"command": "node",
"args": ["path/to/this/repo/dist/jira.js"],
"env": {
"JIRA_HOST": "https://your-domain.atlassian.net",
"JIRA_EMAIL": "[email protected]",
"JIRA_API_TOKEN": "your-api-token"
}
}
}
}
Configuration
You'll need to set up the following environment variables in your MCP settings:
JIRA_HOST: Your Atlassian domain URL (e.g.,https://your-company.atlassian.net)JIRA_EMAIL: Your JIRA account emailJIRA_API_TOKEN: Your JIRA API token- You can generate an API token from your Atlassian Account Settings
Usage
Once configured, you can use the tools through the MCP interface in Claude:
List Sprint Tickets
To get all tickets in the active sprint for a project:
<use_mcp_tool>
<server_name>jira</server_name>
<tool_name>list-sprint-tickets</tool_name>
<arguments>
{
"projectKey": "YOUR_PROJECT_KEY"
}
</arguments>
</use_mcp_tool>
Get Ticket Details
To get detailed information about a specific ticket:
<use_mcp_tool>
<server_name>jira</server_name>
<tool_name>get-ticket-details</tool_name>
<arguments>
{
"issueKey": "PROJECT-123"
}
</arguments>
</use_mcp_tool>
Editing content from a file
update-description, update-comment, add-comment, create-ticket and create-sub-ticket
accept filePath instead of inline text. This is meant for long content: keep the source in a
file, edit that file, and re-send — no need to repost the whole body through the tool call each
time. On the two create tools the description stays optional, so omitting both is still fine.
The format is inferred from the extension, so descriptionFormat / commentFormat can be
omitted:
| Extension | Format | Content |
|---|---|---|
.md, .markdown | markdown | Markdown (## headings, **bold**) |
.wiki, .jira | wiki | Jira wiki markup (h2., {code}) |
.json, .adf | adf | Raw Atlassian Document Format JSON |
.txt, .text | plain | Plain text, wrapped in a paragraph |
Passing the format explicitly overrides the extension, which is also how to use a file with any other extension. Paths are absolute or relative to the server's working directory.
{
"issueKey": "PROJECT-123",
"filePath": "/abs/path/to/description.md"
}
An empty file is rejected rather than wiping the existing description or comment, and passing
both the inline text and filePath is an error.
Markdown constructs that end up empty — a table cell (header or body), a list item, a
blockquote, a fenced code block — are repaired into valid ADF before sending. Jira's validator
refuses an empty tableHeader / tableCell / listItem / blockquote with a bare
400 INVALID_INPUT that names the field (errors.comment) and not the offending node, so
without this repair the whole comment looks rejected while a single empty cell is at fault.
Patching existing content
To change part of a description or comment that already exists, export it first with
export-content, edit the file, and re-upload it — no need to rewrite the whole thing:
{ "issueKey": "PROJECT-123", "commentId": "54660", "filePath": "/tmp/pir-timeline.md" }
The export reports whether that content is safe to re-upload as markdown. Jira stores content
as ADF, and constructs such as panels, mentions, status lozenges, media, tables, task lists and
expands have no markdown equivalent — re-uploading markdown would silently drop them. When any
are present the tool warns and lists them; export with "format": "adf" instead and patch the
JSON, which always round-trips exactly (.json files are recognised as ADF on upload).
Omit filePath to get the content back inline instead of writing a file. Comment IDs are shown
by get-ticket-details.
Content versions (optimistic concurrency)
update-description and update-comment require expectedVersion whenever the content being
replaced is not empty: the version the edit was based on. If the content changed in Jira since,
the update is refused instead of silently discarding that change — the same lock Confluence gets
from its page version numbers.
Jira has no version number of its own, and an issue's updated timestamp is not a substitute:
it moves for any change to the issue, so transitions, labels and new comments would all reject
description patches that never conflicted. The version is therefore a hash of the content
itself (v1-…), so it changes exactly when the thing being patched changes.
Versions come from export-content and from get-ticket-details, which reports
Description version: and a version: for every comment — so a small inline edit needs no
export round-trip.
Writing a description for the first time needs no version. Omitting expectedVersion is
itself the assertion "there is nothing here yet", which the server checks: the write goes through
when the description is still empty, and is refused — naming the version now in Jira — when
someone wrote one meanwhile. So the lock covers the first write as well, without the caller
having to fetch the version of empty content.
Pass "force": true to skip the check and overwrite regardless.
Embedding files in descriptions and comments
add-comment, update-comment, update-description, create-ticket and create-sub-ticket embed
files referenced with the image syntax of the content format:

!error.png! (wiki, image)
[^report.pdf] (wiki, file)
Each reference resolves to an issue attachment. Jira stores a file shown in a comment as an issue attachment, so comments and descriptions work the same way. References resolve in this order:
attachment:<filename or ID>embeds an attachment already on the ticket.- A local path (relative to the content file, or to the server's working directory for inline text) is uploaded. If the ticket already has an attachment with the same name and size, that attachment is reused, so re-sending an edited file does not attach the same screenshot again.
- Otherwise, an attachment already on the ticket with that filename is used.
Every reference is checked before anything is uploaded or written. A single bad reference makes
the call fail with nothing changed. Web URLs (https://…) are left as they are. Images render
inline, and other files appear as attachment links. When creating a ticket, the description is
written in a second step after the issue exists, because files can only be attached to an existing
issue.
Development
The server is written in TypeScript and uses:
@modelcontextprotocol/sdkfor MCP server implementationjira.jsfor JIRA API integration
Recommended scripts:
- Build once:
npm run build - Build and watch:
npm run build:watch - Type-check only:
npm run typecheck - Dev run with watch:
npm run start:dev - Run compiled server:
npm start - Format check:
npm run fmt:check - Format write:
npm run fmt - Unit tests:
npm test
npm test runs unit tests only. They use fake Jira clients, need no credentials, and never touch a
real Jira instance. Checks against a live Jira that create tickets, comments or attachments are run
by hand as one-off scripts and are not committed. Neither kind of test should commit details of a
real Jira instance, such as its hostname, project keys, issue keys, people's names or attachment IDs.
Typical workflow:
- Make changes to
jira.ts - Run
npm run start:devduring development, ornpm run buildthennpm startfor compiled run - Restart your MCP client if needed to pick up changes
Error Handling
The server includes error handling for:
- Invalid JIRA credentials
- Missing active sprints
- Invalid project keys or issue keys
- Network errors
Error messages will be returned in the tool response.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.