agentcraftai-mcp-jira-confluence
v1.3.0
Published
MCP server for self-hosted Jira and Confluence integration
Readme
🔗 Jira & Confluence MCP Server
Connect your AI-powered editor to self-hosted Jira and Confluence
Query Jira tickets and Confluence pages directly from your AI editor — no browser tab switching required.
Works with Antigravity, Windsurf, VS Code, and any MCP-compatible client.
Source Code & Tracking: https://github.com/Kalpeshgithub58/mcp-jira-confluence
📋 Table of Contents
- What is this?
- Quick Start
- Available Tools
- Editor Configuration
- Configuration Reference
- Local Development
- Architecture
- Project Structure
- Troubleshooting
- License
What is this?
This is an MCP (Model Context Protocol) server that lets AI assistants in your editor directly access Jira and Confluence.
Instead of switching to a browser, you ask your AI editor:
"How many tickets are assigned to me in the last 15 days?"
The AI calls the MCP tool, the server queries your Jira instance, and you get the answer — all within your editor.
You (in editor) MCP Server Jira / Confluence
│ │ │
│ "Show my tickets" │ │
│ ────────────────────► │ │
│ │ REST API + your PAT │
│ │ ────────────────────► │
│ │ ◄──── JSON ────── │
│ ◄── Formatted answer ─── │ │🚀 Quick Start
Prerequisites
- Docker installed on your machine
- A Personal Access Token (PAT) from your Jira instance
- A Personal Access Token (PAT) from your Confluence instance
How to get a PAT: Go to your Jira/Confluence → Profile → Personal Access Tokens → Create Token
Option A: Run via NPX (Recommended for Cursor/Windsurf/Claude)
You don't need to install anything if you have Node.js. Just configure your AI editor to run the server directly using npx:
{
"mcpServers": {
"jira-confluence": {
"command": "npx",
"args": ["-y", "agentcraftai-mcp-jira-confluence", "stdio"],
"env": {
"JIRA_BASE_URL": "https://jira.yourcompany.com",
"JIRA_PAT": "your_jira_token",
"CONFLUENCE_BASE_URL": "https://confluence.yourcompany.com",
"CONFLUENCE_PAT": "your_confluence_token"
}
}
}
}Option B: Run via Docker (Recommended for Remote/Background Servers)
Step 1: Pull and Run
You can find the official image on Docker Hub.
# Pull the latest image
docker pull agentcraftai/mcp-jira-confluence
# Run the container (auto-starts on Docker Desktop boot)
docker run -d \
--name mcp-jira-confluence \
--restart unless-stopped \
-p 8000:8000 \
-e JIRA_BASE_URL=https://jira.yourcompany.com \
-e JIRA_PAT=your_jira_token \
-e CONFLUENCE_BASE_URL=https://confluence.yourcompany.com \
-e CONFLUENCE_PAT=your_confluence_token \
agentcraftai/mcp-jira-confluence🔁 Auto-Start: The
--restart unless-stoppedflag means this container will automatically start whenever Docker Desktop launches. You only need to run this command once.
Step 2: Verify
curl http://localhost:8000/healthExpected response:
{ "status": "ok", "server": "jira-confluence-mcp", "version": "1.0.0" }Step 3: Configure Your Editor
Add this to your editor's MCP settings (see Editor Configuration):
{
"servers": [
{
"name": "jira-confluence",
"url": "http://localhost:8000/mcp"
}
]
}No tokens in the editor config — the server handles authentication internally.
Step 4: Start Asking Questions
Open your AI editor and ask:
- "Show my Jira tickets from the last 7 days"
- "Search for all open bugs in project XYZ"
- "Find Confluence pages about deployment"
- "Get details of ticket PROJ-456"
🛠 Available Tools
Jira Tools
| Tool | Description | Example Input |
|------|-------------|---------------|
| getMyTickets | Fetch issues assigned to you, updated in the last N days | { "lastNDays": 15 } |
| searchJira | Search using any JQL query | { "jql": "project = PROJ AND status = Open" } |
| getIssueDetails | Get full details of a specific issue | { "issueKey": "PROJ-123" } |
| createIssue | Create a new Jira issue (epic, story, task, bug) | { "projectKey": "PROJ", "summary": "Fix auth", "description": "...", "issueType": "Bug" } |
| addComment | Add a comment to an existing issue | { "issueKey": "PROJ-123", "body": "Fixed in PR #45" } |
| updateIssue | Transition an issue to a new status via transition ID | { "issueKey": "PROJ-123", "transitionId": "31" } |
| editIssue | Edit any combination of fields on an existing issue | { "issueKey": "PROJ-123", "summary": "New title", "priority": "High" } |
| listProjects | List all accessible Jira projects | {} |
| getComments | Retrieve the comment history for a specific issue | { "issueKey": "PROJ-123" } |
| getTransitions | List available transition IDs for a specific issue | { "issueKey": "PROJ-123" } |
| getIssueHistory | See status, assignment, and field changes over time | { "issueKey": "PROJ-123" } |
| getSubtasks | Get child tickets of an epic or parent issue | { "issueKey": "PROJ-123" } |
| getLinkTypes | Get all available issue link types in Jira (e.g., 'Blocks') | {} |
| linkIssues | Link two tickets together using a specific link type | { "inwardIssue": "A", "outwardIssue": "B", "linkType": "Blocks" } |
| deleteComment | Delete a comment from a Jira issue | { "issueKey": "PROJ-123", "commentId": "10001" } |
| getIssueAttachments | Retrieve a list of attachments for a Jira issue | { "issueKey": "PROJ-123" } |
| listBoards | List all Agile boards to find a boardId | {} |
| getSprints | Get sprint information for a specific Agile board | { "boardId": 12 } |
| searchUsers | Search for Jira users by name, username, or email | { "query": "John Doe" } |
| addWorklog | Log time against a specific Jira issue | { "issueKey": "PROJ-123", "timeSpent": "2h", "comment": "Writing tests" } |
| deleteIssue | Permanently delete a Jira issue | { "issueKey": "PROJ-123" } |
| getFilters | Retrieve your favorite/starred Jira filters | {} |
Confluence Tools
| Tool | Description | Example Input |
|------|-------------|---------------|
| searchPages | Search pages by keyword | { "query": "deployment guide" } |
| getPage | Get full content of a page by ID | { "pageId": "12345" } |
| listSpaces | List all accessible Confluence spaces | {} |
| createPage | Create a new Confluence page | { "spaceKey": "DOCS", "title": "New Title", "content": "<h1>HTML Body Here</h1>" } |
| editPage | Edit an existing Confluence page (title, content, or both) | { "pageId": "12345", "title": "Updated Title" } |
| deletePage | Delete a Confluence page by its ID | { "pageId": "12345" } |
| getPageAttachments | Retrieve a list of attachments for a Confluence page | { "pageId": "12345" } |
Example Responses
getMyTickets response:
{
"tickets": [
{
"key": "PROJ-101",
"summary": "Fix authentication timeout",
"status": "In Progress",
"priority": "High",
"assignee": "Kalpesh Sarvaiya",
"updated": "2026-03-21",
"type": "Bug",
"project": "PROJ"
}
],
"total": 1
}searchPages response:
{
"pages": [
{
"id": "98765",
"title": "Deployment Guide",
"space": "DEV",
"spaceName": "Development",
"status": "current",
"url": "https://confluence.yourcompany.com/display/DEV/Deployment+Guide"
}
],
"total": 1
}🔌 Editor Configuration
Antigravity & VS Code (HTTP Mode)
Add to your MCP server configuration:
{
"servers": [
{
"name": "jira-confluence",
"url": "http://localhost:8000/mcp"
}
]
}Windsurf (HTTP / SSE Mode)
Windsurf uses a different config format — edit %USERPROFILE%\.codeium\windsurf\mcp_config.json:
{
"mcpServers": {
"jira-confluence": {
"serverUrl": "http://localhost:8000/sse"
}
}
}⚠️ Important: Windsurf uses
mcpServers(object),serverUrl, and the/sseendpoint. Other editors useservers(array),url, and the/mcpendpoint. Always usehttp://— NOThttps://.
Using NPX (STDIO Mode) - No Docker Required
If you prefer to run the server via Node.js instead of Docker, you can use npx to run it directly over STDIO. This is fully supported by Cursor, Claude Desktop, and Windsurf.
Example for mcp_config.json:
{
"mcpServers": {
"jira-confluence": {
"command": "npx",
"args": ["-y", "agentcraftai-mcp-jira-confluence", "stdio"],
"env": {
"JIRA_BASE_URL": "https://jira.yourcompany.com",
"JIRA_PAT": "your_jira_token",
"CONFLUENCE_BASE_URL": "https://confluence.yourcompany.com",
"CONFLUENCE_PAT": "your_confluence_token"
}
}
}
}⚙ Configuration Reference
Independent Services
Jira and Confluence are fully independent. You can use one without the other. If one token expires or is missing, the other service continues working normally.
| Scenario | What happens | |----------|-------------| | Only Jira configured | ✅ Jira tools work · Confluence tools return "not configured" message | | Only Confluence configured | ✅ Confluence tools work · Jira tools return "not configured" message | | Both configured | ✅ All tools work | | Jira token expires | ❌ Jira tools return auth error · ✅ Confluence tools unaffected | | Confluence token expires | ✅ Jira tools unaffected · ❌ Confluence tools return auth error |
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| JIRA_BASE_URL | For Jira tools | Your Jira instance URL (e.g., https://jira.yourcompany.com) |
| JIRA_PAT | For Jira tools | Jira Personal Access Token |
| CONFLUENCE_BASE_URL | For Confluence tools | Your Confluence instance URL (e.g., https://confluence.yourcompany.com) |
| CONFLUENCE_PAT | For Confluence tools | Confluence Personal Access Token |
| PORT | No | Server port (default: 8000) |
Usage Examples
Jira only:
docker run -d -p 8000:8000 \
-e JIRA_BASE_URL=https://jira.yourcompany.com \
-e JIRA_PAT=your_jira_token \
agentcraftai/mcp-jira-confluenceConfluence only:
docker run -d -p 8000:8000 \
-e CONFLUENCE_BASE_URL=https://confluence.yourcompany.com \
-e CONFLUENCE_PAT=your_confluence_token \
agentcraftai/mcp-jira-confluenceBoth:
docker run -d -p 8000:8000 \
-e JIRA_BASE_URL=https://jira.yourcompany.com \
-e JIRA_PAT=your_jira_token \
-e CONFLUENCE_BASE_URL=https://confluence.yourcompany.com \
-e CONFLUENCE_PAT=your_confluence_token \
agentcraftai/mcp-jira-confluenceUsing Docker Compose
Create a .env file (include only the services you need):
JIRA_BASE_URL=https://jira.yourcompany.com
JIRA_PAT=your_jira_token
CONFLUENCE_BASE_URL=https://confluence.yourcompany.com
CONFLUENCE_PAT=your_confluence_tokenRun:
docker compose up -dSecurity
- ✅ Tokens are passed as environment variables only
- ✅ Tokens are never logged or exposed in API responses
- ✅ Logger automatically redacts token-like patterns
- ✅ No tokens in client configuration files
- ✅ Docker container runs as non-root user
💻 Local Development
# Clone the repo
git clone https://github.com/Kalpeshgithub58/mcp-jira-confluence.git
cd mcp-jira-confluence
# Install dependencies
npm install
# Build TypeScript
npm run build
# Set environment variables and run
# (Linux/Mac)
export JIRA_BASE_URL=https://jira.yourcompany.com
export JIRA_PAT=your_token
export CONFLUENCE_BASE_URL=https://confluence.yourcompany.com
export CONFLUENCE_PAT=your_token
npm start
# (Windows PowerShell)
$env:JIRA_BASE_URL="https://jira.yourcompany.com"
$env:JIRA_PAT="your_token"
$env:CONFLUENCE_BASE_URL="https://confluence.yourcompany.com"
$env:CONFLUENCE_PAT="your_token"
npm startBuild Docker Image Locally
docker build -t mcp-jira-confluence .🏗 Architecture
| Component | Detail |
|-----------|--------|
| Runtime | Node.js 18 (Alpine) |
| Language | TypeScript |
| MCP Transport | Streamable HTTP (/mcp) + Legacy SSE (/sse) for backward compatibility |
| HTTP Framework | Express |
| API Client | Axios |
| Endpoints | POST /mcp, GET /mcp, DELETE /mcp (Streamable HTTP) · GET /sse, POST /messages (Legacy SSE) · GET /health |
Key Features
- Full pagination — All list endpoints auto-paginate. No partial results ever returned.
- Rate limit handling — Exponential backoff on HTTP 429 (1s → 2s → 4s, up to 3 retries).
- Clean error mapping —
401→ auth error,403→ permission error, network issues → connection error. - LLM-optimized responses — Minimal, clean JSON. No raw API payloads.
- Session management — Per-client MCP sessions with proper lifecycle.
📁 Project Structure
├── src/
│ ├── index.ts # Express server + MCP transport setup
│ ├── config.ts # Environment variable loading & validation
│ ├── logger.ts # Structured logger with token redaction
│ ├── clients/
│ │ ├── jira-client.ts # Jira REST API client (pagination + retry)
│ │ └── confluence-client.ts # Confluence REST API client (pagination + retry)
│ └── tools/
│ ├── jira.ts # getMyTickets, searchJira, getIssueDetails
│ └── confluence.ts # searchPages, getPage
├── Dockerfile # Multi-stage production build
├── docker-compose.yml # One-command deployment
├── mcp_config.json # Example client configuration
├── .env.example # Template environment variables
├── package.json
└── tsconfig.json🔧 Troubleshooting
| Problem | Cause | Solution |
|---------|-------|----------|
| Unable to connect to remote server | Server not running | Start the container: docker start mcp-jira-confluence |
| Jira authentication failed | Invalid or expired PAT | Generate a new PAT in Jira → Profile → Personal Access Tokens |
| Jira access denied | PAT lacks permissions | Ensure your PAT has read access to the required projects |
| Confluence authentication failed | Invalid or expired PAT | Generate a new PAT in Confluence |
| Jira/Confluence not configured | Missing env vars | Pass all required env vars via -e flags or .env file |
| Connection refused to Jira/Confluence | Network issue | Verify the container can reach your Jira/Confluence URLs |
| Editor can't connect to MCP | Wrong URL | Use http://localhost:8000/mcp (not just localhost:8000) |
Check Container Logs
docker logs mcp-jira-confluenceRestart Container
docker restart mcp-jira-confluence📄 License
MIT
Built with ❤️ for developer productivity
