testrails-mcp
An MCP (Model Context Protocol) server that exposes TestRail CRUD operations to agentic coding tools like Claude Code and Codex CLI, plus a bundled agent skill for turning Jira tickets into TestRail cases.
What it does
testrails-mcp is a thin, async wrapper around the TestRail API v2. Once registered with your agent, it lets the model:
- Navigate your TestRail instance — list projects, suites, and sections.
- Manage test cases — list, read, create, update, and (soft-)delete cases.
- Manage runs — list, read, create, and close test runs; list the tests
inside a run.
- Record results — add and read results for cases within a run.
It speaks stdio (the standard MCP transport for local tools), authenticates with TestRail via HTTP Basic auth using your email and API key, and reads credentials from environment variables or a local .env file.
The repo also ships a portable agent skill (skills/jira-to-testrail/) that auto-triggers when a user asks to convert a Jira ticket into TestRail cases. The skill orchestrates a Jira MCP (any vendor) + this MCP to produce one case per acceptance criterion, with a confirmation gate before anything is created.
Requirements
- Python 3.11+
- A TestRail account with API access enabled (admin → Site Settings → API)
- A TestRail API key — generate one at My Settings → API Keys → Add Key
- An agent runtime that speaks MCP — Claude Code, Codex CLI, Claude Desktop,
or any other MCP-compatible client
Setup
git clone <this-repo> testrails-mcp
cd testrails-mcp
uv venv
uv pip install -e .
cp .env.example .env
# then edit .env with your TestRail URL, email, and API key
.env shape:
TESTRAIL_URL=https://yourcompany.testrail.io
TESTRAIL_USER=you@example.com
TESTRAIL_API_KEY=...
Verify it launches:
.venv/bin/testrails-mcp
# (should sit silently waiting on stdin; Ctrl+C to exit)
Confirm the protocol surface:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | .venv/bin/testrails-mcp
For an interactive smoke test with form inputs for every tool:
npx @modelcontextprotocol/inspector .venv/bin/testrails-mcp
Register with your agent
Claude Code
claude mcp add testrails -- /absolute/path/to/.venv/bin/testrails-mcp
Or add to ~/.claude.json (user-scope) or .mcp.json (project-scope):
{
"mcpServers": {
"testrails": {
"command": "/absolute/path/to/.venv/bin/testrails-mcp"
}
}
}
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.testrails]
command = "/absolute/path/to/.venv/bin/testrails-mcp"
Other clients (Claude Desktop, etc.)
Use the standard MCP server entry: command = /absolute/path/to/.venv/bin/testrails-mcp, no args.
Tools
Navigation
list_projects()list_suites(project_id)list_sections(project_id, suite_id?)
Cases (CRUD)
list_cases(project_id, suite_id?, section_id?, limit?, offset?)get_case(case_id)add_case(section_id, title, type_id?, priority_id?, estimate?, refs?, custom_fields?)update_case(case_id, title?, type_id?, priority_id?, estimate?, refs?, custom_fields?)delete_case(case_id, soft=True)—soft=Truepreviews; passsoft=Falseto actually delete
Runs
list_runs(project_id)get_run(run_id)add_run(project_id, name, suite_id?, description?, case_ids?, include_all?)close_run(run_id)list_tests(run_id)
Results
add_result_for_case(run_id, case_id, status_id, comment?, version?, elapsed?, defects?)get_results_for_case(run_id, case_id)
TestRail default status IDs: 1=Passed, 2=Blocked, 3=Untested, 4=Retest, 5=Failed.
custom_fields on add_case / update_case accepts any TestRail custom field the instance has configured — commonly custom_steps, custom_preconds, custom_expected, or custom_steps_separated.
Skills
This repo ships one bundled skill — a portable SKILL.md that works in both Claude Code and Codex CLI. Skills are auto-loaded by the agent based on their description and activate when the user's prompt matches.
jira-to-testrail
Converts a Jira ticket into TestRail test cases. Triggers on phrases like:
- "Turn PROJ-1234 into test cases"
- "Create TestRail cases from this ticket"
- "Generate QA coverage for <ticket>"
What it does:
- Verifies both a Jira MCP and this TestRail MCP are connected.
- Reads the ticket, extracts acceptance criteria (refuses to invent any).
- Auto-discovers the instance's custom-field shape by sampling an existing
case in the target section.
- Drafts one case per AC with behavior-focused titles and mapped priority.
- Shows you the plan and waits for confirmation before creating.
- Creates the cases and reports IDs + URLs as a table.
- On partial failure, asks how to proceed rather than auto-retrying.
Requires a Jira MCP to also be installed (e.g. Atlassian's official MCP, or mcp-atlassian) — the skill is vendor-agnostic about which one.
Installing the skill
Skills live in a directory the agent watches. Symlink the bundled skill into your agent's skills location so git pull keeps it up to date:
Claude Code
mkdir -p ~/.claude/skills
ln -s "$(pwd)/skills/jira-to-testrail" ~/.claude/skills/jira-to-testrail
Codex CLI
mkdir -p ~/.agents/skills
ln -s "$(pwd)/skills/jira-to-testrail" ~/.agents/skills/jira-to-testrail
Project-scoped (Codex only)
If you'd rather scope the skill to a single repo, drop a copy into that repo's .agents/skills/ directory — Codex walks up from the cwd to find skills.
Prefer a copy over a symlink:
cp -r skills/jira-to-testrail ~/.claude/skills/ # or ~/.agents/skills/
Verifying the skill loaded
- Claude Code: run
/skillsand look forjira-to-testrailin the list. - Codex CLI: start a new session and ask "what skills do you have?" — it
should mention jira-to-testrail (Codex loads skill names/descriptions at session start).
If it doesn't show up, double-check:
- The symlink target exists (
ls -la ~/.claude/skills/jira-to-testrail). SKILL.mdis directly inside that folder, not nested further.- The frontmatter (
name,description) is present and valid YAML.
Project layout
testrails_mcp/
├── pyproject.toml
├── README.md
├── .env.example
├── .gitignore
├── src/testrails_mcp/
│ ├── __init__.py
│ ├── client.py # async httpx client (Basic auth)
│ └── server.py # FastMCP tools, stdio entrypoint
└── skills/
└── jira-to-testrail/
└── SKILL.md # portable Claude/Codex skill
Troubleshooting
Missing TestRail credentialson startup —.envnot found or missing a
key. The server reads .env from the cwd it's launched in; if your agent spawns it from a different directory, set the vars in your shell profile or agent config instead.
TestRail API 401— wrong email or API key. Confirm the key in *My
Settings → API Keys* and that the user has API access on the instance.
TestRail API 403on create/update/delete — the user lacks write
permission on the project, suite, or section.
delete_casereturns a preview — that's the default (soft=True). Pass
soft=False to actually delete.
- Skill doesn't trigger — descriptions are matched fuzzily, but very short
prompts may miss. Try a phrase closer to the examples in the skill's description. As a fallback you can invoke it explicitly (/skill jira-to-testrail in Codex; mention the skill name directly in Claude Code).
Roadmap
Phase 1 (current): Cases, Runs, Results, plus the Jira → TestRail skill.
Likely next:
- Sections CRUD (so the skill can create new sections if needed).
- Milestones and Plans.
- A
bulk_add_result_for_casestool (TestRail has a native batch endpoint). - A second skill for bug report → regression case flows.
License
MIT.






