MCP (Model Context Protocol)#
Beta
The MCP server is currently in beta. While fully functional, the available tools, authentication mechanism, and protocol details may change in future releases. If you encounter any issues or have feedback, please contact the Zebrunner support team.
Zebrunner exposes an MCP server that allows AI assistants — such as Cursor, Claude Desktop, and other MCP-compatible clients — to interact with Zebrunner resources via natural language. Through MCP, an AI assistant can list, create, and update Test Cases, Test Runs, Test Suites, Shared Steps, and more on your behalf.
The MCP server uses the Streamable HTTP transport and is available at a dedicated endpoint on your Zebrunner workspace.
Prerequisites#
Before configuring an MCP client, make sure you have:
- Active Zebrunner user account with at least the Guest role in the target project (Engineer or higher for write operations).
- API Token — issued in the Account and profile → API Access section. You can assign a display name and an expiration date for each token.
- Workspace URL — the URL of your Zebrunner workspace (e.g.
https://mycompany.zebrunner.com).

Authentication#
The MCP server uses the same credentials as the Public REST API — your username (or email) and API Token.
Credentials are provided via HTTP headers that the MCP client sends with every request to the MCP server:
| Header | Value |
|---|---|
X-Zebrunner-Username |
Your Zebrunner username or email |
X-Zebrunner-Api-Token |
The API Token from the API Access section |
Note
The API Token is not your account password. If you use your regular password instead of an API Token, the request will be rejected.
Endpoint URL#
The MCP server endpoint for your workspace is:
Replace {workspace} with your actual workspace hostname — for example, https://mycompany.zebrunner.com/api/mcp.
Client configuration#
Cursor#
Create or edit the .cursor/mcp.json file in your project root (or configure globally in Cursor settings):
{
"mcpServers": {
"zebrunner": {
"url": "https://mycompany.zebrunner.com/api/mcp",
"headers": {
"X-Zebrunner-Username": "<your-username-or-email>",
"X-Zebrunner-Api-Token": "<your-api-token>"
}
}
}
}
Claude Desktop#
Claude Desktop's config file (claude_desktop_config.json) does not natively recognize remote MCP servers configured with url / headers — at startup it silently strips such entries from the file. Use the mcp-remote bridge instead, which exposes the remote server over the local stdio transport that Claude Desktop does support. You will need Node.js installed.
Edit the claude_desktop_config.json file (typically located at ~/Library/Application Support/Claude/ on macOS or %APPDATA%\Claude\ on Windows):
{
"mcpServers": {
"zebrunner": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mycompany.zebrunner.com/api/mcp",
"--header",
"X-Zebrunner-Username:<your-username-or-email>",
"--header",
"X-Zebrunner-Api-Token:<your-api-token>"
]
}
}
}
Restart Claude Desktop after saving. The Zebrunner tools will appear in the conversation's tool picker.
Tip
If you are on Claude Pro / Team / Max, you can alternatively add Zebrunner as a Custom Connector under Settings → Connectors → Add custom connector, paste the same endpoint URL, and provide the two headers in the dedicated fields. No mcp-remote bridge required in that case.
MCP Inspector (for testing)#
You can verify the connection using the MCP Inspector tool:
This opens a web UI (typically at http://localhost:6274) where you can:
- Select transport type Streamable HTTP.
- Enter the URL:
https://mycompany.zebrunner.com/api/mcp. - Add the
X-Zebrunner-UsernameandX-Zebrunner-Api-Tokenheaders. - Connect and browse the available tools.
Available tools#
The MCP server exposes the following tools, grouped by category:
Projects#
| Tool | Description |
|---|---|
list_projects |
Returns the projects the authenticated user has access to |
Projects are the central entity in Zebrunner, and almost every other tool is scoped to a single project via its projectKey (or numeric projectId). Use list_projects to discover those identifiers when the target project is not already clear from the request.
Test Cases#
| Tool | Description |
|---|---|
list_test_cases |
Returns a paginated, filterable list of Test Cases in a project |
get_test_case_by_id |
Returns full Test Case details (including steps) by numeric ID |
get_test_case_by_key |
Returns full Test Case details (including steps) by key (e.g. TC-1) |
create_test_case |
Creates a new Test Case within a Test Suite |
update_test_case_by_id |
Partially updates a Test Case by numeric ID (PATCH semantics) |
update_test_case_by_key |
Partially updates a Test Case by key (PATCH semantics) |
list_test_cases accepts a filter expression over: id, key, testSuite.id, title, description, priority.id, automationState.id, draft, deprecated, requirements, preConditions, postConditions, createdAt, createdBy.{id,username,email}, and any project Custom Field as customField.<systemName> (use list_custom_fields to discover the system names and types).
Test Suites#
| Tool | Description |
|---|---|
list_test_suites |
Returns a paginated list of Test Suites in a project |
get_test_suite |
Returns Test Suite details by numeric ID |
create_test_suite |
Creates a new Test Suite (can be nested) |
update_test_suite |
Fully replaces a Test Suite by numeric ID |
Shared Steps#
| Tool | Description |
|---|---|
list_shared_steps |
Returns a paginated list of Shared Steps groups |
create_shared_steps |
Creates a new reusable Shared Steps group |
Test Runs#
| Tool | Description |
|---|---|
list_test_runs |
Returns a paginated, filterable list of Test Runs |
get_test_run |
Returns Test Run details by numeric ID |
create_test_run |
Creates a new Test Run |
update_test_run |
Partially updates a Test Run (PATCH semantics) |
replace_test_run |
Fully replaces a Test Run (PUT semantics) |
close_test_run |
Closes a Test Run (irreversible) |
list_test_runs accepts a filter expression over: id, title, description, milestone.id, closed, requirements, configurations.{groupName,optionName}, createdAt, createdBy.{id,username,email}.
Test Run Test Cases#
| Tool | Description |
|---|---|
list_test_run_test_cases |
Returns all Test Cases in a Test Run with results |
add_test_run_test_cases |
Adds Test Cases to a Test Run (without results) |
import_test_run_test_case_results |
Imports Test Cases with execution results into a Test Run |
Test Case Settings#
| Tool | Description |
|---|---|
list_automation_states |
Returns Automation States configured for the project |
list_priorities |
Returns Priorities configured for the project |
list_custom_fields |
Returns Custom Fields configured for the project |
create_custom_field |
Creates a new Custom Field definition |
Test Run Settings#
| Tool | Description |
|---|---|
list_result_statuses |
Returns Result Statuses configured for the project |
list_configuration_groups |
Returns Configuration Groups and their Options |
list_environments |
Returns Environments configured for the project (referenced by Test Runs) |
Launches#
| Tool | Description |
|---|---|
list_launches |
Returns a paginated, filterable list of automation launches in a project |
list_launch_attempts |
Returns the full list of attempts (initial run + reruns) for a single launch |
add_comment_to_launches |
Bulk-adds the same comment to multiple launches (and marks them as reviewed) |
assign_launches_to_milestone |
Bulk-assigns multiple launches to a single milestone |
unassign_launches_from_milestone |
Bulk-removes the milestone assignment from multiple launches |
get_launch_relaunch_config |
Inspects a finished launch and returns everything needed to relaunch it into the same launch. Read-only; choose rerunScope=FAILURES (default), ALL, or SPECIFIC_TESTS with a testIds list |
rebuild_launch_job |
Relaunches a CI-triggered launch by re-triggering its CI job with the given parameters, reporting results back into the same launch (use after get_launch_relaunch_config returns mode=CI) |
list_launches accepts a filter expression over: id, name, status, environment, platform, browser, locale, reviewed, startedAt, milestone.id, milestone.name.
Milestones#
| Tool | Description |
|---|---|
list_milestones |
Returns a paginated, filterable list of milestones in a project |
create_milestone |
Creates a new milestone in a project |
list_milestones accepts a filter expression over: name, completed.
Tests within launches#
| Tool | Description |
|---|---|
list_tests_by_launch |
Returns a paginated, filterable list of tests in a single launch |
get_test_execution_history |
Returns up to 50 latest historical executions of the same test method (default 10) |
get_test_issue_assignment_history |
Returns the full chronological LINK / UNLINK history of issue references for a test |
assign_issue_to_tests |
Bulk-assigns an issue tracker reference (e.g. a Jira issue) to multiple tests |
add_comment_to_tests |
Bulk-adds the same comment to multiple tests (one comment per test, upsert) |
list_tests_by_launch accepts a filter expression over: id, name, status, startedAt, maintainer.{id,username,email}.
Test logs and screenshots#
| Tool | Description |
|---|---|
list_test_logs |
Returns a paginated list of log entries reported for a single test execution |
list_test_screenshots |
Returns a paginated list of screenshots captured during a single test execution |
list_test_logs_and_screenshots |
Returns a paginated unified stream that interleaves logs and screenshots for one test |
Repository tree and settings#
| Tool | Description |
|---|---|
get_repository_tree |
Returns the entire automation tree for a project (repositories → launchers → presets → schedules + webhooks) with minimal identifying fields only |
list_repository_branches |
Returns live git branches for a repository (fetched from the underlying git provider) |
list_engine_capabilities |
Returns Zebrunner Engine provider-capability names and compatible browser / platform / device combinations |
list_instance_types |
Returns Zebrunner Engine instance types (CPU / memory profiles) available to the project |
Launchers#
| Tool | Description |
|---|---|
list_launchers |
Returns full launchers (id, name, gitRepoId, config) for a project. Optional ids filter narrows the result; otherwise returns every launcher |
create_launcher |
Creates a new launcher inside an existing git repository |
replace_launcher |
Full PUT — replaces a launcher (name + config). Prefer patch_launcher_configs when changing only a few fields |
patch_launcher_configs |
Batch PATCH for launcher configurations. Up to 100 entries per request. envVars / providerCapabilities / customCapabilities merge per key (null value removes the key) |
delete_launchers |
Bulk-deletes launchers by ID. CASCADE — child presets, schedules, and webhooks are also removed |
launch_tests |
Starts one automation launch from a launcher / preset with the (possibly edited) config inline. Returns the launch id; call once per launch (no batch) |
Presets#
| Tool | Description |
|---|---|
list_presets |
Returns full presets including config, schedules, and webhooks. Optional ids filter narrows the result; otherwise returns every preset |
create_preset |
Creates a new preset under an existing launcher |
replace_preset |
Full PUT — replaces a preset (name + config). Prefer patch_preset_configs when changing only a few fields |
patch_preset_configs |
Batch PATCH for preset configurations. Up to 100 entries per request. Same map-merge semantics as patch_launcher_configs |
delete_presets |
Bulk-deletes presets by ID. CASCADE — child schedules and webhooks are also removed |
Schedules#
| Tool | Description |
|---|---|
create_schedule |
Adds a Quartz-cron schedule to an existing preset. A preset can have at most 5 schedules |
replace_schedule |
Full PUT — replaces a schedule. The owning preset and the schedule type cannot be changed |
delete_schedules |
Bulk-deletes schedules by ID |
Webhooks#
| Tool | Description |
|---|---|
create_webhook |
Adds a webhook to an existing preset. Optional base64 HMAC secret turns the webhook into a signed-callable one. The returned webhook id is a string |
replace_webhook |
Full PUT for name. base64SecretKey is ternary: null = leave secret unchanged, "" = clear (webhook becomes unauthenticated), non-empty base64 = replace the secret. Webhook id is passed as a string |
delete_webhooks |
Bulk-deletes webhooks by ID (passed as strings). Unknown IDs are silently skipped |
Files#
| Tool | Description |
|---|---|
upload_file |
Uploads a file (base64-encoded, max 100 KB) and returns its UUID for use in attachments |
get_file_metadata |
Returns metadata for a single file by UUID (name, content type, size) |
list_files_metadata |
Returns metadata for up to 100 files in a single call. Missing UUIDs are silently dropped |
get_image_file_content |
Downloads an image file (image/*) and returns its bytes as native MCP ImageContent. Default cap: 5 MB |
get_text_file_content |
Downloads a text-like file (text/*, application/json, application/xml, etc.) and returns it as MCP TextContent. Cap: 128 KB |
See Working with files for end-to-end guidance on uploading large files and on choosing the right inspection tool.
Available prompts#
In addition to tools, the MCP server exposes a set of pre-built prompts — guided multi-step recipes that an AI assistant can invoke (for example via Cursor's / prompt picker or Claude Desktop's slash commands). Each prompt expands into a USER-roled message that walks the assistant through the right sequence of Zebrunner tools, so common QA workflows produce consistent output regardless of which model is driving the conversation.
Automation QA recipes#
| Prompt | Description |
|---|---|
triage_failed_launch |
Investigate failures in a single automation launch end-to-end (failed/aborted tests, logs, screenshots, history) and summarise root-cause hypotheses. Read-only. |
bulk_link_failures_to_issue |
After triage, cluster identical failures and bulk-link them to an issue tracker entry with a shared comment and a launch review. Mutates Zebrunner data — gated behind explicit user confirmation. |
compare_launches |
Compare two specific automation launches (e.g. before/after a build) and produce a regression diff: new failures, newly fixed, still failing. Read-only. |
analyze_suite_history |
Pipeline-level analysis of the same automation suite over its last N runs (exact-name lookup): classify per-test as new regression / chronic / flaky / newly fixed. Read-only. |
relaunch_launch |
Relaunch a finished automation launch — re-run its failed tests, all tests, or a hand-picked set of tests, reporting results back into the same launch. Works for both launcher- and CI-triggered launches. |
bulk_edit_launcher_configs |
Bulk-edit launcher and / or preset configurations safely: loads current state, computes a per-item diff, asks for explicit confirmation, then applies the patches in a single batch. Mutates Zebrunner data — gated behind explicit user confirmation. |
launch_tests |
Launch automated tests from a launcher / preset, with optional config edits: finds the target by name, fetches its config, applies changes, confirms with the user, then launches (sequentially for multiple launches). Mutates Zebrunner data — gated behind explicit user confirmation. |
Manual QA / TCM recipes#
| Prompt | Description |
|---|---|
submit_test_run_results |
Submit execution results into an existing TCM Test Run via import_test_run_test_case_results, with status mapping discovered from the project's allowed statuses. |
create_test_cases_from_description |
Create one or more TCM Test Cases from a free-form description of what should be covered, de-duplicating against existing cases in the target suite. |
create_test_cases_from_requirement |
Create TCM Test Cases from a tracked requirement (Jira / Azure DevOps ticket, GitHub issue, Confluence page, etc.); Jira and Azure DevOps cases are linked back to the ticket for traceability. |
create_test_cases_for_suite_gaps |
Extend an existing populated TCM Test Suite by finding missing coverage (negative paths, boundary inputs, error states, permissions, …) and creating cases to fill the gaps. |
Prompts are gated by your organization's enabled features in the same way as tools — automation prompts are visible only when TAM (Test Automation Management) is enabled, TCM prompts only when TCM is enabled, and launcher-editing prompts only when the Launcher add-on is enabled. Hidden prompts simply do not appear in the client's prompt picker.
Working with files#
Several Zebrunner resources reference attached files by UUID — screenshots from failed automated tests, attachments on Test Cases, logs uploaded by the runner, files referenced in Shared Steps, and so on. Likewise, several mutation tools (such as create_test_case, create_shared_steps, import_test_run_test_case_results) accept attachments by UUID. The MCP server provides a small family of tools to cover both directions plus a dedicated HTTP endpoint for the cases where the LLM context is the wrong place for the file.
Uploading files#
The built-in upload_file tool handles uploads automatically for small files (up to 100 KB). Because the file content is passed as base64 through the LLM context, larger files would consume too many tokens. For bigger files, use one of the following approaches:
| Approach | When to use |
|---|---|
| Built-in shell / terminal | AI coding assistants with terminal access (Cursor, Windsurf, VS Code Copilot, etc.) can run a curl upload command directly, read the response, and extract the file UUID. This is the simplest and most common approach. |
| Curl MCP Server | If your AI client supports multiple MCP servers but has no shell access, add the Curl MCP Server alongside Zebrunner MCP. The AI can execute the upload command via the Curl MCP and use the returned UUID with Zebrunner tools. |
| Other HTTP / shell MCPs | MCP servers such as Desktop Commander or shell-command-mcp provide general shell access that the AI can use to perform the upload. |
| Manual upload | Upload the file yourself (e.g. via Postman or curl) and paste the returned UUID into the conversation. The AI will use it in subsequent tool calls. |
The upload endpoint, credentials, and response format are fully described in the upload_file tool description — the AI assistant already has all the details it needs to guide you or to perform the upload itself.
Tip
The upload endpoint uses the same credentials as the MCP server (username and API token). If the AI assistant does not have access to these credentials, it will ask you to provide them or to perform the upload manually.
Inspecting files in the MCP context#
Once you have a UUID, the AI assistant can inspect the file with one of the four download tools without leaving the conversation:
| Situation | Recommended tool |
|---|---|
| You have a single UUID and need to know what kind of file it is | get_file_metadata |
| You have a list of UUIDs (e.g. all attachments of a Test Run) and want bulk metadata | list_files_metadata |
The field name implies an image (screenshotFileUuid, attachment of a UI test, …) |
get_image_file_content directly |
The field name implies text (logFileUuid, *.log, structured artifact, …) |
get_text_file_content directly |
| You need a video, archive, PDF, or any other binary that does not fit MCP context | Direct download endpoint |
The AI assistant does not need to call get_file_metadata first when the file kind is obvious from the originating field — get_image_file_content and get_text_file_content self-validate the content type and respond with a clear error if the assumption is wrong.
Both content tools are capped to keep the LLM context manageable:
| Tool | Cap |
|---|---|
get_image_file_content |
5 MB |
get_text_file_content |
128 KB |
When a file exceeds the cap, the tool does not return any bytes. Instead, it returns an isError = true result containing the actual cap and instructions on how to fetch the file directly from the Direct download endpoint — for example, via a separate HTTP / shell MCP that can stream and chunk the content.
get_text_file_content decodes bytes as UTF-8 with the malformed-input / unmappable-character replacement strategy — invalid sequences become the U+FFFD replacement character. Files that are not actually UTF-8 (e.g. Latin-1, UTF-16) will still be returned but may contain visible replacement characters; in that case download via the Direct download endpoint and decode with the correct charset locally.
Direct download endpoint#
Any file uploaded to Zebrunner can be downloaded directly via:
Authentication is HTTP Basic with the same username and API token that the MCP server uses. The response body contains the raw binary content; the Content-Type header reflects the MIME type detected at upload time, and the Content-Disposition header carries the original filename.
curl -L 'https://mycompany.zebrunner.com/api/public/v1/files/01919f03-1146-7931-bccd-5c54c7274f7a' \
-u '<username>:<api-token>' \
--output my-file.png
Use this endpoint whenever the file is too large for the LLM context, when the AI client cannot natively render the MIME type, or when you want to stream the raw bytes from scripts.