Skip to main content
Glama
g-tiwari

@g-tiwari/mcp-testrail

by g-tiwari
README.md
# @g-tiwari/mcp-testrail

MCP server for the [TestRail](https://www.testrail.com/) API. Gives AI assistants full access to manage test cases, runs, results, plans, and all other TestRail resources.

**107 tools** covering every TestRail API endpoint, with toolset filtering for token efficiency.

Works with **any TestRail setup** — standard cloud/self-hosted instances (API key or password auth) and enterprise SSO deployments (SAML/OIDC cookie-based auth).

## Quick Start

Add to your MCP client config (Claude Desktop, Claude Code, Kiro, Cursor, Windsurf — see [IDE Configuration](#ide--ai-assistant-configuration) below):

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

That's it. Restart your MCP client and start asking it to manage TestRail.

> **Enterprise SSO?** Replace the API key env vars with `"TESTRAIL_COOKIE_PATH": "~/path/to/cookies.txt"` — see [Authentication](#authentication) for all options. You can also add optional env vars like `TESTRAIL_PROJECT_IDS`, `TESTRAIL_TOOLSETS`, and `TESTRAIL_READ_ONLY_MODE` to the same `env` block — see [Environment Variables](#environment-variables).

## Authentication

### Option 1: API Key (Recommended for most users)

This is the standard auth method for TestRail Cloud and self-hosted instances.

1. Go to **My Settings** in TestRail (top-right menu)
2. Enable the API under **API** section
3. Generate an **API key**

Set these environment variables:

```
TESTRAIL_URL=https://yourcompany.testrail.com
TESTRAIL_EMAIL=your@email.com
TESTRAIL_API_KEY=your-api-key
```

### Option 2: Password

For instances where API keys are not available.

```
TESTRAIL_URL=https://yourcompany.testrail.com
TESTRAIL_EMAIL=your@email.com
TESTRAIL_PASSWORD=your-password
```

### Option 3: SSO Cookie Auth (Enterprise)

For enterprise TestRail instances behind SSO providers (Okta, Azure AD, etc.). The server reads a [Netscape-format cookie file](https://curl.se/docs/http-cookies.html), automatically completes the SAML/OIDC login flow, and obtains a TestRail session.

```
TESTRAIL_URL=https://testrail.yourcompany.com
TESTRAIL_COOKIE_PATH=~/path/to/sso/cookies.txt
```

**How it works:** The server loads SSO cookies from the file, hits the TestRail SSO redirect endpoint, parses the SAML response form, and submits it back to TestRail to obtain a `tr_session` cookie. It also hot-reloads when the cookie file changes (e.g. after re-authenticating with your SSO provider).

> **Note:** You may need to refresh your SSO cookies periodically (e.g. re-authenticate via your SSO provider's CLI).

### Option 4: SSO Cookie + API Key (Hybrid)

For enterprise setups where the SSO proxy requires cookies **and** TestRail also validates API key auth.

```
TESTRAIL_URL=https://testrail.yourcompany.com
TESTRAIL_COOKIE_PATH=~/path/to/sso/cookies.txt
TESTRAIL_EMAIL=your@email.com
TESTRAIL_API_KEY=your-api-key
```

## IDE / AI Assistant Configuration

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

**API Key auth:**

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

**SSO Cookie auth (enterprise):**

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://testrail.yourcompany.com",
        "TESTRAIL_COOKIE_PATH": "~/path/to/sso/cookies.txt"
      }
    }
  }
}
```

### Claude Code (CLI)

Add to `~/.claude/settings.json` or your project's `.claude/settings.json`:

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

### Kiro

Add to `.kiro/settings/mcp.json` in your project root:

**API Key auth:**

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

**SSO Cookie auth (enterprise):**

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://testrail.yourcompany.com",
        "TESTRAIL_COOKIE_PATH": "~/path/to/sso/cookies.txt"
      }
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json` in your project root:

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

### Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "testrail": {
      "command": "npx",
      "args": ["-y", "@g-tiwari/mcp-testrail"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

### Local Development

For local testing (not published to npm), use the absolute path to the built file:

```json
{
  "mcpServers": {
    "testrail": {
      "command": "node",
      "args": ["/absolute/path/to/testrail-mcp/build/src/index.js"],
      "env": {
        "TESTRAIL_URL": "https://yourcompany.testrail.com",
        "TESTRAIL_EMAIL": "your@email.com",
        "TESTRAIL_API_KEY": "your-api-key"
      }
    }
  }
}
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `TESTRAIL_URL` | Yes | TestRail instance URL (e.g. `https://yourcompany.testrail.com`) |
| `TESTRAIL_EMAIL` | For API key/password auth | User email address |
| `TESTRAIL_API_KEY` | Option 1 | API key (from My Settings in TestRail) |
| `TESTRAIL_PASSWORD` | Option 2 | Password (if API keys are unavailable) |
| `TESTRAIL_COOKIE_PATH` | Option 3 | Path to Netscape-format cookie file |
| `TESTRAIL_TOOLSETS` | No | Comma-separated toolset names or `"all"` (default: core toolsets) |
| `TESTRAIL_TOOLS` | No | Additional individual tool names to enable |
| `TESTRAIL_DENIED_TOOLS_REGEX` | No | Regex pattern to exclude tools by name |
| `TESTRAIL_PROJECT_IDS` | No | Comma-separated project IDs to scope the server to (e.g. `"5"` or `"1,5,12"`) |
| `TESTRAIL_READ_ONLY_MODE` | No | Set to `"true"` to expose only read operations |

If both `TESTRAIL_API_KEY` and `TESTRAIL_PASSWORD` are set, API key takes precedence.

### Project Scoping

Use `TESTRAIL_PROJECT_IDS` to restrict the server to specific projects. This is useful when your TestRail instance has many projects but you only work with a few.

| Configuration | Description hints | Auto-inject `project_id` | Restrict |
|---|---|---|---|
| Unset | None | No | No |
| Single ID (`"5"`) | `[Project 5]` appended to tool descriptions | Yes — fills missing `project_id` | Rejects other IDs |
| Multiple IDs (`"1,5,12"`) | `[Allowed projects: 1, 5, 12]` appended | No — LLM must pick | Rejects other IDs |

```bash
# Scope to a single project (auto-injects project_id)
TESTRAIL_PROJECT_IDS="5"

# Scope to multiple projects (LLM must specify which)
TESTRAIL_PROJECT_IDS="1,5,12"
```

Tools like `get_projects` (no project_id input) and `add_project` (creates new) are unaffected. Entity-scoped tools like `get_case` (which take a case_id, not project_id) are also unaffected.

## Toolsets

Tools are organized into 18 toolsets. **9 are enabled by default** (54 tools) to keep token usage low. Use `TESTRAIL_TOOLSETS` to customize.

| Toolset | Default | Tools | Description |
|---------|---------|-------|-------------|
| `projects` | Yes | 5 | Project CRUD |
| `suites` | Yes | 5 | Suite CRUD |
| `sections` | Yes | 6 | Section CRUD + move |
| `cases` | Yes | 13 | Case CRUD + bulk + fields/types |
| `runs` | Yes | 6 | Run CRUD + close |
| `tests` | Yes | 2 | Read tests in runs |
| `results` | Yes | 8 | Result CRUD + bulk + fields |
| `users` | Yes | 5 | User lookup + roles |
| `metadata` | Yes | 4 | Priorities, statuses, templates |
| `plans` | No | 12 | Test plan management |
| `milestones` | No | 5 | Milestone CRUD |
| `groups` | No | 5 | Group management |
| `attachments` | No | 8 | File attachments |
| `configurations` | No | 7 | Test configurations |
| `reports` | No | 2 | Report execution |
| `shared_steps` | No | 5 | Shared steps |
| `variables` | No | 4 | Variables |
| `datasets` | No | 5 | Datasets |

### Toolset Examples

```bash
# Only case and result management (21 tools)
TESTRAIL_TOOLSETS="cases,results"

# Everything (107 tools)
TESTRAIL_TOOLSETS="all"

# Default toolsets + specific additional tools
TESTRAIL_TOOLS="get_plan,get_plans,get_milestones"

# Block all destructive operations
TESTRAIL_DENIED_TOOLS_REGEX="^(delete_|close_)"

# Read-only mode (~40 tools)
TESTRAIL_READ_ONLY_MODE="true"
```

## Token Efficiency

Every MCP tool definition is injected into the LLM context on **every conversation turn**. More tools = more tokens burned before the model even reads your message. This MCP is designed to keep that cost low.

**Default config uses ~2,000 tokens for tool definitions** — roughly half of what exposing all 107 tools would cost (~4,000 tokens). Over a 10-turn conversation, that's ~20,000 tokens saved.

| Configuration | Tools | ~Tokens per turn |
|---|---|---|
| Default (9 core toolsets) | 54 | ~2,000 |
| Read-only mode | 46 | ~1,700 |
| Custom (e.g. `cases,results`) | 21 | ~800 |
| All toolsets | 107 | ~4,000 |

### How

- **Toolset filtering** — only 54 of 107 tools exposed by default; non-essential toolsets (plans, milestones, groups, etc.) are opt-in
- **Compact descriptions** — average 24 characters per tool (5-10 words), not full sentences
- **Bulk operations** — `add_results`, `update_cases`, `delete_cases` accept arrays, so one call replaces dozens of round-trips (each avoided round-trip saves the full tool list re-injection)
- **Max pagination** — defaults to 250 items per page (TestRail's maximum), fewer calls needed
- **Raw JSON responses** — no metadata envelope or wrapper overhead; delete/close operations return just `{"success": true}`
- **Layered filtering** — `TESTRAIL_TOOLSETS` → `TESTRAIL_TOOLS` → `TESTRAIL_READ_ONLY_MODE` → `TESTRAIL_DENIED_TOOLS_REGEX` all compose, so you can tune to exactly what you need

## Rate Limiting

Automatic retry with exponential backoff on HTTP 429 responses. Respects the `Retry-After` header. Max 3 retries.

## Available Tools (107)

<details>
<summary>Click to expand full tool list</summary>

### Projects (5)
- `get_project` — Get a project by ID
- `get_projects` — List all projects
- `add_project` — Create a new project
- `update_project` — Update an existing project
- `delete_project` — Delete a project by ID

### Suites (5)
- `get_suite` — Get a test suite by ID
- `get_suites` — List suites for a project
- `add_suite` — Create a test suite
- `update_suite` — Update a test suite
- `delete_suite` — Delete a test suite

### Sections (6)
- `get_section` — Get a section by ID
- `get_sections` — List sections in a project/suite
- `add_section` — Create a section
- `move_section` — Move a section to a new parent
- `update_section` — Update a section
- `delete_section` — Delete a section

### Cases (13)
- `get_case` — Get a test case by ID
- `get_cases` — List test cases with filters
- `get_history_for_case` — Get change history for a case
- `add_case` — Create a test case in a section
- `update_case` — Update a test case
- `update_cases` — Bulk update multiple test cases
- `delete_case` — Delete a test case
- `delete_cases` — Bulk delete multiple test cases
- `copy_cases_to_section` — Copy cases to another section
- `move_cases_to_section` — Move cases to another section
- `get_case_fields` — List available case fields
- `add_case_field` — Create a custom case field
- `get_case_types` — List available case types

### Runs (6)
- `get_run` — Get a test run by ID
- `get_runs` — List test runs for a project
- `add_run` — Create a test run
- `update_run` — Update a test run
- `close_run` — Close a test run
- `delete_run` — Delete a test run

### Tests (2)
- `get_test` — Get a test by ID
- `get_tests` — List tests in a run

### Results (8)
- `get_results` — Get results for a test
- `get_results_for_case` — Get results for a case in a run
- `get_results_for_run` — Get all results for a run
- `add_result` — Add a result for a test
- `add_result_for_case` — Add a result for a case in a run
- `add_results` — Bulk add results for a run
- `add_results_for_cases` — Bulk add results by case for a run
- `get_result_fields` — List available result fields

### Plans (12)
- `get_plan` — Get a test plan by ID
- `get_plans` — List test plans for a project
- `add_plan` — Create a test plan
- `add_plan_entry` — Add a suite entry to a plan
- `add_run_to_plan_entry` — Add a run to a plan entry
- `update_plan` — Update a test plan
- `update_plan_entry` — Update a plan entry
- `update_run_in_plan_entry` — Update a run in a plan entry
- `close_plan` — Close a test plan
- `delete_plan` — Delete a test plan
- `delete_plan_entry` — Delete a plan entry
- `delete_run_from_plan_entry` — Delete a run from a plan entry

### Milestones (5)
- `get_milestone` — Get a milestone by ID
- `get_milestones` — List milestones for a project
- `add_milestone` — Create a milestone
- `update_milestone` — Update a milestone
- `delete_milestone` — Delete a milestone

### Users & Roles (5)
- `get_user` — Get a user by ID
- `get_current_user` — Get the authenticated user
- `get_user_by_email` — Find a user by email
- `get_users` — List users
- `get_roles` — List available user roles

### Groups (5)
- `get_group` — Get a group by ID
- `get_groups` — List all groups
- `add_group` — Create a user group
- `update_group` — Update a user group
- `delete_group` — Delete a user group

### Attachments (8)
- `add_attachment_to_plan` — Attach a file to a test plan
- `add_attachment_to_result` — Attach a file to a result
- `add_attachment_to_run` — Attach a file to a run
- `add_attachment_to_case` — Attach a file to a case
- `get_attachments_for_case` — List attachments for a case
- `get_attachments_for_run` — List attachments for a run
- `get_attachment` — Get attachment metadata by ID
- `delete_attachment` — Delete an attachment

### Configurations (7)
- `get_configs` — List configurations for a project
- `add_config_group` — Create a configuration group
- `add_config` — Add a config to a group
- `update_config_group` — Update a configuration group
- `update_config` — Update a configuration
- `delete_config_group` — Delete a configuration group
- `delete_config` — Delete a configuration

### Metadata (4)
- `get_priorities` — List available priorities
- `get_statuses` — List available test statuses
- `get_case_statuses` — List available case statuses
- `get_templates` — List templates for a project

### Reports (2)
- `get_reports` — List reports for a project
- `run_report` — Execute a report template

### Shared Steps (5)
- `get_shared_step` — Get a shared step by ID
- `get_shared_steps` — List shared steps for a project
- `add_shared_step` — Create a shared step
- `update_shared_step` — Update a shared step
- `delete_shared_step` — Delete a shared step

### Variables (4)
- `get_variables` — List variables for a project
- `add_variable` — Create a variable
- `update_variable` — Update a variable
- `delete_variable` — Delete a variable

### Datasets (5)
- `get_dataset` — Get a dataset by ID
- `get_datasets` — List datasets for a project
- `add_dataset` — Create a dataset
- `update_dataset` — Update a dataset
- `delete_dataset` — Delete a dataset

</details>

## Troubleshooting

### "Authentication failed: invalid or missing user/password or session cookie"

- **API Key auth:** Verify your API key is correct and the API is enabled in TestRail (Administration > Site Settings > API).
- **SSO Cookie auth:** Your SSO cookies may have expired. Refresh them (re-authenticate with your SSO provider) and try again. The server auto-detects cookie file changes.

### "TESTRAIL_URL environment variable is required"

Ensure `TESTRAIL_URL` is set in your MCP config's `env` block. The URL should not have a trailing slash.

### SSO login flow fails

1. Ensure your SSO cookies are fresh and valid
2. Test by opening your TestRail URL in a browser — if you can access it, the cookies should work
3. Check that `TESTRAIL_COOKIE_PATH` points to the correct Netscape-format cookie file
4. The server logs to stderr — check your MCP client's logs for detailed SSO flow output

### Tools not appearing

Check `TESTRAIL_TOOLSETS` — by default only 9 core toolsets (54 tools) are enabled. Use `TESTRAIL_TOOLSETS="all"` for all 107 tools.

## License

MIT

TDQS

C2.9/5.0

Scored across 54 tools

Disambiguation3/5

The tools are mostly entity-based and distinct, but several groups can be confused: the four add_result variants differ mainly by test/case/bulk scope, and get_case vs get_test relies on the TestRail-specific distinction between a case definition and a test instance in a run. Descriptions help somewhat but do not fully disambiguate these boundaries.

Naming Consistency5/5

Tool names follow a highly consistent snake_case verb_noun pattern with predictable prefixes like get/add/update/delete and singular/plural conventions for object vs list operations. Special actions like close_run, move_section, and copy_cases_to_section still fit the same overall naming style.

Tool Count2/5

At 54 tools, this is far beyond the comfortable MCP range and will create a heavy selection surface for agents, even though each tool maps to a distinct TestRail API endpoint. The set is organized, but the sheer number makes it too large for efficient tool choice.

Completeness3/5

The core lifecycle for projects, suites, sections, cases, runs, and results is well covered, including bulk and move/copy operations. However, notable TestRail entities are missing—milestones, test plans, attachments, and configurations—so agents requiring those workflows will encounter dead ends.

Maintenance

ActivityInactive
ResponsivenessNo issues