jira-readonly-mcp
Integrates with Atlassian Jira (Cloud or Server/Data Center) via its REST API, using API tokens or Personal Access Tokens for authenticated read-only access to issues and projects.
Provides read-only access to a Jira instance, with tools for retrieving issues, running JQL searches, fetching comments, related issues, assigned open issues, and project metadata.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jira-readonly-mcpsummarize DEMO-123 and its linked issues"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.tsexposes exactly one HTTP method:get(). There is nopost/put/patch/deletemethod anywhere in the codebase for a compromised or confused tool call to reach. Every outgoing request also passes throughassertReadOnlyMethod(), which throws if the method is anything butGET/HEAD. This is enforced in code, not by asking the model nicely — seetests/guard.test.tsandtests/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.tsbefore 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 |
| Full compact view of one issue: summary, description, status, type, priority, acceptance criteria (if configured), comments, and linked issues. |
| Runs a JQL query, returns compact rows (key, summary, status, type, priority, assignee). Result count is capped. |
| Comments on an issue as |
| Linked issues, subtasks, and parent for an issue. |
| Unresolved issues assigned to the authenticated user. |
| 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 buildThis 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=infoTwo 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): sendsAuthorization: Basic base64(user:token). This is the standard way to authenticate to Jira Cloud —JIRA_USERNAMEis your Atlassian account email,JIRA_TOKENis an API token from https://id.atlassian.com/manage-profile/security/api-tokens.Bearer (
JIRA_TOKENonly, noJIRA_USERNAME): sendsAuthorization: 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_issuesusing JQLproject = 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.jsThe 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.jsInspector 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, setJIRA_API_VERSION=3in.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 theenvironmentblock 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). TryJIRA_AUTH_TYPE=basicorJIRA_AUTH_TYPE=bearerexplicitly to rule out mis-detection."Jira returned a non-JSON response" — usually means
JIRA_BASE_URLis wrong (e.g. pointing at a login page or reverse proxy), or the wrongJIRA_API_VERSIONfor your deployment.Empty
linksarray you expected to be populated — Jira only returnsissuelinkswhen 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.acceptanceCriteriais alwaysnull— setJIRA_ACCEPTANCE_CRITERIA_FIELDto 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
commandis an absolute path todist/index.jsand that you rannpm 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 testTests 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 suiteLicense
MIT — see LICENSE.
Available Tools
6 toolsget_commentsB
Fetch comments for a Jira issue as compact structured data. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max comments to return | |
| issue_key | Yes | Jira issue key, e.g. DEMO-123 |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| issue_key | Yes | Jira issue key, e.g. DEMO-123 |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max issues to return |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| project_key | Yes | Jira project key, e.g. DEMO |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| jql | Yes | JQL query, e.g. "project = DEMO AND status = \"In Progress\"" | |
| limit | No | Max issues to return |
TDQS
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.
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.
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.
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.
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.
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.
6 tool updates
v0.1.0- First observed
get_comments - First observed
get_issue - First observed
get_my_open_issues - First observed
get_project_metadata - First observed
get_related_issues - First observed
search_issues
TDQS
Scored across 6 tools
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.
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.
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.
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
Related MCP Connectors
Read-only MCP tools for AI agent discovery, structured resources, and NIULAI information.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides tools for AI assistants to interact with JIRA APIs, enabling them to read, create, update, and manage JIRA issues through standardized MCP tools.66 npm3MIT
- AlicenseAqualityDmaintenanceProvides read-only access to JIRA REST API, enabling LLMs to query and retrieve information from JIRA instances.1412 npmMIT
- AlicenseNot gradedqualityCmaintenanceA read-only MCP server that provides AI agents structured access to Jira Cloud, enabling project listing, sprint overview, issue retrieval, and JQL search.60 npmMIT
- AlicenseNot gradedqualityDmaintenanceA 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