An MCP server for Atlassian products (Confluence and Jira) built on the omniskill framework. Provides 26 tools for AI assistants to interact with Confluence pages and Jira issues.
- 📄 Confluence tools — Read, create, update, and search Confluence pages with safe handling of Storage Format (XHTML)
- 🎫 Jira tools — Search, create, update, clone, and transition issues; agile boards, sprints, and reporting
- 🔑 Shared Atlassian auth — Single
ATLASSIAN_URLcredential for both products - 🔐 OAuth 2.1 with PKCE — Serve over HTTP with authorization code flow and optional ngrok tunneling
- 🏦 Vault-backed credentials — 1Password, Bitwarden, Keeper support via omnitoken
- 🧩 Composable skills — Each product is an independent omniskill that can be used standalone or combined
| Package | Description |
|---|---|
skills/confluence |
Confluence omniskill — 8 tools for page operations |
skills/jira |
Jira omniskill — 18 tools for issue tracking, agile, and reporting |
cmd/mcp-atlassian |
MCP server binary with stdio and HTTP modes |
The underlying Confluence and Jira client libraries live in Go-Atlassian (confluence/ and jira/ packages).
go install github.com/plexusone/mcp-atlassian/cmd/mcp-atlassian@latestgo get github.com/plexusone/mcp-atlassianimport "github.com/grokify/go-atlassian/confluence/storage"
// Create a page with structured blocks
page := &storage.Page{
Blocks: []storage.Block{
&storage.Heading{Level: 1, Text: "Welcome"},
&storage.Paragraph{Text: "This is a test page."},
&storage.Table{
Headers: []string{"Name", "Status"},
Rows: []storage.Row{
{Cells: []storage.Cell{
{Text: "Service A"},
{Macro: &storage.Macro{
Name: "status",
Params: map[string]string{"colour": "Green", "title": "OK"},
}},
}},
},
},
},
}
// Render to Storage XHTML
xhtml, err := storage.Render(page)
if err != nil {
log.Fatal(err)
}
// Validate before sending to Confluence
if err := storage.Validate(xhtml); err != nil {
log.Fatal(err)
}import "github.com/grokify/go-atlassian/confluence"
// Create client
auth := confluence.BasicAuth{
Username: "user@example.com",
Token: "your-api-token",
}
client := confluence.NewClient("https://example.atlassian.net/wiki", auth)
// Get a page as structured IR
page, info, err := client.GetPageStorage(ctx, "12345")
if err != nil {
log.Fatal(err)
}
// Modify the page
page.Blocks = append(page.Blocks, &storage.Paragraph{Text: "New content"})
// Update the page
err = client.UpdatePageStorage(ctx, info.ID, page, info.Version, info.Title)# Install from GitHub
go install github.com/plexusone/mcp-atlassian/cmd/mcp-atlassian@latest
# Or build from source
go build -o mcp-atlassian ./cmd/mcp-atlassianClaude Code supports three configuration scopes. See Claude Code MCP docs for details.
User scope (~/.claude.json):
{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"ATLASSIAN_USERNAME": "user@example.com",
"ATLASSIAN_API_TOKEN": "your-api-token"
}
}
}
}Project scope (.mcp.json in project root, can be checked into source control):
{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"ATLASSIAN_USERNAME": "user@example.com",
"ATLASSIAN_API_TOKEN": "your-api-token"
}
}
}
}Enterprise managed (managed-mcp.json in system directories):
See Enterprise MCP configuration for details.
Add to your Claude Desktop settings (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"ATLASSIAN_USERNAME": "user@example.com",
"ATLASSIAN_API_TOKEN": "your-api-token"
}
}
}
}{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"OP_SERVICE_ACCOUNT_TOKEN": "ops_...",
"OMNITOKEN_VAULT_URI": "op://MyVault",
"OMNITOKEN_CREDENTIALS_NAME": "atlassian"
}
}
}
}{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"BW_ACCESS_TOKEN": "...",
"BW_ORGANIZATION_ID": "...",
"OMNITOKEN_VAULT_URI": "bw://org-id",
"OMNITOKEN_CREDENTIALS_NAME": "atlassian"
}
}
}
}{
"mcpServers": {
"atlassian": {
"command": "/path/to/mcp-atlassian",
"env": {
"ATLASSIAN_URL": "https://example.atlassian.net",
"KSM_TOKEN": "US:...",
"OMNITOKEN_VAULT_URI": "keeper://",
"OMNITOKEN_CREDENTIALS_NAME": "atlassian"
}
}
}
}Use omnitoken with vault backends for secure credential storage.
| Provider | URI Pattern | Requirements |
|---|---|---|
| 1Password | op://vault |
OP_SERVICE_ACCOUNT_TOKEN env var |
| Bitwarden | bw://org-id |
BW_ACCESS_TOKEN and BW_ORGANIZATION_ID env vars |
| Keeper | keeper:// |
KSM_TOKEN or KSM_CONFIG env var |
| File | file:///path |
None |
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
mcp-atlassian --vault op://MyVault --credentials-name atlassian \
--base-url https://example.atlassian.netexport BW_ACCESS_TOKEN="..."
export BW_ORGANIZATION_ID="..."
mcp-atlassian --vault bw://org-id --credentials-name atlassian \
--base-url https://example.atlassian.netexport KSM_TOKEN="US:..."
mcp-atlassian --vault keeper:// --credentials-name atlassian \
--base-url https://example.atlassian.net| Variable | Flag | Description |
|---|---|---|
ATLASSIAN_URL |
--base-url |
Your Atlassian instance URL (e.g., https://example.atlassian.net) |
ATLASSIAN_USERNAME |
--username |
Your Atlassian username (usually your email) |
ATLASSIAN_API_TOKEN |
--api-token |
API token from Atlassian Account Settings |
CONFLUENCE_BASE_URL |
- | Legacy: Confluence URL with /wiki suffix (falls back if ATLASSIAN_URL not set) |
OMNITOKEN_VAULT_URI |
--vault |
Vault URI for credentials |
OMNITOKEN_CREDENTIALS_NAME |
--credentials-name |
Name of credentials in vault (default: atlassian) |
OP_SERVICE_ACCOUNT_TOKEN |
- | 1Password service account token |
BW_ACCESS_TOKEN |
- | Bitwarden access token |
BW_ORGANIZATION_ID |
- | Bitwarden organization ID |
KSM_TOKEN |
- | Keeper token (format: REGION:TOKEN) |
export ATLASSIAN_URL=https://example.atlassian.net
export ATLASSIAN_USERNAME=user@example.com
export ATLASSIAN_API_TOKEN=your-api-token
./mcp-atlassianThe MCP server exposes these tools:
| Tool | Description |
|---|---|
confluence_read_page |
Read a page as structured blocks |
confluence_read_page_xhtml |
Read a page as raw Storage Format XHTML |
confluence_update_page |
Update a page with structured blocks |
confluence_update_page_xhtml |
Update a page with raw Storage Format XHTML |
confluence_create_page |
Create a new page with structured blocks |
confluence_create_table |
Create a table block from structured data |
confluence_delete_page |
Delete a page |
confluence_search_pages |
Search pages using CQL |
| Tool | Description |
|---|---|
jira_get_issue |
Get a Jira issue by key |
jira_search |
Search issues using JQL |
jira_create_issue |
Create a new issue |
jira_update_issue |
Update issue fields |
jira_add_comment |
Add a comment to an issue |
jira_get_comments |
Get comments for an issue |
jira_get_transitions |
Get available transitions |
jira_transition_issue |
Transition an issue to a new status |
jira_clone_issue |
Clone an issue with field mapping |
jira_bulk_update |
Update multiple issues at once |
jira_get_projects |
List available projects |
jira_get_boards |
List agile boards |
jira_get_sprints |
List sprints for a board |
jira_move_to_sprint |
Move issues to a sprint |
jira_velocity_report |
Sprint velocity report |
jira_burndown_report |
Sprint burndown data |
jira_worklog_report |
Time tracking summary |
jira_cycle_time_report |
Issue cycle time analysis |
The structured block tools (confluence_read_page, confluence_update_page) are safer and recommended for most use cases. However, the XHTML tools are useful when:
- Debugging: See the raw XHTML to understand parsing issues
- Complex content: Tables with column widths, nested lists, or custom macros that the block parser doesn't fully support
- Preserving formatting: When you need to make small edits without losing inline styles or attributes
{
"name": "confluence_read_page",
"arguments": {
"page_id": "12345"
}
}{
"name": "confluence_read_page_xhtml",
"arguments": {
"page_id": "12345"
}
}Returns the raw Storage Format XHTML in the xhtml field, along with page metadata.
{
"name": "confluence_create_page",
"arguments": {
"space_key": "TEAM",
"title": "Meeting Notes 2025-01-15",
"parent_id": "11111",
"blocks": [
{"type": "heading", "level": 1, "text": "Meeting Notes"},
{"type": "paragraph", "text": "Attendees: Alice, Bob, Carol"},
{"type": "heading", "level": 2, "text": "Action Items"},
{"type": "bullet_list", "items": ["Review PR #123", "Update documentation", "Schedule follow-up"]}
]
}
}{
"name": "confluence_update_page",
"arguments": {
"page_id": "12345",
"title": "Updated Page Title",
"blocks": [
{"type": "heading", "level": 1, "text": "Updated Content"},
{"type": "paragraph", "text": "This page has been updated."},
{"type": "table", "headers": ["Name", "Role"], "rows": [["Alice", "Lead"], ["Bob", "Developer"]]}
]
}
}{
"name": "confluence_update_page_xhtml",
"arguments": {
"page_id": "12345",
"title": "Updated Page Title",
"xhtml": "<h1>Updated Content</h1><p>This page has been updated with raw XHTML.</p><table><tbody><tr><th>Name</th><th>Role</th></tr><tr><td>Alice</td><td>Lead</td></tr></tbody></table>"
}
}Use this when you need to preserve complex formatting that would be lost with structured blocks.
{
"name": "confluence_create_table",
"arguments": {
"headers": ["Service", "Owner", "Status"],
"rows": [
["Auth", "Platform", {"macro": {"name": "status", "params": {"colour": "Green", "title": "OK"}}}],
["API", "Backend", {"macro": {"name": "status", "params": {"colour": "Yellow", "title": "Degraded"}}}]
]
}
}{
"name": "confluence_delete_page",
"arguments": {
"page_id": "12345"
}
}{
"name": "confluence_search_pages",
"arguments": {
"cql": "space=TEAM and type=page and title~\"Meeting\"",
"limit": 10
}
}| Type | Description |
|---|---|
Paragraph |
Text paragraph |
Heading |
H1-H6 headings |
Table |
Tables with headers, rows, and optional macros in cells |
BulletList |
Unordered list |
NumberedList |
Ordered list |
Macro |
Confluence macros (status, info, code, etc.) |
CodeBlock |
Code blocks with language |
HorizontalRule |
Horizontal divider |
- LLMs produce structured JSON (not XHTML) → fewer errors
- Rendering is deterministic Go code → guaranteed valid output
- Validation catches issues before API calls
- Round-trip safe: Parse → Modify → Render preserves structure
MIT
- CHANGELOG.md - Release history
- ROADMAP.md - Planned features
- Confluence Storage Format Documentation