Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Atlassian Ai Toolkit

FreeNot checked

MCP server for AI assistants to interact with Atlassian Jira and Confluence Cloud APIs through typed tools and secure authentication.

GitHubEmbed

About

MCP server for AI assistants to interact with Atlassian Jira and Confluence Cloud APIs through typed tools and secure authentication.

README

AI-first SDK, CLI, and MCP server for Atlassian Jira and Confluence

A Bun monorepo containing a typed SDK, an agent-native CLI, and an MCP server for Atlassian Cloud APIs.

Packages

Package Description
@atlassian-ai-toolkit/sdk Core SDK with types, API client, and business logic
@atlassian-ai-toolkit/cli Command-line interface (Stricli)
@atlassian-ai-toolkit/mcp MCP server for AI assistants (FastMCP)

Install The CLI

Recommended: Standalone Binary

No Node.js, no npm, no PATH conflicts. One file built with Bun.

macOS and Linux:

curl -fsSL https://raw.githubusercontent.com/spenserhale/atlassian-ai-toolkit/main/scripts/install.sh | sh

The script detects your OS + architecture, downloads the matching binary from the latest release, verifies its SHA256, and installs to $HOME/.local/bin/atlassian.

Pin a version with ATLASSIAN_AI_TOOLKIT_VERSION=v0.1.0 or change the install directory with ATLASSIAN_AI_TOOLKIT_INSTALL=$HOME/bin.

Windows: download atlassian-windows-x64.exe from the latest release and put it on your PATH.

Available binaries: atlassian-linux-{x64,arm64}, atlassian-darwin-{x64,arm64}, and atlassian-windows-x64.exe.

Upgrade

Upgrade an installed binary in place from the latest GitHub release (verifies the SHA256 first):

atlassian upgrade            # apply the latest release
atlassian upgrade --dry-run  # only show current vs latest

On Windows, close running instances before upgrading, or re-download the exe from the latest release.

Shell Aliases

For shorter commands, add these aliases to your shell profile (~/.zshrc or ~/.bashrc):

alias jira='atlassian jira'
alias conf='atlassian confluence'

Then jira get PROJ-123 runs atlassian jira get PROJ-123, and conf get 123456 runs atlassian confluence get 123456.

Configure

Set Atlassian Cloud credentials in your shell:

export ATLASSIAN_SITE_URL="https://your-site.atlassian.net"
export ATLASSIAN_EMAIL="[email protected]"
export ATLASSIAN_API_TOKEN="your-api-token"

Create a scoped API token at https://id.atlassian.com/manage-profile/security/api-tokens.

Creating Issues

Create an issue with the same field semantics as jira edit: the issue type and every field are resolved against the project's own create screen, so plain values work and a bad one is rejected before the write.

# Preview the full create payload without writing
atlassian jira create --project DMP --type Bug --summary "Login times out" \
  --description-file ./repro.md --field "Task Category=Support" --field "Priority=High" --dry-run --json

# Create it, then hand the key to jira edit or jira attach
atlassian jira create --project DMP --type Bug --summary "Login times out" --json
# {"status":"created","key":"DMP-2470","id":"1234567","url":"https://your-site.atlassian.net/browse/DMP-2470", ...}

# A sub-task, or an issue under an epic
atlassian jira create --project DMP --type Sub-task --summary "Write the migration" --parent DMP-123

# A reviewed batch in one command
atlassian jira create --from-file issues.json --json

--project defaults to ATLASSIAN_JIRA_PROJECT. --type takes a display name (case-insensitive) or an id. --description / --description-file take markdown and are converted to ADF, which is what Jira's v3 API requires. Everything else goes through --field <id|name>=<value>, including priority, labels, assignee, story points, sprint, and custom fields; list fields take a comma-separated value (--field labels=audit,login) and a repeated --field is rejected rather than silently keeping the last value. An assignee given as an email address or display name is resolved to an account id.

issues.json is [{"project": "DMP", "issuetype": "Bug", "summary": "...", "fields": {...}}]. Every record is attempted, results are reported per record, and the command exits non-zero if any record failed. A record key outside that set is rejected rather than ignored, so a field value put at the top level fails loudly instead of vanishing; with --from-file, --project is the default for records that name none and the other single-issue flags are refused.

project and issuetype come from --project and --type, so passing either through --field is an error rather than a value the create would overwrite.

Rejections carry what a retry needs, so no separate metadata call is required:

code details
invalid_issue_type the project's real issue types
missing_required_field the required fields the payload left out, with their allowed values
field_not_settable the fields that issue type's create screen does accept
field_value_not_allowed the field's allowed values
invalid_parent Jira's own parent error

Creating is not destructive, so there is no --force --confirm gate. --dry-run resolves the whole payload against the create screen — including the ADF description and every coerced field — and prints it without sending, so a dry run shows exactly what the real create would write.

Editing Issue Fields

Set fields by id or display name. Values are coerced to the shape each field's schema requires, read from the issue's own edit screen, so a single-select takes Support rather than {"value":"Support"} and a number takes 2 rather than "2".

# Preview the resolved payload without writing
atlassian jira edit PROJ-123 --field "Task Category=Support" --field customfield_10105=2 --dry-run --json

# Apply the edit
atlassian jira edit PROJ-123 --field customfield_10105=2

# Apply a reviewed batch of corrections in one command
atlassian jira edit --from-file edits.json --json

Field values are coerced the same way on create and on edit: a markdown value for description or another rich-text field becomes ADF, Sprint takes a bare sprint id, parent takes an issue key, and an assignee takes an email address, display name, or account id.

edits.json is [{"key": "PROJ-123", "fields": {"Task Category": "Support", "customfield_10105": 2}}]. Each key is attempted, per-key results are reported, and the command exits non-zero if any key failed. Lists are comma-separated (--field labels=audit,sprint-close), json: passes a raw value through (--field customfield_13841=json:{"id":"14501"}), and an empty value clears a field.

Jira rejects the whole call when one field is unsettable on that issue type, so a rejected field comes back with the issue's settable fields in the error details:

{
  "status": "error",
  "code": "field_not_settable",
  "message": "\"Story Points\" is not a field that can be set on this issue",
  "details": { "field": "Story Points", "settableFields": [{ "id": "customfield_13841", "name": "Task Category", "type": "option" }] }
}

Editing is reversible from the issue history, so no --force --confirm gate applies; --dry-run validates the payload against the edit screen without sending it.

Searching And Sprint Reporting

jira search --json reports total, isLast, and startAt alongside the issues, so a truncated result is detectable rather than inferred. isLast is false when the walk stopped at --limit, and total is then Jira's approximate count for the query.

# Trim the response to the fields actually read
atlassian jira search --jql "sprint = 42 AND status = Done" --fields key,summary,status,customfield_10105 --json

# Same flag on sprint issue listing
atlassian jira sprint issues 42 --fields key,summary,status

Story point rollups are opt-in, since they cost one pass over the sprint:

atlassian jira sprint get 42 --points --json
# ... "points": { "committed": 47, "completed": 31, "field": "customfield_10105", "issueCount": 18, "unestimated": 2 }

# Reported in the close preview and result too, measured before any rollover move
atlassian jira sprint close 42 --points --issues PROJ-1,PROJ-2 --move-to-sprint 43

Completed points are those on issues whose status category is done. The story point field id varies by site: set ATLASSIAN_STORY_POINTS_FIELD, or pass --points-field customfield_10105.

Board-scoped sprint commands accept a default board, so the id does not have to be repeated:

export ATLASSIAN_JIRA_BOARD_ID=1234
atlassian jira sprint current --points --json
atlassian jira sprint list --state active
atlassian jira sprint create --name "Sprint 43" --goal "Ship search"

An explicit board (sprint current 42, --board 42) still wins over the environment; without either, the command fails with a hint to set ATLASSIAN_JIRA_BOARD_ID.

Attachments

Upload one or more files to a Jira issue. Repeat --file for multiple uploads; the stored filename is the file's basename and the MIME type is inferred from its extension.

# Attach a single file
atlassian jira attach PROJ-123 --file ./screenshot.png

# Attach several files and print the API response
atlassian jira attach PROJ-123 --file ./error.log --file ./har-capture.har --json

The MCP tool jira_add_attachment takes the same paths, plus a files array for content an agent generates inline (filename, content, encoding: utf8 | base64).

Confluence pages take one attachment per call:

atlassian confluence attachment upload --page 123456 --file ./diagram.png

Attachments must be enabled on the site, and uploads are subject to the site's maximum attachment size.

Destructive Actions

Deletes preview by default. Actual deletion requires --force and a matching --confirm value from the fetched resource.

# Preview the permanent Jira delete
atlassian jira delete PROJ-123

# Permanently delete the Jira issue
atlassian jira delete PROJ-123 --force --confirm PROJ-123

# Preview moving a Confluence page to trash
atlassian confluence delete 123456

# Move a Confluence page to trash
atlassian confluence delete 123456 --force --confirm 123456

# Permanently purge an already-trashed Confluence page
atlassian confluence delete 123456 --purge --force --confirm 123456

Sprint deletion is permanent and follows the same pattern. The preview reports how many issues the sprint holds; Jira moves its open issues to the backlog.

# Preview deleting a duplicate future sprint
atlassian jira sprint delete 5168

# Permanently delete the sprint
atlassian jira sprint delete 5168 --force --confirm 5168

Getting Started From Source

# Install dependencies
bun install

# Build all packages
bun run build

# Run the CLI
bun run dev:cli -- --help

# Run the MCP server (stdio mode for Claude Desktop)
bun run dev:mcp

The token should be scoped to the smallest set of Jira and Confluence permissions needed for the workflow. Third-party reference implementations live under refs/, which is intentionally gitignored so this repo never vendors or executes unreviewed code with local credentials.

Architecture

packages/sdk/     <-- Types, API client, business logic (foundation)
    ^       ^
    |       |
packages/cli/   packages/mcp/
    (Stricli)    (FastMCP)

Both the CLI and MCP server are thin wrappers over the SDK. If the REST API changes, you update the SDK and both consumers get the fix automatically.

Development

# Run tests across all packages
bun test

# Build a specific package
cd packages/sdk && bun run build

Adding a New API Operation

  1. Add types to packages/sdk/src/types.ts
  2. Add the client method to packages/sdk/src/client.ts
  3. Add a CLI command in packages/cli/src/commands/
  4. Add an MCP tool in packages/mcp/src/tools/

Destructive operations must default to a preview path and require an explicit --force flag in the CLI or force: true in MCP tools.

from github.com/spenserhale/atlassian-ai-toolkit

Installing Atlassian Ai Toolkit

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/spenserhale/atlassian-ai-toolkit

FAQ

Is Atlassian Ai Toolkit MCP free?

Yes, Atlassian Ai Toolkit MCP is free — one-click install via Unyly at no cost.

Does Atlassian Ai Toolkit need an API key?

No, Atlassian Ai Toolkit runs without API keys or environment variables.

Is Atlassian Ai Toolkit hosted or self-hosted?

A hosted option is available: Unyly runs the server in the cloud, no local setup required.

How do I install Atlassian Ai Toolkit in Claude Desktop, Claude Code or Cursor?

Open Atlassian Ai Toolkit on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Atlassian Ai Toolkit with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All productivity MCPs