Skip to main content
Glama

testrail-mcp

An MCP server for TestRail that goes beyond CRUD: it prepares everything an MCP client needs to generate real test cases from Jira tickets, Confluence pages, or any free-form spec — and pushes them back to TestRail.

Built on the official Python MCP SDK (FastMCP). Designed to plug into Claude Desktop, Claude Code, Cursor, or any other MCP-capable client.

No ANTHROPIC_API_KEY required. The server never calls an LLM. It fetches data (Jira/Confluence/TestRail), bundles in house-style anchors, and returns it with instructions for your MCP client. The LLM work happens in your client (Claude Desktop / Cursor / etc.) on your existing subscription — you pay once.

What it gives you

CRUD over TestRail

  • list_projects — projects visible to the user

  • list_suites — suites under a project

  • search_test_cases — list cases under a project / suite / section, optionally filter by title substring

  • get_test_case — fetch one case by ID

  • create_test_case — create a case in a section

  • get_or_create_section — resolve a path like Auth > Login > Edge Cases, creating missing nodes

Preparation tools — fetch + bundle data, hand off to your MCP client's LLM

  • prepare_cases_from_text — feed any spec/PRD/bug-report text → returns spec + house-style anchors + schema + instructions for the client to generate cases.

  • prepare_cases_from_jira — pass a Jira issue key (e.g. ABC-123); server fetches summary, description, comments, subtasks, walks the ADF tree.

  • prepare_cases_from_confluence — pass a Confluence page ID; HTML body stripped to plain text.

  • preview_house_style — see the 5 sibling cases the server will use as in-context style anchors.

  • add_test_cases_bulk — once the LLM has the cases array, push them all into TestRail in one call (with auto section-hierarchy creation).

All three prepare_cases_* tools pull a few existing cases from the target section as house-style examples by default, so generated cases match local title casing, step granularity, and expected-result phrasing. Override with house_style_section_id to draw style from a different "golden" section, or set house_style=False to skip.

Related MCP server: qa-mcp

Quick start

Run with uvx (recommended — no clone, no venv)

Once the package is on PyPI:

uvx testrail-mcp-server

For local development from a checkout:

git clone https://github.com/Sergey-Bl/testrail-mcp
cd testrail-mcp
uv venv --python 3.12
uv pip install -e .
cp .env.example .env   # fill in TestRail / Jira / Anthropic keys
npx @modelcontextprotocol/inspector python server.py

This opens a local web UI where each tool can be called by hand. Use it to verify auth and tool wiring before you plug into a client.

Use in Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "testrail": {
      "command": "uvx",
      "args": ["testrail-mcp-server"],
      "env": {
        "TESTRAIL_BASE_URL": "https://your-org.testrail.io",
        "TESTRAIL_USER": "you@example.com",
        "TESTRAIL_API_KEY": "...",
        "TESTRAIL_PROJECT_ID": "1",
        "TESTRAIL_SUITE_ID": "1",
        "JIRA_BASE_URL": "https://your-org.atlassian.net",
        "JIRA_USER": "you@example.com",
        "JIRA_API_TOKEN": "..."
      }
    }
  }
}

Restart Claude Desktop. The testrail server should appear in the tools menu.

Use in Claude Code

claude mcp add testrail -- uvx testrail-mcp-server

(You'll still need to provide env vars — either via claude mcp add --env KEY=VALUE flags or a .env in the working directory.)

Use in Cursor

In ~/.cursor/mcp.json:

{
  "mcpServers": {
    "testrail": {
      "command": "uvx",
      "args": ["testrail-mcp-server"],
      "env": { "TESTRAIL_BASE_URL": "...", "TESTRAIL_USER": "...", "TESTRAIL_API_KEY": "..." }
    }
  }
}

Configuration

Env var

Required

Purpose

TESTRAIL_BASE_URL

yes

e.g. https://your-org.testrail.io

TESTRAIL_USER

yes

TestRail account email

TESTRAIL_API_KEY

yes

from My Settings → API Keys

TESTRAIL_PROJECT_ID

optional

default project ID for tools that take it

TESTRAIL_SUITE_ID

optional

default suite ID

TR_TEMPLATE_ID

optional

default template (2 = "Test Case (Steps)")

TR_TYPE_ID

optional

default case type

TR_PRIORITY_ID

optional

default priority (3 = Medium)

JIRA_BASE_URL

optional

only for prepare_cases_from_jira

JIRA_USER

optional

Jira account email

JIRA_API_TOKEN

optional

https://id.atlassian.com/manage-profile

CONFLUENCE_BASE_URL

optional

only for prepare_cases_from_confluence

CONFLUENCE_EMAIL

optional

defaults to JIRA_USER

CONFLUENCE_API_TOKEN

optional

defaults to JIRA_API_TOKEN

Example: from a Jira ticket straight into TestRail

In Claude Code or Claude Desktop, after the server is registered:

Generate test cases from ABC-123 and put them under Auth > Login > Smoke.

The server walks the section path (creating missing nodes), pulls the Jira ticket, generates ~15-30 cases, then bulk-creates them with house-style defaults (template 2, type 7, priority 3). Reply contains every new case ID.

Tool reference

In addition to the basics above:

Test-case authoring & QA

  • prepare_feature_bootstrap — one-shot: ingest a Confluence page / Jira ticket / raw spec, plan the suite + section, fetch house-style anchors. Hand it all back to the client LLM with step-by-step instructions for generation + push.

  • dedupe_against_section — flag generated cases that look like duplicates of cases already in a target section (title-token containment; configurable threshold).

  • prepare_lint — return the case batch + lint instructions; the client LLM reviews and reports vague titles, generic expecteds, combined steps, etc.

  • prepare_coverage_gaps — return the spec + case titles + instructions; the client LLM lists testable behaviours not covered.

  • list_sections, find_populated_section, create_suite, update_case — CRUD helpers.

Test-run management & reporting

  • list_runs, get_run, get_tests_in_run, get_results_for_run — read-side access.

  • create_run, update_run, close_run — write-side. Pair with CI to auto-create a run per build.

  • add_result, add_bulk_results — post results back from automation. Status accepts either a string ("passed", "failed", "blocked", "retest") or a TestRail status_id.

  • prepare_run_summary — fetch run metadata + statuses + failure comments; client LLM writes the ship-ready Markdown report.

  • prepare_runs_diff(run_a, run_b) — regression/fix delta between two runs; client LLM narrates the diff as Markdown.

  • flaky_test_detector(case_id, last_n_runs) — pull a case's status across recent runs and flag flakiness when it flips between pass/fail. Pure data, no LLM needed.

Roadmap

  • SSE / HTTP transport for hosted use

  • Embedding-based dedupe (semantic, not just token overlap)

  • update_case — patch existing cases when the spec changes

  • Suite cloning across projects

License

MIT

Available Tools

31 tools
add_bulk_resultsA

Post many results in one TestRail call (much faster than looping add_result).

Each entry in results must have at least case_id and status (string or id). Optional per-entry fields: comment, defects, elapsed, version, assignedto_id.

Inputs: run_id (required), results (required).

add_resultA

Post a single test result by case_id (TestRail looks up the test inside the run).

status accepts a string ("passed" | "failed" | "blocked" | "retest" | "untested") or a raw TestRail status_id (1..5 by default). elapsed is a TestRail time string ("30s", "1m 30s", "1h 5m"). defects is a comma-separated list of bug-tracker IDs ("BUG-1, BUG-2").

Inputs: run_id (required), status (required), case_id (required), comment, +3 more.

add_test_cases_bulkA

Push a batch of test cases to TestRail in one call. Returns the IDs created.

cases items are in the shape returned by prepare_cases_* — each has {title, preconditions, steps:[{step, expected}]}. The server maps that into TestRail's payload format (custom_steps_separated etc.).

Targeting: either section_id directly, or section_hierarchy like 'Auth > Login > Smoke' — missing nodes are created.

Inputs: cases (required), suite_id, project_id, section_id, +1 more.

close_runC

Mark a test run as completed/archived. This is irreversible in TestRail.

Inputs: run_id (required).

create_runC

Create a new test run.

By default includes every case in the suite (include_all=True). Pass an explicit case_ids list and set include_all=False to scope the run.

Inputs: name (required), refs, case_ids, suite_id, +4 more.

create_suiteB

Create a new TestRail suite in a project (only works on multi-suite projects).

project_id defaults to TESTRAIL_PROJECT_ID from env.

Inputs: name (required), project_id, description.

create_test_caseC

Create a single test case in a TestRail section.

case should look like: { "title": "...", "preconditions": "...", "steps": [{"step": "...", "expected": "..."}, ...] }

Inputs: case (required), section_id (required).

dedupe_against_sectionA

Check generated cases against what's already in a TestRail section.

Uses title-token overlap (no embeddings) — fast, deterministic. Returns:

  • kept: list of {case, reason} that look new

  • duplicates: list of {case, existing_id, existing_title, overlap} threshold is the minimum token-overlap (0..1) to flag as duplicate.

Inputs: cases (required), section_id (required), suite_id, threshold, +1 more.

find_populated_sectionA

Find a section that has at least min_cases real cases — useful as a house-style anchor when bootstrapping a new feature. Returns the first section meeting the threshold (sections are scanned in TestRail order).

Inputs: suite_id, min_cases, project_id, scan_limit. Returns: result

flaky_test_detectorA

Pull this case's result across the last N runs and flag flakiness.

A test is "flaky" if it has BOTH passes and failures in the window AND flips between them at least twice. Returns the run-by-run trace.

Inputs: case_id (required), project_id, last_n_runs.

get_or_create_sectionA

Resolve a section hierarchy like Auth > Login > Edge Cases, creating missing parents as needed. Returns {"section_id": int, "path": str}.

Defaults to TESTRAIL_PROJECT_ID / TESTRAIL_SUITE_ID from env when not provided.

Inputs: hierarchy (required), suite_id, project_id.

get_results_for_runC

All result entries for a run — includes comments, defects, who tested when.

Inputs: run_id (required), limit. Returns: result

get_runC

Fetch the full metadata of a single test run.

Inputs: run_id (required).

get_test_caseB

Fetch a single test case by its TestRail ID.

Inputs: case_id (required).

get_tests_in_runC

Tests in a run with their current status (current = latest result).

Inputs: run_id (required), limit. Returns: result

list_projectsA

List all TestRail projects visible to the configured user.

Inputs: no named parameters. Returns: result

list_runsC

List test runs in a project.

Filters:

  • suite_id — only runs of this suite

  • is_completed — True for closed/archived runs only, False for open only

Inputs: limit, suite_id, project_id, is_completed. Returns: result

list_sectionsB

List sections in a suite, returning {id, name, parent_id}.

Defaults to TESTRAIL_PROJECT_ID / TESTRAIL_SUITE_ID from env when omitted.

Inputs: limit, suite_id, project_id. Returns: result

list_suitesA

List suites under a TestRail project.

project_id defaults to TESTRAIL_PROJECT_ID from env when omitted or 0.

Inputs: project_id. Returns: result

prepare_cases_from_confluenceB

Fetch a Confluence page + house-style anchors. Returns the context the calling Claude needs to generate TestRail cases. page_id is the numeric ID from the page URL: /wiki/spaces/X/pages/<page_id>.

Inputs: page_id (required), suite_id, project_id, section_id, +4 more.

prepare_cases_from_jiraC

Fetch a Jira ticket + house-style anchors. Returns the context the calling Claude needs to generate TestRail cases. Example: issue_key='ABC-123'.

Inputs: issue_key (required), suite_id, project_id, section_id, +4 more.

prepare_cases_from_textA

Fetch the inputs needed to generate TestRail cases from a free-form spec.

This is an MCP-native pattern: the server doesn't call an LLM. It returns the spec, the house-style anchors, the target section, and an instructions block that tells the calling Claude how to generate cases and where to push them.

Targeting modes:

  • section_id — push into an existing section ID later

  • section_hierarchy — like Auth > Login; missing nodes will be created when you call add_test_cases_bulk. Defaults come from TESTRAIL_PROJECT_ID and TESTRAIL_SUITE_ID env.

House-style matching (default on): the server pulls a few existing cases from the target section (or a fallback populated section) so the calling Claude can match the local tone, naming, and step granularity. Override the style source with house_style_section_id to pull anchors from a different "golden" section.

Inputs: text (required), suite_id, project_id, section_id, +5 more.

prepare_coverage_gapsB

Return the spec and the existing case titles, plus instructions for the calling Claude to find missing coverage. No LLM call happens server-side.

Inputs: cases (required), spec_text (required), feature_title.

prepare_feature_bootstrapA

Prepare a feature-import workflow: fetch the spec, pull house-style anchors, and return everything the calling Claude needs to drive generation and push.

No LLM call happens server-side. Claude in the client generates cases (with the instructions and style examples this tool returns) and then calls add_test_cases_bulk to commit them.

Required:

  • source_type: "confluence" | "jira" | "text"

  • source_value: page_id / issue_key / raw text

  • either new_suite_name (creates a new suite when you push) or existing_suite_id

  • section_name — hierarchy allowed: "A > B > C"

Optional:

  • style_from_suite_id — pull style anchors from a populated suite. Recommended when you're bootstrapping a brand-new empty suite that has no cases yet.

Inputs: source_type (required), source_value (required), project_id, section_name, +3 more.

prepare_lintB

Return the case batch alongside lint instructions for the calling Claude to evaluate.

No LLM call happens server-side — the client Claude reviews the cases using its own context and reports back, paid for by the user's subscription.

Inputs: cases (required), feature_title.

prepare_runs_diffA

Compute the regression / fix / coverage delta between two runs and return the structured data + narrate instructions for the calling Claude.

A is the baseline (older), B is the newer run. No LLM call happens server-side.

Inputs: run_id_a (required), run_id_b (required).

prepare_run_summaryA

Pull run metadata, statuses, and failure comments — return the structured payload + report instructions for the calling Claude to synthesise into Markdown.

No LLM call happens server-side. Claude in the client writes the report.

include_passed_titles=False (default) keeps the payload compact for big runs. Set True only for tiny runs (<50 tests) when full granularity is useful.

Inputs: run_id (required), include_passed_titles.

preview_house_styleC

Return up to N existing cases from the target section in style-example format.

Use this to preview what Claude will see as "house style" before generating.

Inputs: n, suite_id, project_id, section_id, +1 more.

search_test_casesA

List test cases in a project, optionally filtered by suite, section, or title substring.

Both project_id and suite_id fall back to env defaults (TESTRAIL_PROJECT_ID / TESTRAIL_SUITE_ID) when omitted or 0.

Inputs: limit, suite_id, project_id, section_id, +1 more. Returns: result

update_caseA

Patch an existing test case. fields is forwarded to TestRail as-is.

Common keys: title, custom_preconds, custom_steps_separated, priority_id, type_id, refs. To rewrite steps, pass a list under custom_steps_separated: [{"content": "...", "expected": "..."}, ...].

Inputs: fields (required), case_id (required).

update_runA

Patch an existing test run's metadata. Pass only fields you want to change.

Inputs: run_id (required), name, refs, description, +1 more.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 31 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, but the high number of 'prepare_*' tools (prepare_cases_from_confluence, prepare_cases_from_jira, prepare_coverage_gaps, etc.) could cause confusion for an agent trying to select the right one, despite detailed descriptions.

    Naming Consistency4/5

    The naming convention is predominantly verb_noun in snake_case, but there are minor inconsistencies such as 'add_test_cases_bulk' (should be 'add_bulk_test_cases') and 'flaky_test_detector' (noun phrase instead of verb_noun).

    Tool Count2/5

    With 31 tools, the server exceeds the recommended range for well-scoped MCP servers. While TestRail is a complex domain, several tools could be merged or omitted to reduce cognitive load.

    Completeness3/5

    The server covers core CRUD for runs, cases, and results, and adds valuable analysis tools. However, it lacks deletion capabilities (delete_case, delete_run) and project creation, which are notable gaps for full lifecycle coverage.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      An MCP server that enables Claude to create and manage TestRail test cases directly from Jira or Azure DevOps user stories. It provides tools for section management and automated test case creation with built-in format enforcement and traceability links.
      -
    • A
      license
      C
      quality
      D
      maintenance
      MCP server for TestRail API, providing AI assistants with 107 tools to manage test cases, runs, results, plans, and more. Supports API key, password, and SSO cookie authentication.
      54
      17 npm
      2
      MIT