
Zephyr Scale Mcp
io.github.vilaaboPublished by GitHub account vilaabov1.0.0Updated Oct 24, 2026
Zephyr Scale on self-hosted Jira Server/DC: test cases, cycles, executions, plans and attachments
Overview
Local MCP server giving an AI assistant 54 tools to manage Zephyr Scale test cases, cycles, executions, plans and attachments on self-hosted Jira Server/Data C
- What you can do
- Create, read, search, update, clone, move and delete test cases, including step-by-step, plain-text and BDD scripts, bulk creation and issue linking with coverage reports. Create, read, search, delete and rebuild test cycles, with summaries and paged results. Record, update and bulk-create executions, and fetch the latest result for a case. Create, read, update, search and delete test plans. Create and rename folders, and upload, list, download and delete attachments. Publish automation and Cucumber result ZIPs, export BDD feature files, and run health checks, environment and Jira user lookups.
- When to use it
- Useful when your team keeps test management in Zephyr Scale on an on-premise Jira Server or Data Center instance and you want an assistant to draft cases, record results, trace issue coverage or import automation reports. It does not work with Zephyr Scale Cloud or Zephyr Squad.
- Requirements
- Runs locally via npx with Node.js 20 or newer. Needs a reachable Jira Server/DC instance with the Zephyr Scale plugin, set through JIRA_BASE_URL, plus either a Personal Access Token in JIRA_PAT (default mode) or JIRA_USERNAME and JIRA_PASSWORD with JIRA_AUTH=basic. Optional settings cover project key, timeouts, retries, read-only mode and internal API tools.
Installation
In SourceWeft
- Open Zephyr Scale Mcp in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
zephyr-scale-mcp
MCP server for Zephyr Scale on self-hosted Jira Server / Data Center (formerly TM4J). It gives an AI agent — Claude Code, Claude Desktop, Cursor, any MCP client — 54 tools over your test management: test cases, folders, test cycles, executions, test plans, attachments and automation imports, through the Zephyr Scale REST API v1 at {JIRA_BASE_URL}/rest/atm/1.0.
[Node] [TypeScript] [Tests] [License] [API]
npm: zephyr-scale-mcp · MCP Registry: io.github.vilaabo/zephyr-scale-mcp · Русская версия →
⚠️ Scope: Server / Data Center only. Zephyr Scale Cloud (API v2) and Zephyr Squad are different APIs and are out of scope — this server will not work against them.
Why this exists
Most Zephyr MCP servers target the Cloud API. If your Jira is on-premise you get the v1 API instead, and v1 has teeth: test runs are immutable after creation, folders cannot be listed, statuses are case-sensitive internal names, BDD scripts reject a Feature: header, and older plugin builds are missing whole endpoints. This server encodes that knowledge instead of leaving the agent to discover it one 400 at a time.
- 54 tools (42 public + 12 opt-in internal-API tools), each with a description that states the endpoint, the constraints a caller cannot guess, and the exact response shape.
- Composite tools for the API's blind spots —
add_test_stepsmerges steps by id (read → merge → write) so nothing is silently deleted;recreate_test_run_with_itemsworks around run immutability and can carry the last results over;get_issue_test_coverage,get_test_run_summary,clone_test_case,move_test_cases_to_folder. - Degradation on older builds — automatic fallback when the paginated results endpoint is absent, and a per-item fallback when the bulk create endpoint is broken. Both were found on a real legacy instance, not in a changelog.
- Plumbing that fails loudly — strict zod input validation,
Retry-After-aware retries with exponential backoff, error messages carrying actionable hints, read-only mode, secrets kept out of logs and tool output. - 1181 unit and contract tests (vitest + msw, no network) plus a gated end-to-end scenario against a real instance.
Quick start
Requirements: Node.js >= 20, Jira Server/DC with the Zephyr Scale plugin, and a Personal Access Token (Jira 8.14+) or a username/password pair.
Nothing to clone — the package is on npm. Claude Code:
Claude Desktop / any MCP client (claude_desktop_config.json, .mcp.json):
Running from source instead
Then point the client at the build: "command": "node", "args": ["/path/to/zephyr-scale-mcp/dist/index.js"].
ZEPHYR_ALLOW_INTERNAL_API=trueis optional and recommended. It registers 12 extra tools that reach the things the public API cannot do at all: editing a test run in place — renaming or moving it (update_test_run) and adding or removing cases without changing its key (add_test_cases_to_run,remove_test_cases_from_run) — plus listing the folder tree (get_folder_tree), deleting folders (delete_folder), editing older executions (update_test_result_by_id) and reading the exact status names the API silently expects (get_status_options). These call the same undocumented/rest/tests/1.0endpoints the Jira UI itself uses; the vendor does not support them and they may differ or be absent on another Zephyr Scale version. Leave the flag off if that trade-off is not acceptable — the other 42 tools are unaffected.
Then ask the agent to run health_check. It verifies connectivity and credentials via GET /rest/api/2/myself and, when ZEPHYR_DEFAULT_PROJECT_KEY is set, that the Zephyr plugin answers on /rest/atm/1.0.
What you can ask your agent to do
- "Create the folder
/Regression/Paymentsand add step-by-step test cases for the checkout flow described in this document." - "Find every Draft case in
/Regression, review them, and set the ready ones to Approved." - "Create a cycle for sprint 42 with all smoke cases, then record the results from this report — step by step where the script has steps."
- "Which test cases cover PROJ-123, and when did each of them last pass?" — traceability from the issue to its cases and their latest executions.
- "Take this ZIP of Cucumber JSON reports and publish it as a new cycle in PROJ." — automation import; scenarios are matched to BDD cases by their
@TestCaseKey=PROJ-T1tag. - "Add two steps to PROJ-T55 after step 3." — existing steps and their ids survive.
- "Recreate cycle PROJ-R7 with three more cases, keep the results, and delete the original."
Configuration
Two guarantees the tests cover: JIRA_PAT and JIRA_PASSWORD never appear in logs, tool output or error messages — in any encoding they can take on the way out: raw, JSON-escaped, or the base64 basic-auth token (error text carries the method and path only — never the query string, which may contain data) — and stdout is reserved for the MCP protocol, every log line goes to stderr. One deliberate exception: a secret shorter than six characters is left alone, because redacting it would corrupt unrelated output while protecting nothing; the server warns about it at startup.
Configuration is validated at startup: all problems are reported at once and the process exits with a non-zero code rather than starting half-configured.
Tools
54 tools. The 42 public ones are always registered; the 12 in the last group only with ZEPHYR_ALLOW_INTERNAL_API=true.
Test cases — 13 tools
Test cycles (test runs) — 7 tools
Executions (test results) — 4 tools
Items that exist several times in a run (per environment or per assignee) are disambiguated with matchEnvironment / matchUserKey, sent as query parameters.
Test plans — 5 tools
Folders — 2 tools
Attachments — 4 tools
Automation — 3 tools
Service and diagnostics — 4 tools
UNOFFICIAL — internal API, opt-in — 12 tools
Registered only with ZEPHYR_ALLOW_INTERNAL_API=true. These call /rest/tests/1.0, the undocumented API behind the Jira UI. The vendor does not support it: endpoints may differ or be absent on another Zephyr Scale version, and a 404/405 from one of these tools means exactly that. Every request shape below was either captured from the Jira UI's own traffic or verified live against a real instance — never guessed. Errors from this layer carry a hint saying so.
Working around API v1
These are the constraints the server is built around. Every tool description repeats the ones relevant to it, so the agent sees them at call time.
- Test runs are immutable. There is no
PUT /testrun: a run cannot be renamed, moved, or have cases added or removed. Its items are fixed at creation and the run status is derived from item statuses. Escape hatches:recreate_test_run_with_items(public, produces a new key) or the internalupdate_test_run/add_test_cases_to_run/remove_test_cases_from_run(same key). - Folders are never created implicitly.
create_test_case,create_test_runandcreate_test_planfail with 400 on an unknown folder. Folders also cannot be listed through the public API, and renaming needs the numeric id returned bycreate_folder— orget_folder_treewith the internal API enabled. owner/executedBy/assignedTotake a Jira user key (JIRAUSER10000), never a username or an e-mail.find_jira_userresolves it.- TQL is strict: spaces around operators are mandatory, string values go in double quotes,
ANDis the only connector (noOR), and folder paths start with/. Test runs are searchable byprojectKeyandfolderonly. For single/multi-choice custom fields=does not work — useIN. - Statuses, priorities and environments are case-sensitive internal names. Built-in statuses are shown localized in the UI (the label you see for
Draftmay be a translation) while custom ones use their literal names —get_status_optionsshows what the API actually expects. A wrong execution status is silently ignored by the public API. - A BDD script is the scenario body only — bare
Given/When/Then/And/Butlines. Text wrapped inFeature:/Scenario:is rejected with400 Invalid BDD Script; the wrapper is generated on export. STEP_BY_STEPsteps are synchronized by id onPUT: a step without an id is created, a step with an id is updated, and every stored step missing from the list is deleted. Always send the complete final list with ids carried over fromget_test_case— or letadd_test_stepsdo the read-merge-write.- Deprecated fields are intentionally not accepted: use
issueLinksinstead ofissueKey,actualEndDateinstead ofexecutionDate,executedByinstead ofuserKey.
Quirks of older plugin builds
All of the following was observed live on a real legacy Zephyr Scale Server instance and is covered by tests.
- Cycle keys may use the
-Cprefix (PROJ-C34) instead of-R. Every run-key parameter takes the key as-is, so pass whatever your instance shows. GET /testrun/{key}/testresults/pagemay not exist.get_test_run_resultsandget_test_run_summaryfall back to the deprecated flat endpoint and paginate client-side, adding anoteto the response. A run that genuinely does not exist still surfaces as a 404.- An overall
statussent together withscriptResultsis ignored. Send the step results first, then set the overall status withupdate_last_test_result. POST /testcase/link-issuesmay answer 500. Link throughupdate_test_casewithissueLinksinstead.POST /testcase/bulkmay answer HTTP 500 with an empty body for any payload while single creation works.create_test_cases_bulkfalls back to creating the cases one by one — on any5xx, and on a JSON404(which means "no such endpoint on this build", unlike the HTML404Jira serves when the plugin is absent) — and reports which ones succeeded (#1). Every other4xxis a payload error and is not retried.- Posting a result for a case that is not among the run's items silently adds it to the run on this build; other builds reject the call with 400/404. The result tools document both.
- The custom automation-results format is validated strictly.
{"version": 1, "executions": [{"source", "result", "testCase": {"key"}}]}works; extra per-execution fields such asexecutionTimeare rejected withInvalid Custom Format JSON file. Cucumber JSON reports work as-is when the scenario carries@TestCaseKey=PROJ-T1. download_feature_filesrequires thetqlquery parameter — the API rejects the call without it.- The last execution of a run item cannot be deleted.
delete_test_resultsrejects it; remove the item instead. - Custom fields may be absent entirely — the definitions endpoint then returns
[].
Development
The smoke scenario is skipped unless ZEPHYR_E2E=1. It needs a real JIRA_BASE_URL, credentials and a dedicated ZEPHYR_DEFAULT_PROJECT_KEY — it creates and deletes real entities and leaves /mcp-smoke-* folders behind, since the public API cannot delete folders.
Versioning and changelog
Version 1.0.0. Tool names, parameter names and response shapes are a public contract from this release on and change only in a major version. See CHANGELOG.md.
License
Source: README.md at commit 9c43dc5
Tools
0Version history
1- v1.0.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts