test-rail-mcp
by kluchick
README.md
# test-rail-mcp
## Purpose
- Lightweight Model Context Protocol (MCP) server that bridges Cursor (or any MCP client) to TestRail.
- Exposes a tool `get_case_by_id` to fetch TestRail cases and return typed Pydantic models.
- Configured via `TESTRAIL_URL`, `TESTRAIL_USERNAME`, `TESTRAIL_PASSWORD`; deploy via Docker or run locally.
- Designed to be easily extended with more TestRail endpoints (runs, results, sections, etc.).
## Features
- **MCP over HTTP**: Works with Cursor and other MCP clients.
- **Containerized**: One-command Docker setup.
- **Extensible**: Add more tools without changing the transport.
## Setup
### Docker Setup
1. Update docker-compose.yml file with TestRail credentials
```sh
TESTRAIL_URL=https://your-instance.testrail.com
TESTRAIL_USERNAME=your-username
TESTRAIL_PASSWORD=your-api-key
```
2. Build and start:
```bash
docker-compose up -d
# or on Windows: run the bundled script
.\run_docker.bat
```
3. View logs:
```bash
docker-compose logs -f testrail-mcp
```
4. Stop:
```bash
docker-compose down
```
### Local Development
1. Create and activate venv (macOS/Linux):
```bash
python -m venv .venv
source .venv/bin/activate
```
Windows (PowerShell):
```powershell
.venv\Scripts\Activate.ps1
```
2. Install dependencies:
```bash
pip install -r requirements.txt
```
3. Copy env and set credentials:
```bash
cp env.example .env
# Edit `.env` with your TestRail credentials:**
```sh
TESTRAIL_URL=https://your-instance.testrail.com
TESTRAIL_USERNAME=your-username
TESTRAIL_PASSWORD=your-api-key
```
4. Run locally:
```bash
python code/server.py
# server listens on http://localhost:8000
```
Or use Docker (see above) which exposes `http://localhost:8001`.
### Add to Cursor
Add to your Cursor `mcp.json`:
```json
{
"mcpServers": {
"testrail": {
"type": "http",
"url": "http://localhost:8001/mcp"
}
}
}
```
- If running locally without Docker, use `http://localhost:8000/mcp`.
- Enable in Tools & Integrations, ensure the `testrail` MCP is enabled.
## Tooling API
- **get_case_by_id**: Fetch a case by numeric `case_id`.
Example result (shape):
```json
{
"id": 123,
"title": "Verify login",
"type_id": 1,
"priority_id": 2,
"section_id": 10,
"suite_id": 3,
"custom_fields": {
"custom_steps": "...",
"custom_expected": "..."
}
}
```