mcp server
jira-mcp
An enhanced Enterprise-grade Jira MCP server.
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 26, 2026jira-mcp
The Enterprise-grade MCP server generated by mcpfather, specifically designed for AI to call Jira Software Data Center REST API Reference APIs, generated from MCPFather — exposes 435 native tools. Each API operation becomes an AI-callable tool with typed schemas and customized aggregate virtual tools, auth forwarding, and observability built-in, and even use as regular CLI.
Quick Start
make
# Or with OpenTelemetry distributed tracing (gRPC or HTTP)
make build-with-otel-grpc # OTLP gRPC exporter
make build-with-otel-http # OTLP HTTP/protobuf exporter
Start in HTTP mode (example)
# Configure your upstream API
export MCP__UPSTREAM__DEFAULT__ENDPOINT=https://api.example.com
export MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN=your-token
./bin/jira-mcp --transport http --port 8080 &
- Inspection MCP Server Authentication (OAuth2.1).
export MCP__SERVER__AUTH__OIDC__ENABLED=true
export MCP__SERVER__AUTH__OIDC__ISSUER="https://keycloak.example.com/realms/master"
export MCP__SERVER__AUTH__OIDC__AUDIENCE="jira-mcp"
./bin/jira-mcp -v 10 --transport http --port 8080
# Obtain the OAuth2.1 metadata.
curl -s https://iam.example.com/realms/master/.well-known/openid-configuration
curl -s localhost:8080/.well-known/oauth-protected-resource
#{"resource":"jira-mcp","authorization_servers":["https://keycloak.example.com/realms/master"],"bearer_methods_supported":["header"]}
Run in CLI mode (example)
./bin/jira-mcp -v 1 -t cli list
./bin/jira-mcp -v 1 -t cli <tool-name> [OPTIONS]
Request body (--body)
Use --body to send a JSON request body to the upstream API. Query/path
parameters are passed as regular --key value flags.
# JSON body
./bin/jira-mcp -v 1 -t cli uploadScanReport --scanId 12345 \
--body '{"note":"quarterly"}'
File uploads (fileRef URL)
For file upload tools, pass file fields as normal tool arguments. Values starting
with @file:///, @https://, or @http:// are fileRef URLs: the server downloads
the file to the TFS temp cache and forwards it to upstream. Other multipart
fields are passed as regular --key value flags.
# Local file, for the conventional multipart field named "file"
./bin/jira-mcp -v 1 -t cli uploadScanReport --scanId 12345 \
--file /tmp/report.pdf
# Remote URL (server downloads, then forwards to upstream)
./bin/jira-mcp -v 1 -t cli uploadScanReport --scanId 12345 \
--file @https://cdn.example.com/reports/q1.pdf
# Named file field
./bin/jira-mcp -v 1 -t cli configSaml \
--identityProviderXml @file:///tmp/idp.xml \
--samlConfiguration '{"enabled":true}'
The same flag syntax works in HTTP mode via mcpclient.sh:
./mcpclient.sh call uploadScanReport --scanId 12345 \
--file /tmp/report.pdf
Options
| Flag | Default | Description |
|---|---|---|
-t, --transport | stdio | stdio / http / cli |
-p, --port | 8080 | HTTP server port |
--metrics-port | 0 | Override mgmt port (0 = use config) |
-v, --verbose | 0 | Log verbosity (0–10) |
-V, --version | — | Print version and exit |
--print-default-config | — | Print default config.yaml to stdout |
Authentication
Auth is split into two independent layers — neither shares credentials with the other:
| Layer | Config YAML path | Env var prefix | Role |
|---|---|---|---|
| Server | server.auth.oidc | MCP__SERVER__AUTH__OIDC__* | Validates AI agent bearer tokens (inbound) |
| Upstream OIDC | upstream.default.auth.oidc | MCP__UPSTREAM__DEFAULT__AUTH__OIDC__* | Server's own OIDC client_credentials for upstream APIs |
| Upstream Static | upstream.default.auth.static | MCP__UPSTREAM__DEFAULT__AUTH__STATIC__* | Server's own static token/cookie for upstream APIs |
Server (inbound) — validates bearer tokens presented by AI agents (MCP clients).
Only applies to --transport http; stdio has no network boundary. Standard OIDC JWT
bearer validation per RFC 9728 / MCP Authorization spec.
Upstream (outbound) — credentials the MCP server uses to call upstream APIs. Token priority (first available wins):
- OIDC client_credentials grant (
upstream.default.auth.oidc.*) - Static web token (
upstream.default.auth.static.web_token)
The AI agent's inbound token is never forwarded upstream (MCP spec: Token Passthrough Prohibition).
Cookie-based auth is also available via upstream.default.auth.static.cookie_token.
Configuration
Create ~/.jira-mcp/config.yaml (run --print-default-config for a full template):
# ---- Server (inbound) ----
# Validates bearer tokens presented by MCP clients (AI agents).
# Resource Server role per RFC 9728 / MCP Authorization spec.
# Only enforced on the http transport; stdio has no network boundary.
server:
# HTTP server timeouts in seconds. 0 = disabled.
# write_timeout_seconds must be 0 for SSE (Streamable HTTP) transport.
read_timeout_seconds: 30
write_timeout_seconds: 0
idle_timeout_seconds: 120
auth:
oidc:
enabled: false
issuer: "" # e.g. https://idp.example.com/realms/myrealm
jwks_uri: "" # optional override (auto-discovered from issuer if empty)
audience: "" # expected JWT "aud" claim; also published as the RFC 9728 protected-resource identifier
# When true, validated JWT claims (sub, email) are forwarded upstream
# as X-MCP-Client-Token-Sub and X-MCP-Client-Token-Email headers.
enable_client_token_claim_forward: true
# Additional JWT claims to forward as X-MCP-Client-Token-<Header-Name> headers.
# e.g. ["given_name", "family_name", "preferred_username"]
# additional_client_token_claim_forward: []
# ---- Temporary File System (TFS) Data Plane ----
# Built-in REST API for binary file transfer, separate from the
# JSON-RPC 2.0 control plane at /mcp.
# Files stored under ~/.<service-name>/tfs/{download,upload}/
tfs:
enabled: true
# Empty means auto-detect from the inbound /mcp request Host/X-Forwarded-* headers.
base_uri: ""
# Download URLs are one-shot: after a successful GET from /_/tfs/download/{id},
# the temporary file is immediately removed. Files that are never downloaded
# are removed by the background clean job after this TTL.
clean-job-ttl-seconds: "5m"
logging:
level: 0
auth_verbose: false
# ---- Upstream (outbound) ----
# Credentials the server uses to call upstream APIs.
# The two auth layers are independent — the inbound token is never reused outbound
# (see MCP Authorization spec: Token Passthrough Prohibition).
upstream:
default:
endpoint: "" # upstream API base URL (e.g. https://api.example.com)
enable_mcp_session_forward: true
auth:
oidc:
enabled: true
issuer: https://idp.example.com/realms/myrealm
client_id: my-client
client_secret: "${MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_SECRET}"
scopes: openid
# token_url: "" # auto-discovered from issuer /.well-known
# Static credentials for legacy / simple APIs
static:
web_token: "${MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN}" # or set cookie_token
# Reusable policies selected by HTTP-node `spec.pool` and `spec.retry`.
# Omitted references use pool limits 32/32/32, request_timeout 0s, and 0 retries.
middleware:
http_client_pool:
large:
max_idle_conns: 128 # reusable idle connections across all upstream hosts
max_idle_conns_per_host: 32 # reusable idle connections retained per upstream host
max_conns_per_host: 64 # hard cap: active + dialing + idle connections per host
dial_timeout: 10s # TCP connection establishment timeout
request_timeout: 60s # complete attempt, including response-body reads
medium:
max_idle_conns: 64
max_idle_conns_per_host: 16
max_conns_per_host: 32
dial_timeout: 5s
request_timeout: 30s
small:
max_idle_conns: 16
max_idle_conns_per_host: 4
max_conns_per_host: 8
dial_timeout: 3s
request_timeout: 15s
retry:
reliable:
max_retries: 4 # extra attempts after the first request
max_elapsed_time: 30s # hard budget for all attempts and backoff
standard:
max_retries: 2
max_elapsed_time: 15s
besteffort:
max_retries: 0 # no automatic retry; max_elapsed_time is unnecessary
# QoS-style names communicate retry intent without promising application success.
native_tools:
expose:
register_all_tools_by_default: true # expose all native tools
# includes: [Tool1, Tool2] # or whitelist specific tools
# excludes: [Tool3] # hide noisy tools
All values can be set via MCP__-prefixed environment variables (e.g. MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_ID).
Management — Metrics, Tracing, Pprof
mgmt:
enabled: true
host: 0.0.0.0
port: 9991
otel:
enabled: false
endpoint: localhost:4317
protocol: grpc
sample_rate: 1.0
metrics:
enabled: true
prometheus: true
export_interval: 30s
pprof:
enabled: false
server_bind: 0.0.0.0:6669
./bin/jira-mcp --transport http --port 8080
curl http://localhost:9991/metrics # Prometheus endpoint
curl http://localhost:9991/health # health check
Trace spans are named mcp.tool.<name>. W3C traceparent is propagated to upstream calls.
Available Tools (435)
| Tool | Description |
|---|---|
AcknowledgeErrors | Retry cluster upgrade - Retries the cluster upgrade. |
AddActorUsers | Add actor to project role - Adds an actor (user or group) to a project role. For user actors, their usernames should be used. |
AddAttachment | Add one or more attachments to an issue - Add one or more attachments to an issue. This resource expects a multipart post. The media-type multipart/form-data is defined in RFC 1867. Most client libraries have classes that make dealing with multipart posts simple. For instance, in Java the Apache HTTP Components library provides a MultiPartEntity that makes it simple to submit a multipart POST. In order to protect against XSRF attacks, because this method accepts multipart/form-data, it has XSRF protection on it. This means you must submit a header of X-Atlassian-Token: no-check with the request, otherwise it will be blocked. The name of the multipart/form-data parameter that contains attachments must be file. A simple example to upload a file called "myfile.txt" to issue TEST-123: curl -D- -u admin:admin -X POST -H "X-Atlassian-Token: no-check" -F "file=@myfile.txt" http://myhost/rest/api/2/issue/TEST-123/attachments |
AddComment | Add a comment - Adds a new comment to an issue. |
AddField | Add field to a tab - Adds field to the given tab. |
AddFieldToDefaultScreen | Add field to default screen - Moves field on the given tab. |
AddProjectAssociationsToScheme | Add project associations to scheme - Adds additional projects to those already associated with the specified issue type scheme |
AddProjectRoleActorsToRole | Adds default actors to a role - Adds default actors to the given role. The request data should contain a list of usernames or a list of groups to add. |
AddSharePermission | Add share permissions to filter - Adds a share permissions to the given filter. Adding a global permission removes all previous permissions from the filter |
AddTab | Create tab for a screen - Creates tab for given screen. |
AddUserToApplication1 | Add user to application - Add user to given application. Admin permission will be required to perform this operation. |
AddUserToGroup | Add a user to a specified group - Adds given user to a group |
AddVote | Add vote to issue - Adds voter (currently logged user) to particular ticket. You need to be logged in to use this method. |
AddWatcher1 | Add a user as watcher - Adds a user to an issue's watcher list. |
AddWorklog | Add a worklog entry - Adds a new worklog entry to an issue. |
| … | 420 more tools not shown |
Virtual Tools
Compose native tools via a declarative pipeline DSL:
virtual_tools:
- name: MyVirtualTool
description: Chain multiple native tools together
input_schema:
type: object
properties:
appId: { type: string }
required: [appId]
pipeline:
- id: getApp
kind: call
spec: { tool: GetApplication, args: { applicationId: "$input.appId" } }
- id: appName
kind: jq
spec: { from: "$getApp", expr: .name }
- id: done
kind: return
spec: { from: "$appName" }
Pipeline kinds: call, jq, foreach, emit, return.
Agent Integration
OpenCode
~/.config/opencode/opencode.json:
{
"mcp": {
"jira-mcp": {
"type": "local",
"command": ["bash", "-c", "/path/to/jira-mcp"],
"args": ["--transport", "stdio"],
"env": {
"MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
},
"enabled": true
}
}
}
Claude Code
~/.claude.json:
{
"mcpServers": {
"jira-mcp": {
"command": "/path/to/jira-mcp",
"args": ["--transport", "stdio"],
"env": {
"MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
}
}
}
}
Codex CLI
~/.codex/config.toml:
[mcp_servers.jira-mcp]
url = "http://localhost:8080/mcp"
web_token_env_var = "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN"
Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"jira-mcp": {
"command": "/path/to/jira-mcp",
"args": ["--transport", "stdio"],
"env": {
"MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
}
}
}
}
OpenCode (Remote)
~/.config/opencode/opencode.json:
{
"mcp": {
"jira-mcp": {
"type": "remote",
"url": "http://localhost:8080/mcp",
"env": {
"MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
}
}
}
}
Claude Code (Remote)
~/.claude.json(User MCPs):
{
"mcpServers": {
"jira-mcp": {
"url": "http://localhost:8080/mcp",
"env": {
"MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
"MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
}
}
}
}
Codex CLI (Remote)
~/.codex/config.toml:
[mcp_servers.jira-mcp]
url = "http://localhost:8080/mcp"
web_token_env_var = "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN"
Cursor (Remote)
~/.cursor/mcp.json:
{
"mcpServers": {
"jira-mcp": {
"url": "http://localhost:8080/mcp"
}
}
}
Deployment — Docker
Build
make build-image
Or manually:
docker build -t ghcr.io/<YOUR_ORG>/jira-mcp:latest -f deploy/docker/Dockerfile .
docker push ghcr.io/<YOUR_ORG>/jira-mcp:latest
Run
Pull the pre-built image from GitHub Container Registry:
docker pull ghcr.io/<YOUR_ORG>/jira-mcp:latest
First generate a default config, then mount it when running:
docker run --rm ghcr.io/<YOUR_ORG>/jira-mcp:latest --print-default-config > ~/.jira-mcp/config.yaml
- Static web token
docker run -d --name jira-mcp \
-p 8080:8080 -p 9991:9991 \
-e MCP__UPSTREAM__DEFAULT__ENDPOINT="https://api.example.com" \
-e MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN="YOUR_WEB_TOKEN" \
-v ~/.jira-mcp:/home/mcp/.jira-mcp \
ghcr.io/<YOUR_ORG>/jira-mcp:latest \
--transport http --port 8080
- OIDC upstream auth
docker run -d --name jira-mcp \
-p 8080:8080 -p 9991:9991 \
-e MCP__UPSTREAM__DEFAULT__ENDPOINT="https://api.example.com" \
-e MCP__UPSTREAM__DEFAULT__AUTH__OIDC__ENABLED=true \
-e MCP__UPSTREAM__DEFAULT__AUTH__OIDC__ISSUER="https://idp.example.com/realms/myrealm" \
-e MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_ID="my-client" \
-e MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_SECRET="YOUR_CLIENT_SECRET" \
-v ~/.jira-mcp:/home/mcp/.jira-mcp \
ghcr.io/<YOUR_ORG>/jira-mcp:latest \
--transport http --port 8080
Test with mcpclient.sh
After the container starts, use the bundled mcpclient.sh to verify.
Note:
mcpclient.shonly supports upstream static token auth. If the server requires server OIDC authentication, use a real AI-agent MCP client instead.
# Point to the mapped host port (include /mcp path)
export MCP_SERVER_ENDPOINT=http://localhost:18080/mcp
# Call any tool (example: AcknowledgeErrors)
./mcpclient.sh call AcknowledgeErrors --param value
# List all available tools
./mcpclient.sh list-tools
Tip: Map the host config directory for persistent configuration:
-v ~/.jira-mcp:/home/mcp/.jira-mcp
Deployment — Kubernetes (Helm)
First generate a default config, then mount it when running:
docker run --rm ghcr.io/<YOUR_ORG>/jira-mcp:latest --print-default-config > ~/.jira-mcp/config.yaml
- Static web token
helm upgrade -i jira-mcp deploy/helm \
--set image.repository=ghcr.io/<YOUR_ORG>/jira-mcp \
--set image.tag=latest \
--set secret.static.create=true \
--set secret.static.webToken="YOUR_WEB_TOKEN" \
--set config.upstream.default.endpoint="https://api.example.com"
- OIDC authentication
helm upgrade -i jira-mcp deploy/helm \
--set image.repository=ghcr.io/<YOUR_ORG>/jira-mcp \
--set image.tag=latest \
--set secret.static.create=true \
--set secret.static.oidcClientSecret="YOUR_OIDC_CLIENT_SECRET" \
--set config.upstream.default.auth.oidc.enabled=true \
--set config.upstream.default.auth.oidc.issuer="https://idp.example.com" \
--set config.upstream.default.auth.oidc.client_id="my-client" \
--set config.upstream.default.endpoint="https://api.example.com"
See deploy/helm/values.yaml for all configurable parameters.
Contributing
We welcome contributions! Here's how you can help:
- Fork the repository and create a feature branch
- Make your changes — add features, fix bugs, or improve documentation
- Add tests — every new feature or bug fix should include unit tests
- Run the test suite —
make testmust pass with no regressions - Submit a Pull Request — describe what you changed and why
Development Setup
git clone https://github.com/<YOUR_ORG>/jira-mcp.git
cd jira-mcp
make build
make test-ut
Code Style
- Follow standard Go conventions (
go fmt,go vet) - Keep functions small and focused
- Write clear commit messages
Please read CONTRIBUTING.md for detailed guidelines and our Code of Conduct.
License
This generated MCP server project is licensed under the Apache License 2.0 — see the LICENSE file for details.
The Apache-2.0 license is intentionally permissive for generated server output: commercial use, internal enterprise deployment, modification, redistribution, and proprietary integration are allowed subject to the Apache License 2.0 terms. This generated project is not subject to mcpfather's AGPL license obligations solely because it was generated by mcpfather.
Contact
For questions, suggestions, or support:
- GitHub Issues: Create an issue
- Discussions: Start a discussion
- Email: jameswong1376@gmail.com
Acknowledgments
This MCP server was generated by MCPFather, an enterprise-grade OpenAPI-to-MCP code generator.
Built with these excellent open-source projects:
- mcp-go — Go SDK for the Model Context Protocol
- OpenTelemetry — observability framework for metrics and tracing
- Prometheus — metrics collection and alerting
- Viper — Go configuration management
- go-jq — Pure Go implementation of jq
- Keycloak — Open Source Identity and Access Management