Manage JIRA tickets, boards, sprints, and backlog directly from Kiro chat sessions via MCP (Model Context Protocol).
Works with any JIRA instance (Cloud or Server) and any project — fully configured via environment variables.
This power exposes 24 MCP tools for interacting with the JIRA REST API v2:
- Query: View tickets, search with JQL, list your open/recent work, browse backlog/sprint
- Mutate: Create tickets, update fields (including epic link, story points, and arbitrary custom fields), transition status, add comments, link tickets
- Board/Sprint: List boards and sprints, list sprint issues, move tickets between sprints
- Versions: Create, list, update, release, and delete project versions (fixVersions)
- Report: Status and component summaries
| Tool | Purpose |
|---|---|
jira_view |
View a ticket with full details (description, comments, links, epic link) |
jira_search |
Search tickets using JQL |
jira_my_open |
List your currently open tickets |
jira_backlog |
List project backlog by priority |
jira_my_recent |
List your recently updated tickets |
jira_my_summary |
Summary of your assigned tickets grouped by status |
jira_sprint |
List current sprint tickets |
jira_create |
Create a new ticket (supports epic link, story points, custom fields) |
jira_update |
Update ticket fields (priority, assignee, labels, epic link, story points, custom fields) |
jira_transitions |
List available status transitions for a ticket |
jira_transition |
Move a ticket to a new status |
jira_comment |
Add a comment to a ticket |
jira_link |
Link two tickets together |
jira_boards |
List project Scrum/Kanban boards |
jira_sprints |
List active/future sprints for a board |
jira_sprint_issues |
List issues in a specific sprint |
jira_move_to_sprint |
Move a ticket into a sprint |
jira_status_summary |
Count open issues grouped by status |
jira_component_summary |
Count open issues grouped by component |
jira_create_version |
Create a new project version (fixVersion) |
jira_list_versions |
List project versions |
jira_release_version |
Mark a version as released |
jira_update_version |
Update a version's metadata |
jira_delete_version |
Delete (or archive) a version |
- Python 3.11+
- uvx (from the
uvpackage manager) - JIRA Personal Access Token with read/write access to your project
The power is fully self-contained — the MCP server lives at server/jira_mcp.py inside this directory. No external project scripts are needed.
All configuration is via environment variables — no JIRA instance or project is hardcoded:
| Environment Variable | Required | Description |
|---|---|---|
JIRA_PAT |
Yes | Personal access token for authentication |
JIRA_BASE_URL |
Yes | JIRA instance URL (e.g., https://jira.example.com) |
JIRA_PROJECT |
Yes | Default project key (e.g., MYPROJ, TEAM) |
Atlassian Cloud:
export JIRA_PAT="your-api-token"
export JIRA_BASE_URL="https://yourcompany.atlassian.net"
export JIRA_PROJECT="PROJ"JIRA Server (self-hosted):
export JIRA_PAT="your-personal-access-token"
export JIRA_BASE_URL="https://jira.internal.company.com"
export JIRA_PROJECT="OPS"Multiple projects: Install the power once, then switch projects by changing JIRA_PROJECT in the mcp.json env block. Or create multiple MCP server entries with different env configs.
git clone https://github.com/revagomes/kiro-power-jira.git
cd kiro-power-jiraAdd to your shell profile (~/.bashrc, ~/.zshrc, etc.):
export JIRA_PAT="your-personal-access-token"
export JIRA_BASE_URL="https://jira.example.com"
export JIRA_PROJECT="MYPROJ"To generate a PAT:
- JIRA Server: Profile → Personal Access Tokens → Create
- Atlassian Cloud: Account Settings → Security → API Tokens → Create
Edit mcp.json and replace the path with your local clone location:
{
"mcpServers": {
"jira": {
"command": "uvx",
"args": ["--from", "fastmcp", "fastmcp", "run", "/path/to/kiro-power-jira/server/jira_mcp.py"],
"env": {
"JIRA_PAT": "${env:JIRA_PAT}",
"JIRA_BASE_URL": "${env:JIRA_BASE_URL}",
"JIRA_PROJECT": "${env:JIRA_PROJECT}"
}
}
}
}Add to ~/.kiro/powers/registries/user-added.json inside the "powers" array:
{
"name": "jira",
"description": "JIRA ticket management via MCP",
"source": {
"type": "local",
"path": "/path/to/kiro-power-jira"
},
"autoInstall": false
}Add to ~/.kiro/powers/installed.json under "installedPowers":
{
"name": "jira",
"registryId": "user-added"
}# Test the server starts (set env vars first)
export JIRA_PAT="test" JIRA_BASE_URL="https://jira.example.com" JIRA_PROJECT="TEST"
uvx --from fastmcp fastmcp inspect /path/to/kiro-power-jira/server/jira_mcp.pyExpected output: Tools: 24
Then restart Kiro — the power should appear in the powers list.
Once installed, just talk naturally in your Kiro session:
"What's PROJ-1234 about?"
"Show me my open tickets"
"Find all P1 bugs"
"Move PROJ-1234 to In Progress"
"Create a bug for the broken pagination"
"What's in the current sprint?"
"Post a comment on PROJ-1234 with the MR link"
"How's the project status?"
jira_create and jira_update support fields beyond the built-in ones (priority,
assignee, labels, etc.) without falling back to the raw REST API.
"Create a task 'Refactor auth' under epic PROJ-100"
→ jira_create(summary="Refactor auth", epic_link="PROJ-100")
"Move PROJ-1234 under epic PROJ-100"
→ jira_update(ticket="PROJ-1234", epic_link="PROJ-100")
The instance's "Epic Link" custom field id is resolved by name at runtime and cached —
nothing is hard-coded, so this works across instances. jira_view now returns an
epic_link field so you can confirm the assignment. On team-managed / next-gen projects
(which have no "Epic Link" field and use the native parent field instead), the tool
raises a clear error explaining the alternative.
→ jira_create(summary="Add pagination", story_points=5)
→ jira_update(ticket="PROJ-1234", story_points=8)
For any other instance-specific field, pass a custom_fields map keyed by human field
name (resolved at runtime) or by raw customfield_* id:
→ jira_create(summary="…", custom_fields={"Story Points": 5, "Team": {"value": "Platform"}})
→ jira_update(ticket="PROJ-1234", custom_fields={"customfield_12345": "value"})
Notes:
- Value shape is passthrough. Each value must match JIRA's expected write schema for
that field (e.g. epic link → bare key string; single-select →
{"value": "…"}; number fields → a number). The tool resolves the field id but does not reshape values. - Typed parameters win. If a field is set both by a named parameter (e.g.
priority) and viacustom_fields, the named parameter takes precedence; the ignored key is reported back in the result underignored_custom_fields. - Unknown field names fail loudly, listing available field names, rather than silently doing nothing.
jira_link defaults to the JIRA-standard link type "Relates". If your instance names
the type differently (some use "Related"), an unknown type no longer returns a raw HTTP
404 — instead the tool lists the valid link-type names for your instance so you can retry
with the correct one.
To manage multiple JIRA projects simultaneously, add multiple server entries in your ~/.kiro/settings/mcp.json:
{
"mcpServers": {
"jira-frontend": {
"command": "uvx",
"args": ["--from", "fastmcp", "fastmcp", "run", "/path/to/server/jira_mcp.py"],
"env": {
"JIRA_PAT": "${env:JIRA_PAT}",
"JIRA_BASE_URL": "${env:JIRA_BASE_URL}",
"JIRA_PROJECT": "FRONT"
}
},
"jira-backend": {
"command": "uvx",
"args": ["--from", "fastmcp", "fastmcp", "run", "/path/to/server/jira_mcp.py"],
"env": {
"JIRA_PAT": "${env:JIRA_PAT}",
"JIRA_BASE_URL": "${env:JIRA_BASE_URL}",
"JIRA_PROJECT": "BACK"
}
}
}
}The power uses FastMCP to expose Python functions as MCP tools over stdio transport. Each tool maps to one or more JIRA REST API v2 endpoints:
- Read operations use
GET /rest/api/2/issue,/search,/transitions - Write operations use
POST /rest/api/2/issue,/comment,/issueLink - Update operations use
PUT /rest/api/2/issue - Agile operations use
GET/POST /rest/agile/1.0/board,/sprint
Authentication is via Bearer token (JIRA_PAT). All requests are made server-side — no credentials are exposed to the agent or chat context.
kiro-power-jira/
├── POWER.md ← Power manifest (frontmatter + instructions for Kiro)
├── mcp.json ← MCP server configuration
├── server/
│ ├── jira_mcp.py ← Self-contained MCP server (FastMCP + JIRA REST API)
│ └── run.sh ← Launcher script (resolves own path, runs from anywhere)
├── steering/
│ ├── jira-workflow.md ← Ticket lifecycle workflow guidance
│ └── jira-lookup.md ← Ticket query and search patterns
├── .gitignore
├── LICENSE
└── README.md ← This file
| Problem | Solution |
|---|---|
| "Missing required environment variable(s)" | Set JIRA_PAT, JIRA_BASE_URL, and JIRA_PROJECT |
| 401 Unauthorized | Token expired — regenerate in JIRA profile |
| 403 Forbidden | Your token lacks permissions — check project role |
| Connection timeout | Ensure network/VPN access to your JIRA instance |
| Server won't start | Run uvx --from fastmcp fastmcp inspect server/jira_mcp.py |
| "Transition not available" | Use jira_transitions first to see available options |
| Tools not showing in Kiro | Verify installed.json entry and restart Kiro |
The server ships with an offline test suite (no live JIRA instance or network required).
Tests mock the HTTP layer at the _api_request seam, and the module skips .env
bootstrap when _JIRA_MCP_SKIP_ENV=1 is set (handled by the test fixtures).
# Create an isolated environment and install runtime + dev dependencies
uv venv .venv
uv pip install --python .venv fastmcp pytest pytest-cov
# Run the suite
.venv/bin/python -m pytest server/tests/ -q
# With coverage for the server module
.venv/bin/python -m pytest server/tests/ --cov=jira_mcp --cov-report=term-missingThe field-coverage features (epic_link, story_points, custom_fields, the
jira_link unknown-type handling, and runtime field-id resolution) are fully covered.
The lower overall percentage reflects pre-existing tools that predate the test suite.
- Fork the repository
- Create a feature branch (
git checkout -b feature/add-watchers-tool) - Add your tool to
server/jira_mcp.py— follow the@mcp.tool()pattern - Test with
uvx --from fastmcp fastmcp inspect server/jira_mcp.py - Update the tools table in
POWER.mdandREADME.md - Submit a pull request
This project is licensed under the GNU General Public License v2.0 or later (GPL-2.0-or-later). See LICENSE for the full text.