OpenClaw Jira Integration
Connect OpenClaw to Jira Cloud using Expanso pipelines. Create issues, track sprints, run JQL queries, and automate project management with natural language - all while keeping your API tokens local.
Prerequisites
You need OpenClaw installed (install guide), a free Expanso Cloud account (sign up), and a Jira Cloud account with API token access.
What you can do with OpenClaw + Jira
Once connected, you can manage Jira with natural language through OpenClaw:
assignee = currentUser() AND type = Bug AND sprint in openSprints()), sends it through the Expanso pipeline, and returns a formatted list of matching issues.Generate a Jira API Token
Jira Cloud uses API tokens for authentication. The token is scoped to your user account's permissions.
1.1 Create an API token
Go to Atlassian API Tokens and click Create API token. Give it a label like "OpenClaw Expanso" and copy the token.
1.2 Store credentials securely
# Add to your .env or shell profile
export JIRA_DOMAIN="yourcompany.atlassian.net"
export JIRA_EMAIL="[email protected]"
export JIRA_API_TOKEN="your-atlassian-api-token"Deploy the Jira Pipeline
Create Expanso pipelines for reading and writing Jira data.
2.1 Set up Expanso (if you haven't already)
Follow the Expanso setup guide to create your account and install the CLI.
2.2 Create the Jira query pipeline
Open cloud.expanso.io, click New Pipeline, and paste:
# jira-query.yaml
# Runs JQL queries and returns structured results
input:
http_server:
path: /jira-query
allowed_verbs: [ "POST" ]
pipeline:
processors:
- http:
url: "https://${JIRA_DOMAIN}/rest/api/3/search"
verb: POST
headers:
Content-Type: "application/json"
basic_auth:
username: "${JIRA_EMAIL}"
password: "${JIRA_API_TOKEN}"
- mapping: |
root.issues = this.issues.map_each(issue -> {
"key": issue.key,
"summary": issue.fields.summary,
"status": issue.fields.status.name,
"priority": issue.fields.priority.name,
"assignee": issue.fields.assignee.displayName.or("Unassigned"),
"type": issue.fields.issuetype.name
})
root.total = this.total
output:
sync_response: {}2.3 Create the Jira issue creator pipeline
For creating and updating issues:
# jira-create.yaml
# Creates new Jira issues
input:
http_server:
path: /jira-create
allowed_verbs: [ "POST" ]
pipeline:
processors:
- mapping: |
root.fields.project.key = this.project
root.fields.summary = this.summary
root.fields.description.type = "doc"
root.fields.description.version = 1
root.fields.description.content = [{
"type": "paragraph",
"content": [{"type": "text", "text": this.description}]
}]
root.fields.issuetype.name = this.type.or("Task")
root.fields.priority.name = this.priority.or("Medium")
- http:
url: "https://${JIRA_DOMAIN}/rest/api/3/issue"
verb: POST
headers:
Content-Type: "application/json"
basic_auth:
username: "${JIRA_EMAIL}"
password: "${JIRA_API_TOKEN}"
output:
sync_response: {}2.4 Create the sprint status pipeline
For sprint tracking and team status:
# jira-sprint.yaml
# Gets current sprint status with issue breakdown
input:
http_server:
path: /jira-sprint
allowed_verbs: [ "POST" ]
pipeline:
processors:
- http:
url: "https://${JIRA_DOMAIN}/rest/api/3/search?jql=sprint%20in%20openSprints()&maxResults=100"
verb: GET
headers:
Content-Type: "application/json"
basic_auth:
username: "${JIRA_EMAIL}"
password: "${JIRA_API_TOKEN}"
- mapping: |
let issues = this.issues
root.total = $issues.length()
root.done = $issues.filter(i -> i.fields.status.statusCategory.name == "Done").length()
root.in_progress = $issues.filter(i -> i.fields.status.statusCategory.name == "In Progress").length()
root.todo = $issues.filter(i -> i.fields.status.statusCategory.name == "To Do").length()
root.issues = $issues.map_each(i -> {
"key": i.key,
"summary": i.fields.summary,
"status": i.fields.status.name,
"assignee": i.fields.assignee.displayName.or("Unassigned")
})
output:
sync_response: {}2.5 Deploy all pipelines
Click Deploy for each pipeline. They run locally with your Jira credentials resolved from environment variables.
Connect to OpenClaw
Register the Expanso MCP server so OpenClaw can invoke your Jira pipelines.
3.1 Register the MCP server
# Register Expanso pipelines with OpenClaw
expanso-cli mcp add npx @expanso/mcp-pipelines3.2 Test the integration
Open OpenClaw and try these commands:
# Query issues
"Show me all open bugs in the PLATFORM project"
# Create an issue
"Create a task in PLATFORM: Update API rate limiting docs"
# Sprint status
"What's the current sprint progress? How many stories are done?"
# Bulk operations
"Move all QA-approved tickets to Done in the current sprint"
# Cross-platform
"Get the sprint status and post it to #standup on Slack"Common Jira workflows
📊 Sprint status reports
Ask for a sprint summary and get a breakdown of done, in-progress, and blocked items with assignees. Post it to Slack automatically before standup meetings.
🔍 Natural language JQL
Skip the JQL syntax. Ask "show me all high-priority bugs created this week" and OpenClaw translates it to the right query, runs it through Expanso, and returns formatted results.
📝 Issue creation from chat
Mention a bug in Slack and have OpenClaw create a Jira issue automatically with the right project, type, priority, and description. The issue link is posted back to the channel.
📈 Team velocity tracking
Weekly velocity reports that compare current sprint performance against historical averages. Surfaces trends, bottlenecks, and scope changes.
🔄 Status transitions
Move issues through your workflow with natural language. "Mark PLATFORM-123 as in review" or "Transition all my QA-passed tickets to done." Expanso handles the Jira API calls.
🔗 Cross-tool linking
Connect Jira issues with GitHub PRs, Slack threads, and Confluence pages. OpenClaw uses Expanso pipelines to link data across your entire toolchain.
Frequently asked questions
Does this work with Jira Server or Data Center?
What Jira permissions does the API token have?
Can OpenClaw handle large JQL result sets?
Is my Jira API token safe?
Can I limit which projects OpenClaw can access?
Start connecting Jira
Get your OpenClaw wired up to Jira in under 15 minutes.
