Skip to main content
Glama
ranson21

jira-readonly-mcp

by ranson21

jira-readonly-mcp

A small, dependency-light MCP server that gives local coding agents (OpenCode, or anything else that speaks MCP over stdio) safe, read-only access to an existing Jira instance — without ever handing the LLM your Jira credentials.

This project is read-only. It cannot create, edit, comment on, transition, delete, reassign, or otherwise modify anything in Jira. See Threat & security model for how that's enforced.

OpenCode / local LLM
     │  MCP (stdio, JSON-RPC)
     ▼
jira-readonly-mcp   ← owns the Jira credential; the LLM never sees it
     │  Jira REST API (GET only)
     ▼
Jira (Cloud or Server/Data Center)

What this is for

Local coding agents are often asked to look at a Jira ticket ("summarize DEMO-123", "what's blocking this epic?"). The naive way to enable that is to give the agent your Jira URL and token directly, which means the token ends up in prompts, logs, and potentially the model provider's request. This server instead sits in between: it holds the credential, calls Jira itself, strips it down to compact structured data, and hands that to the model. The model never sees JIRA_TOKEN.

Related MCP server: JIRA MCP Server

Threat & security model

What this protects against: the LLM (or a malicious prompt injected into a Jira ticket) never has the ability to obtain your Jira credential, and never has the ability to send a write request to Jira, because this process is architecturally incapable of it.

Concretely:

  • The Jira credential lives only in this server's environment variables. It is never included in any MCP message, tool schema, tool result, or log line.

  • src/jira/client.ts exposes exactly one HTTP method: get(). There is no post/put/patch/delete method anywhere in the codebase for a compromised or confused tool call to reach. Every outgoing request also passes through assertReadOnlyMethod(), which throws if the method is anything but GET/HEAD. This is enforced in code, not by asking the model nicely — see tests/guard.test.ts and tests/client.test.ts.

  • The six MCP tools this server registers (below) only ever call .get(). There is no tool for creating, editing, commenting on, transitioning, deleting, or reassigning issues, and none is planned — adding one would require deliberately building a new write path through a client that currently cannot make one.

  • Responses are passed through src/security/sanitize.ts before being returned to the model, which redacts common credential shapes (Bearer/Basic auth headers, password=/api_key=/secret=-style assignments, PEM private key blocks, AWS access key IDs, Atlassian API token shapes) that might otherwise be echoed back inside a ticket description, a comment, or a verbose upstream error message.

What this does not protect against, and is explicitly out of scope:

  • The sanitizer is defense-in-depth, not a security boundary. It's a best-effort regex scrubber over text that Jira users wrote. It will not catch every possible secret shape, and it is not a substitute for keeping real secrets out of Jira in the first place. Treat it as a safety net, not a guarantee.

  • This server does not sandbox or rate-limit the content of what Jira returns — if a ticket contains something sensitive that doesn't match a redaction pattern, it will reach the model like any other ticket field.

  • This server trusts whatever process starts it to supply correct environment variables. It does not manage secrets storage, rotation, or audit logging beyond what you configure yourself.

  • Anyone who can run this process (or read your .env) can read anything your Jira account can read. Scope the account/token you use accordingly (see Authentication configuration).

Available tools

Tool

Description

get_issue(issue_key)

Full compact view of one issue: summary, description, status, type, priority, acceptance criteria (if configured), comments, and linked issues.

search_issues(jql, limit?)

Runs a JQL query, returns compact rows (key, summary, status, type, priority, assignee). Result count is capped.

get_comments(issue_key, limit?)

Comments on an issue as { author, body, created }.

get_related_issues(issue_key)

Linked issues, subtasks, and parent for an issue.

get_my_open_issues(limit?)

Unresolved issues assigned to the authenticated user.

get_project_metadata(project_key)

Basic project info: name, type, lead.

None of these accept a payload that could mutate Jira — there's no fields argument for writing values, no transition argument, nothing beyond what's needed to select what to read.

Installation on macOS

Requires Node.js 18.17+ (Apple Silicon or Intel; no native/compiled dependencies).

git clone https://github.com/ranson21/jira-readonly-mcp.git
cd jira-readonly-mcp
npm install
npm run build

This produces dist/index.js, a plain Node script you point OpenCode (or any MCP client) at.

Authentication configuration

Copy the example env file and fill in your real values — do not commit .env (it's already git-ignored):

cp .env.example .env

.env.example

# Copy this file to .env and fill in real values.
# .env is git-ignored - never commit it.
#
# All values below are FAKE placeholders for illustration only.

# Base URL of your Jira instance (Cloud or Server/Data Center), no trailing slash.
# Cloud example:   https://your-company.atlassian.net
# Server/DC example: https://jira.example-corp.internal
JIRA_BASE_URL=https://example.atlassian.net

# --- Authentication ---
# Jira Cloud: use your Atlassian account email + an API token
#   (create one at https://id.atlassian.com/manage-profile/security/api-tokens)
# Jira Server/Data Center: usually a Personal Access Token (PAT), no username needed
#   (create one under your Jira profile -> Personal Access Tokens)

# Required for Jira Cloud basic auth. Leave unset for Server/DC bearer-token auth.
JIRA_USERNAME=you@example.com

# Jira Cloud API token, or Jira Server/DC Personal Access Token.
JIRA_TOKEN=REPLACE_WITH_YOUR_TOKEN

# Optional: force the auth scheme instead of auto-detecting from JIRA_USERNAME.
# One of: basic | bearer
# JIRA_AUTH_TYPE=basic

# Optional: Jira REST API version to call. Defaults to "2", which both Jira
# Cloud and Jira Server/Data Center support for read operations.
# JIRA_API_VERSION=2

# Optional: custom field ID that holds "Acceptance Criteria" in your Jira
# instance, e.g. customfield_10040. Leave unset if you don't use one.
# JIRA_ACCEPTANCE_CRITERIA_FIELD=customfield_10040

# Optional: default/maximum number of results returned by search tools.
# JIRA_DEFAULT_SEARCH_LIMIT=25
# JIRA_MAX_SEARCH_LIMIT=50

# Optional: request timeout in milliseconds.
# JIRA_REQUEST_TIMEOUT_MS=15000

# Optional: diagnostic log verbosity. One of: debug | info | warn | error.
# Logs always go to stderr, never stdout (stdout is reserved for MCP JSON-RPC
# traffic). Defaults to "info".
# JIRA_MCP_LOG_LEVEL=info

Two supported auth modes, auto-detected from whether JIRA_USERNAME is set (or force one with JIRA_AUTH_TYPE=basic|bearer):

  • Basic (JIRA_USERNAME + JIRA_TOKEN): sends Authorization: Basic base64(user:token). This is the standard way to authenticate to Jira CloudJIRA_USERNAME is your Atlassian account email, JIRA_TOKEN is an API token from https://id.atlassian.com/manage-profile/security/api-tokens.

  • Bearer (JIRA_TOKEN only, no JIRA_USERNAME): sends Authorization: Bearer <token>. This is the standard way to authenticate to Jira Server/Data Center with a Personal Access Token, created from your Jira profile's "Personal Access Tokens" page. No Jira administrator action is required to create a PAT for your own account.

Neither mode requires Jira admin access, Rovo/Atlassian-admin features, or any change to the Jira instance itself — just a normal authenticated-user credential.

Optional: macOS Keychain

If you'd rather not keep the token in a plaintext .env file, store it in Keychain and export it into the environment at launch time instead of setting JIRA_TOKEN directly:

security add-generic-password -a "$USER" -s jira-readonly-mcp-token -w 'your-token-here'

Then wrap the launch command (e.g. in the OpenCode config below) so JIRA_TOKEN is populated from Keychain right before the server starts, for example with a small shell wrapper:

#!/bin/sh
# run.sh
export JIRA_TOKEN="$(security find-generic-password -a "$USER" -s jira-readonly-mcp-token -w)"
exec node "$(dirname "$0")/dist/index.js"

Point OpenCode's command at run.sh instead of node dist/index.js directly. This keeps the token out of .env, shell history, and process-listing tools; it's still visible to anything that can read this process's environment once it's running, same as any other env-var-based secret.

OpenCode MCP configuration

Add this to your OpenCode config (e.g. opencode.json or ~/.config/opencode/opencode.json), using OpenCode's local MCP server schema:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "jira": {
      "type": "local",
      "command": ["node", "/absolute/path/to/jira-readonly-mcp/dist/index.js"],
      "enabled": true,
      "environment": {
        "JIRA_BASE_URL": "https://your-company.atlassian.net",
        "JIRA_USERNAME": "you@example.com",
        "JIRA_TOKEN": "your-real-token-goes-here-not-in-git"
      }
    }
  }
}

Use an absolute path for command — OpenCode resolves it relative to its own working directory, not this repo. If you're using the Keychain wrapper above, point command at run.sh and drop JIRA_TOKEN from environment.

Example tool calls

Once configured, ask your agent things like:

  • "Read Jira issue DEMO-123 and summarize the requested work."

  • "Search Jira for open bugs in project DEMO with search_issues using JQL project = DEMO AND type = Bug AND status != Done."

  • "What issues are linked to DEMO-123?" (uses get_related_issues)

  • "What's currently assigned to me in Jira?" (uses get_my_open_issues)

A get_issue result looks like:

{
  "key": "DEMO-123",
  "summary": "Add dark mode toggle to settings page",
  "description": "Users have requested a dark mode toggle...",
  "status": "In Progress",
  "type": "Story",
  "priority": "Medium",
  "acceptanceCriteria": null,
  "comments": [
    { "author": "Sam Sample", "body": "Started on this.", "created": "2026-01-06T12:00:00.000+0000" }
  ],
  "links": [
    { "type": "blocks", "key": "DEMO-124", "summary": "Design dark mode palette", "status": "Done" }
  ]
}

Logging

This server writes diagnostic logs to stderr only. It never writes anything to stdout, because stdout is the MCP JSON-RPC transport for this stdio server — any stray line written there would corrupt the protocol stream and break the client. console.error (or an equivalent stderr-targeted call) is used everywhere logging happens; console.log is never used in this codebase.

Control verbosity with JIRA_MCP_LOG_LEVEL (debug | info | warn | error, default info). Each line looks like:

[2026-09-13T01:19:17.703Z] [INFO] [jira-readonly-mcp] tool invoked {"tool":"get_issue","issueKey":"DEMO-123"}

What gets logged, and at what level:

Event

Level

Server startup (target base URL, auth type, log level — never the token)

info

Tool invoked (tool name, issue key/JQL/project key/limit as applicable)

info

Outbound Jira request start (method + path only, no query string)

debug

Outbound Jira request complete (method, path, HTTP status, elapsed ms)

info

Sanitization complete (tool name only)

debug

Tool succeeded (tool name only)

info

Errors (auth failures, network failures, tool failures)

error

What is never logged, at any level: the Jira token, the Authorization header value, passwords/secrets, full issue descriptions or comment bodies, raw Jira API response bodies, or other ticket content. As an extra safety net on top of that, every structured log field also passes through the same redaction layer used for tool output (src/security/sanitize.ts) before being written — see Threat & security model for why that's defense-in-depth, not a guarantee.

If you don't see any log output, make sure you're capturing your MCP client's stderr stream — OpenCode and most MCP clients keep it separate from the tool-call output you see in chat. When running the server directly, 2> redirection or just watching the terminal (stderr isn't buffered the way piped stdout can be) will show it.

Verifying the server without exposing credentials

You can confirm the server works end-to-end using fake/placeholder credentials against a Jira instance you control (or just verify it fails safely against a bogus host), without ever putting a real token in a terminal that a shared log might capture:

npm run build

JIRA_BASE_URL="https://your-real-instance.atlassian.net" \
JIRA_USERNAME="you@example.com" \
JIRA_TOKEN="$(security find-generic-password -a "$USER" -s jira-readonly-mcp-token -w)" \
node dist/index.js

The server logs a single non-sensitive startup line to stderr (connected (stdio), read-only, target=..., auth=...) and then waits for MCP JSON-RPC messages on stdin. You can drive it manually with the MCP Inspector:

npx @modelcontextprotocol/inspector node dist/index.js

Inspector lets you call tools/list and tools/call interactively in a browser UI without ever printing your token to the terminal. Run npm test first (see Testing) to verify all parsing/sanitization/auth-handling logic without touching a real Jira instance at all.

Jira Cloud vs. Data Center notes

This server calls the Jira REST API v2 endpoints (/rest/api/2/...) by default, which are supported by both Jira Cloud and Jira Server/Data Center for the read operations this project uses. You generally don't need to change anything.

  • Jira Cloud: use Basic auth (email + API token). Descriptions/comments are internally ADF (Atlassian Document Format) documents even under /rest/api/2/; this server flattens them to plain text automatically (src/jira/transform.ts).

  • Jira Server/Data Center: use Bearer auth (Personal Access Token). Descriptions/comments are typically plain text/wiki markup strings, which pass through unchanged.

  • If your instance needs /rest/api/3/... for some reason, set JIRA_API_VERSION=3 in .env. The response parsing already handles both plain-text and ADF descriptions, so this should work either way.

  • This server does not assume Rovo MCP, Atlassian admin/Connect app access, or any Cloud-specific feature — only the ordinary REST endpoints available to any authenticated user (/issue/{key}, /issue/{key}/comment, /search, /project/{key}).

Troubleshooting

  • "Missing required environment variable JIRA_BASE_URL / JIRA_TOKEN" — you haven't set up .env (or the environment block in your OpenCode config). See Authentication configuration.

  • JiraAuthError / HTTP 401 or 403 — the token is invalid, expired, or the auth mode is wrong for your deployment (Cloud wants Basic + email, Server/DC wants Bearer + PAT). Try JIRA_AUTH_TYPE=basic or JIRA_AUTH_TYPE=bearer explicitly to rule out mis-detection.

  • "Jira returned a non-JSON response" — usually means JIRA_BASE_URL is wrong (e.g. pointing at a login page or reverse proxy), or the wrong JIRA_API_VERSION for your deployment.

  • Empty links array you expected to be populated — Jira only returns issuelinks when the field is requested and the link type is visible to your account/permission scheme. This is a Jira permissions detail, not a bug in this server.

  • acceptanceCriteria is always null — set JIRA_ACCEPTANCE_CRITERIA_FIELD to the custom field ID that holds it in your Jira instance (e.g. customfield_10040). Field IDs are instance-specific; ask your Jira admin or check an issue's "View field" metadata.

  • OpenCode doesn't see the tools — double check command is an absolute path to dist/index.js and that you ran npm run build (OpenCode runs the compiled output, not the TypeScript source).

Running entirely locally

Aside from the HTTPS requests this server makes directly to your JIRA_BASE_URL, everything else — the MCP process, the OpenCode/local-model side, tool schema handling, and the sanitization layer — runs entirely on your machine. No third-party service, telemetry endpoint, or analytics call is contacted. This makes it a good fit for local model setups (OpenCode + a locally-served model, e.g. via MLX/OptiQ) where you want to keep everything except the necessary Jira traffic on-device.

Testing

npm test

Tests cover issue/comment/project parsing (including ADF vs. plain-text descriptions), malformed/partial Jira responses, JQL search handling and result-limit clamping, credential redaction (pattern-based and key-name-based), rejection of any non-GET HTTP method, and authentication-failure handling (401/403). All tests run against fixtures with fictional data in tests/fixtures/ — no network access, no real Jira instance required.

Development

npm run dev    # run src/index.ts directly with tsx, for local iteration
npm run build  # compile to dist/
npm test       # run the test suite

License

MIT — see LICENSE.

Available Tools

6 tools
get_commentsB

Fetch comments for a Jira issue as compact structured data. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax comments to return
issue_keyYesJira issue key, e.g. DEMO-123

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully declares 'Read-only' and characterizes the return as 'compact structured data', which is genuine behavioral context. However, it omits any mention of permissions, pagination behavior, or truncation when the limit is hit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, no filler, with the core action front-loaded and the read-only caveat appended. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with full schema coverage and no output schema, the description is nearly complete: it names the resource and notes the return shape. Only the lack of guidance on the limit parameter and pagination keeps it short of full completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both issue_key and limit are already documented in the schema (including the DEMO-123 format example). The description adds no parameter-level detail beyond that, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: fetch comments for a Jira issue. An agent can clearly tell what it returns. It does not differentiate itself from siblings like get_issue, but the resource name is distinct enough to disambiguate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use guidance or alternatives. The phrase 'for a Jira issue' implies it requires a known issue key, but there is no statement about when to prefer this over get_issue or search_issues, leaving usage to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_issueA

Fetch a single Jira issue by key (e.g. DEMO-123) as compact structured data: summary, description, status, type, priority, acceptance criteria (if configured), comments, and linked issues. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
issue_keyYesJira issue key, e.g. DEMO-123

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose 'Read-only' plus the shape of what comes back. However, it is silent on behavior for a missing/invalid key, permission requirements, and whether the response is paginated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence delivers the action, identifier format, and return contents with little waste. The field list is somewhat long but each item is informative rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with no output schema, the description usefully enumerates the returned fields and flags read-only behavior, which is enough for correct invocation. Missing details are limited to error and permission behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter's format (DEMO-123) is already documented in the schema, so the description's repeated example adds no new meaning. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a single Jira issue by key') and scopes it to one issue, which cleanly separates it from the plural sibling search_issues. The return-field enumeration reinforces what the tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The key-based retrieval and the example key imply the usage context, but there is no explicit statement of when to prefer this over search_issues, get_related_issues, or get_comments, nor any exclusions. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_my_open_issuesA

List unresolved Jira issues assigned to the authenticated user. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax issues to return

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden, and it does disclose the key safety trait ('Read-only'). However it says nothing about ordering, pagination behavior, or what happens when limit is omitted, which matters for a listing tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero waste, with the purpose and scope front-loaded and the read-only trait appended where it is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter read tool with no output schema, the description covers what it returns and its safety profile. Only the default/pagination behavior of 'limit' is left unstated, a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single 'limit' parameter, so the baseline is 3. The description adds no meaning beyond the schema — no default value, no note on how many issues are returned when limit is unset.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List), resource (Jira issues), and two scoping constraints (unresolved, assigned to the authenticated user). Those constraints cleanly separate it from get_issue (single issue) and search_issues (arbitrary queries), so an agent can route without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The scope ('assigned to the authenticated user', 'unresolved') implies when this tool is appropriate, but there is no explicit guidance on when to prefer it over search_issues or get_related_issues, and no stated exclusions. Implied usage only.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_project_metadataB

Fetch basic metadata for a Jira project (name, type, lead). Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_keyYesJira project key, e.g. DEMO

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden, and it does disclose the key trait: 'Read-only'. However, it says nothing about behavior for an invalid or unknown project_key, permission requirements, or whether the result is cached.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence that front-loads the verb and resource, followed by a two-word safety qualifier. Every clause earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter read tool with no output schema and no nested objects, the description covers purpose, scope of returned fields, and safety profile adequately. Only the invalid-key behavior is unaddressed, a minor gap at this complexity level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single project_key parameter is documented in the schema with a concrete example ('e.g. DEMO'). The description adds no syntax or format detail beyond that, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fetch') and resource ('basic metadata for a Jira project') and even enumerates the fields returned (name, type, lead), which is more than a tautology. It does not explicitly distinguish itself from the issue-centric siblings, but the resource difference is self-evident.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no mention of alternatives among siblings such as get_issue or search_issues. The agent must infer that this is the tool for project-level lookups rather than issue-level ones.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_issuesB

Search Jira issues using JQL (Jira Query Language) and return compact summaries. Read-only; results are capped by JIRA_MAX_SEARCH_LIMIT.

ParametersJSON Schema
NameRequiredDescriptionDefault
jqlYesJQL query, e.g. "project = DEMO AND status = \"In Progress\""
limitNoMax issues to return

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It does disclose two useful traits — 'Read-only' and the JIRA_MAX_SEARCH_LIMIT cap — but says nothing about pagination, ordering, or what the compact summaries contain.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the core action and the read-only/limit constraints front-loaded. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read tool with full schema coverage and no output schema, the description covers action, safety, and the result cap. The main gap is the vague 'compact summaries' and no note on pagination or result ordering.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both params (jql, limit) are documented in the schema, so the baseline is 3. The description only echoes JQL and the limit cap without adding syntax, defaults, or interaction detail beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search Jira issues') plus the mechanism (JQL) and the output shape ('compact summaries'). This separates it from get_issue/get_comments in practice, but it never explicitly names or contrasts those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use statement and no mention of alternatives such as get_my_open_issues or get_issue. Usage is only implied by the word 'search' — an agent must infer that this is the multi-issue query tool rather than a single-issue fetch.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.1.0
    • First observedget_comments
    • First observedget_issue
    • First observedget_my_open_issues
    • First observedget_project_metadata
    • First observedget_related_issues
    • First observedsearch_issues

TDQS

A3.7/5.0

Scored across 6 tools

Disambiguation4/5

Most tools have clearly distinct targets (single issue, JQL search, comments, links, my issues, project metadata). However, get_issue already returns comments and linked issues, so it partially overlaps with get_comments and get_related_issues, and get_my_open_issues is essentially a preset of search_issues. Descriptions do help clarify the intended use cases.

Naming Consistency4/5

All names use snake_case with a verb_noun structure (get_issue, get_comments, get_related_issues, get_project_metadata, get_my_open_issues). The only deviation is search_issues, which is still readable and semantically appropriate for a query action rather than a fetch.

Tool Count5/5

Six tools is well-scoped for a focused read-only Jira integration. Each tool maps to a distinct read operation with no filler or redundancy beyond the mild overlap noted.

Completeness4/5

The read-only surface covers the core read paths: fetch, search, comments, links/subtasks, assigned work, and project metadata. Minor gaps exist for read-only needs like attachments, worklogs, or listing all accessible projects, but these are workable omissions.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Provides tools for AI assistants to interact with JIRA APIs, enabling them to read, create, update, and manage JIRA issues through standardized MCP tools.
    6
    6 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server that provides AI agents structured access to Jira Cloud, enabling project listing, sprint overview, issue retrieval, and JQL search.
    60 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A local-only MCP server providing safe, typed Jira tools for AI agents via Atlassian ACLI, enabling search, get issue, add comment, and transition issues with policy guardrails.
    MIT