tram-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ name: Publish Package (manual)
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ jobs:
10
+ publish:
11
+ name: Build and publish to PyPI
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v6
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v7
19
+ with:
20
+ version: "latest"
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v6
24
+ with:
25
+ python-version: "3.13"
26
+
27
+ - name: Install build dependencies
28
+ run: uv pip install --system --upgrade build twine
29
+
30
+ - name: Clean previous builds
31
+ run: rm -rf dist/ build/ *.egg-info
32
+
33
+ - name: Build package
34
+ run: uv build
35
+
36
+ - name: Publish to PyPI
37
+ env:
38
+ TWINE_USERNAME: __token__
39
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
40
+ run: twine upload dist/*
@@ -0,0 +1,92 @@
1
+ name: Tag and release on merge to main
2
+
3
+ on:
4
+ pull_request:
5
+ types: [closed]
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ concurrency:
12
+ group: "release"
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ tag:
17
+ name: Create version tag
18
+ if: github.event.pull_request.merged == true
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v6
24
+ with:
25
+ fetch-depth: 0
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v7
29
+ with:
30
+ version: "latest"
31
+
32
+ - name: Get version
33
+ id: version
34
+ run: echo "version=$(uv version --short)" >> "$GITHUB_OUTPUT"
35
+
36
+ - name: Check if tag already exists
37
+ id: tag_check
38
+ run: |
39
+ if git rev-parse "v${{ steps.version.outputs.version }}" \
40
+ >/dev/null 2>&1; then
41
+ echo "exists=true" >> "$GITHUB_OUTPUT"
42
+ else
43
+ echo "exists=false" >> "$GITHUB_OUTPUT"
44
+ fi
45
+
46
+ - name: Create and push tag
47
+ if: steps.tag_check.outputs.exists == 'false'
48
+ run: |
49
+ git config user.name "github-actions[bot]"
50
+ git config user.email \
51
+ "github-actions[bot]@users.noreply.github.com"
52
+ git tag "v${{ steps.version.outputs.version }}"
53
+ git push origin "v${{ steps.version.outputs.version }}"
54
+
55
+ outputs:
56
+ version: ${{ steps.version.outputs.version }}
57
+ tag_exists: ${{ steps.tag_check.outputs.exists }}
58
+
59
+ publish:
60
+ name: Build and publish to PyPI
61
+ needs: tag
62
+ if: needs.tag.outputs.tag_exists == 'false'
63
+ runs-on: ubuntu-latest
64
+
65
+ steps:
66
+ - name: Checkout code
67
+ uses: actions/checkout@v6
68
+
69
+ - name: Install uv
70
+ uses: astral-sh/setup-uv@v7
71
+ with:
72
+ version: "latest"
73
+
74
+ - name: Set up Python
75
+ uses: actions/setup-python@v6
76
+ with:
77
+ python-version: "3.13"
78
+
79
+ - name: Install build dependencies
80
+ run: uv pip install --system --upgrade build twine
81
+
82
+ - name: Clean previous builds
83
+ run: rm -rf dist/ build/ *.egg-info
84
+
85
+ - name: Build package
86
+ run: uv build
87
+
88
+ - name: Publish to PyPI
89
+ env:
90
+ TWINE_USERNAME: __token__
91
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
92
+ run: twine upload dist/*
@@ -0,0 +1,37 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: Test (Python ${{ matrix.python-version }})
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ python-version: ["3.11", "3.12", "3.13"]
19
+ steps:
20
+ - name: Checkout code
21
+ uses: actions/checkout@v6
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v7
25
+ with:
26
+ version: "latest"
27
+
28
+ - name: Set up Python ${{ matrix.python-version }}
29
+ uses: actions/setup-python@v6
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+
33
+ - name: Install dependencies
34
+ run: uv sync
35
+
36
+ - name: Run tests
37
+ run: uv run pytest
@@ -0,0 +1,18 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Secrets / env
13
+ .env
14
+ .env.*
15
+
16
+ # Local config
17
+ .mcp.json
18
+ .claude/settings.local.json
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,74 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is an MCP (Model Context Protocol) server that wraps the `testrail_api_module` PyPI package, exposing TestRail API endpoints as MCP tools. Built with FastMCP.
8
+
9
+ **Key design principle:** Tools should be discovered dynamically from the `testrail_api_module` rather than hardcoded, to avoid overwhelming LLMs with too many tools and to automatically support new endpoints as the underlying package updates.
10
+
11
+ ## Tech Stack
12
+
13
+ - Python 3.13, managed with `uv`
14
+ - FastMCP (`fastmcp>=2.12.4`) for MCP server framework
15
+ - `testrail_api_module` as the underlying TestRail API client (needs to be added as dependency)
16
+
17
+ ## Common Commands
18
+
19
+ ```bash
20
+ # Install dependencies
21
+ uv sync
22
+
23
+ # Add a new dependency
24
+ uv add <package>
25
+
26
+ # Run the MCP server
27
+ uv run python main.py
28
+
29
+ # Run all tests
30
+ uv run pytest
31
+
32
+ # Run a single test
33
+ uv run pytest test_testing/test_browse.py::test_apple_page_title -v
34
+
35
+ # Run tests with output
36
+ uv run pytest -s
37
+
38
+ # Install packages (not dependencies - dependencies use `uv add`)
39
+ uv pip install <package>
40
+ ```
41
+
42
+ ## Authentication & Secrets
43
+
44
+ - Credentials are managed by **1Password** via an ephemeral `.env` file at the project root.
45
+ - The `.env` file is **not** a normal file — it requires `cat .env` to trigger the 1Password listener and materialize the contents. Python's `open()` and shell `source`/`.` **do not** trigger it.
46
+ - The server uses `_load_env_from_cat()` in `tram_mcp/server.py` to run `cat .env` via subprocess at startup and parse the results into `os.environ`.
47
+ - **Do NOT hardcode credentials** in `.mcp.json` — the `env` block there won't stay in sync. Let the server read from `.env` at startup.
48
+ - Supported env vars: `TESTRAIL_URL`, `TESTRAIL_USERNAME`, `TESTRAIL_API_KEY`, `TESTRAIL_PASSWORD`. Either `TESTRAIL_API_KEY` or `TESTRAIL_PASSWORD` must be set.
49
+ - If auth fails repeatedly, check for **account lockout** — TestRail locks accounts after too many failed attempts (~10 min cooldown).
50
+
51
+ ## Architecture Goals
52
+
53
+ The MCP server should:
54
+ 1. **Introspect `testrail_api_module`** at startup to discover available API modules (projects, cases, runs, results, etc.) and their methods
55
+ 2. **Dynamically register MCP tools** based on discovered endpoints rather than manually defining each one
56
+ 3. **Provide a category/discovery pattern** — e.g., a `list_categories` tool that returns available API modules, and a way to invoke specific endpoints — so the LLM can explore capabilities without being flooded with hundreds of tools upfront
57
+ 4. **Pass through** to `TestRailAPI` client methods, handling authentication via environment variables or MCP configuration
58
+
59
+ ## TestRail Instance Notes
60
+
61
+ - **URL:** `https://vermontsystems.testrail.io`
62
+ - **Templates:** Template 1 = "Test Case (Text)" uses `custom_steps`/`custom_expected` fields. Template 2 = "Test Case (Steps)" uses `custom_steps_separated` (array of `{content, expected}`). To use separated steps, set `template_id: 2`.
63
+ - When updating cases from Text to Steps template, you must change `template_id` in the same call.
64
+
65
+ ## Git Rules
66
+
67
+ - **Never** add `Co-Authored-By` lines to commit messages.
68
+
69
+ ## TestRail API Module Reference
70
+
71
+ The `testrail_api_module` package (`TestRailAPI` class) organizes endpoints into submodules accessed as attributes: `api.projects.get_projects()`, `api.cases.add_case(...)`, `api.results.add_result(...)`, etc. Key modules include: projects, cases, runs, results, attachments, bdd, configurations, labels, sections, users, statuses, plans, datasets, milestones, suites, priorities.
72
+
73
+ Docs: https://trtmn.github.io/testrail_api_module/
74
+ Source: https://github.com/trtmn/testrail_api_module
tram_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matt Troutman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.4
2
+ Name: tram-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server exposing TestRail API endpoints as tools for LLMs
5
+ Project-URL: Homepage, https://github.com/trtmn/tram-mcp
6
+ Project-URL: Repository, https://github.com/trtmn/tram-mcp
7
+ Project-URL: Issues, https://github.com/trtmn/tram-mcp/issues
8
+ Author-email: Matt Troutman <git@trtmn.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: api,llm,mcp,model-context-protocol,testing,testrail
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Testing
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: fastmcp>=2.12.4
22
+ Requires-Dist: python-dotenv>=1.1.1
23
+ Requires-Dist: testrail-api-module==0.7.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ # TestRail MCP Server
27
+
28
+ [![Tests](https://github.com/trtmn/tram-mcp/actions/workflows/tests.yml/badge.svg)](https://github.com/trtmn/tram-mcp/actions/workflows/tests.yml)
29
+ [![Python 3.11 | 3.12 | 3.13](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13-blue?logo=python&logoColor=white)](https://pypi.org/project/tram-mcp/)
30
+ [![PyPI - Version](https://img.shields.io/pypi/v/tram-mcp?label=Latest%20Version)](https://pypi.org/project/tram-mcp/)
31
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/tram-mcp?color=purple)](https://pypi.org/project/tram-mcp/)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
33
+
34
+ Connect your AI coding assistant to [TestRail](https://www.testrail.com/) — manage test cases, runs, results, and more directly from VS Code, Cursor, Claude Desktop, or Claude Code. Built on the [Model Context Protocol](https://modelcontextprotocol.io/) and powered by [`testrail_api_module`](https://github.com/trtmn/testrail_api_module).
35
+
36
+ ## Features
37
+
38
+ - **Dynamic tool discovery** — endpoints are introspected from `testrail_api_module` at startup, so new API coverage is picked up automatically
39
+ - **LLM-friendly** — instead of registering hundreds of tools, provides a category-based discovery pattern so models can explore available operations without being overwhelmed
40
+
41
+ ## Requirements
42
+
43
+ - Python 3.11+
44
+ - [uv](https://docs.astral.sh/uv/)
45
+
46
+ ## Quick Install
47
+
48
+ <a href="vscode:mcp/install?%7B%22name%22%3A%22testrail%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22tram-mcp%22%5D%2C%22env%22%3A%7B%22TESTRAIL_URL%22%3A%22%22%2C%22TESTRAIL_USERNAME%22%3A%22%22%2C%22TESTRAIL_API_KEY%22%3A%22%22%7D%7D"><img src="https://img.shields.io/badge/VS_Code-Install_Server-0078d7?style=flat-square&logo=visual-studio-code" alt="Install in VS Code"></a>
49
+ <a href="vscode-insiders:mcp/install?%7B%22name%22%3A%22testrail%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22tram-mcp%22%5D%2C%22env%22%3A%7B%22TESTRAIL_URL%22%3A%22%22%2C%22TESTRAIL_USERNAME%22%3A%22%22%2C%22TESTRAIL_API_KEY%22%3A%22%22%7D%7D"><img src="https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visual-studio-code" alt="Install in VS Code Insiders"></a>
50
+ <a href="cursor://anysphere.cursor-deeplink/mcp/install?name=testrail&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJ0cmFtLW1jcCJdLCJlbnYiOnsiVEVTVFJBSUxfVVJMIjoiIiwiVEVTVFJBSUxfVVNFUk5BTUUiOiIiLCJURVNUUkFJTF9BUElfS0VZIjoiIn19"><img src="https://img.shields.io/badge/Cursor-Install_Server-purple?style=flat-square&logo=cursor" alt="Install in Cursor"></a>
51
+
52
+ After installing, you will be prompted to fill in your TestRail credentials. See [Configuration](#configuration) below.
53
+
54
+ ## Manual Installation
55
+
56
+ ### Claude Desktop
57
+
58
+ Add to your Claude Desktop config file:
59
+
60
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
61
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
62
+
63
+ ```json
64
+ {
65
+ "mcpServers": {
66
+ "testrail": {
67
+ "command": "uvx",
68
+ "args": ["tram-mcp"],
69
+ "env": {
70
+ "TESTRAIL_URL": "https://yourinstance.testrail.io",
71
+ "TESTRAIL_USERNAME": "your-email@example.com",
72
+ "TESTRAIL_API_KEY": "your-api-key"
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ ### Claude Code
80
+
81
+ ```bash
82
+ claude mcp add testrail \
83
+ -e TESTRAIL_URL=https://yourinstance.testrail.io \
84
+ -e TESTRAIL_USERNAME=your-email@example.com \
85
+ -e TESTRAIL_API_KEY=your-api-key \
86
+ -- uvx tram-mcp
87
+ ```
88
+
89
+ ### VS Code / VS Code Insiders
90
+
91
+ Create `.vscode/mcp.json` in your project (or add to your User Settings):
92
+
93
+ ```json
94
+ {
95
+ "servers": {
96
+ "testrail": {
97
+ "type": "stdio",
98
+ "command": "uvx",
99
+ "args": ["tram-mcp"],
100
+ "env": {
101
+ "TESTRAIL_URL": "",
102
+ "TESTRAIL_USERNAME": "",
103
+ "TESTRAIL_API_KEY": ""
104
+ }
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ VS Code supports `${input:variableName}` placeholders to prompt for values at startup.
111
+
112
+ ### Cursor
113
+
114
+ Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
115
+
116
+ ```json
117
+ {
118
+ "mcpServers": {
119
+ "testrail": {
120
+ "command": "uvx",
121
+ "args": ["tram-mcp"],
122
+ "env": {
123
+ "TESTRAIL_URL": "https://yourinstance.testrail.io",
124
+ "TESTRAIL_USERNAME": "your-email@example.com",
125
+ "TESTRAIL_API_KEY": "your-api-key"
126
+ }
127
+ }
128
+ }
129
+ }
130
+ ```
131
+
132
+ ## Configuration
133
+
134
+ The server requires TestRail credentials via environment variables:
135
+
136
+ | Variable | Required | Description |
137
+ |---|---|---|
138
+ | `TESTRAIL_URL` | Yes | Your TestRail instance URL (e.g. `https://example.testrail.io`) |
139
+ | `TESTRAIL_USERNAME` | Yes | TestRail username or email |
140
+ | `TESTRAIL_API_KEY` | Yes* | TestRail API key |
141
+ | `TESTRAIL_PASSWORD` | Yes* | TestRail password (alternative to API key) |
142
+
143
+ *Either `TESTRAIL_API_KEY` or `TESTRAIL_PASSWORD` must be set. API key is recommended.
144
+
145
+ ## Development
146
+
147
+ ```bash
148
+ # Install dependencies
149
+ uv sync
150
+
151
+ # Run the server locally
152
+ uv run tram_mcp
153
+
154
+ # Run tests
155
+ uv run pytest
156
+
157
+ # Run a single test
158
+ uv run pytest path/to/test.py::test_name -v
159
+ ```
160
+
161
+ ## License
162
+
163
+ MIT
@@ -0,0 +1,138 @@
1
+ # TestRail MCP Server
2
+
3
+ [![Tests](https://github.com/trtmn/tram-mcp/actions/workflows/tests.yml/badge.svg)](https://github.com/trtmn/tram-mcp/actions/workflows/tests.yml)
4
+ [![Python 3.11 | 3.12 | 3.13](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13-blue?logo=python&logoColor=white)](https://pypi.org/project/tram-mcp/)
5
+ [![PyPI - Version](https://img.shields.io/pypi/v/tram-mcp?label=Latest%20Version)](https://pypi.org/project/tram-mcp/)
6
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/tram-mcp?color=purple)](https://pypi.org/project/tram-mcp/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ Connect your AI coding assistant to [TestRail](https://www.testrail.com/) — manage test cases, runs, results, and more directly from VS Code, Cursor, Claude Desktop, or Claude Code. Built on the [Model Context Protocol](https://modelcontextprotocol.io/) and powered by [`testrail_api_module`](https://github.com/trtmn/testrail_api_module).
10
+
11
+ ## Features
12
+
13
+ - **Dynamic tool discovery** — endpoints are introspected from `testrail_api_module` at startup, so new API coverage is picked up automatically
14
+ - **LLM-friendly** — instead of registering hundreds of tools, provides a category-based discovery pattern so models can explore available operations without being overwhelmed
15
+
16
+ ## Requirements
17
+
18
+ - Python 3.11+
19
+ - [uv](https://docs.astral.sh/uv/)
20
+
21
+ ## Quick Install
22
+
23
+ <a href="vscode:mcp/install?%7B%22name%22%3A%22testrail%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22tram-mcp%22%5D%2C%22env%22%3A%7B%22TESTRAIL_URL%22%3A%22%22%2C%22TESTRAIL_USERNAME%22%3A%22%22%2C%22TESTRAIL_API_KEY%22%3A%22%22%7D%7D"><img src="https://img.shields.io/badge/VS_Code-Install_Server-0078d7?style=flat-square&logo=visual-studio-code" alt="Install in VS Code"></a>
24
+ <a href="vscode-insiders:mcp/install?%7B%22name%22%3A%22testrail%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22tram-mcp%22%5D%2C%22env%22%3A%7B%22TESTRAIL_URL%22%3A%22%22%2C%22TESTRAIL_USERNAME%22%3A%22%22%2C%22TESTRAIL_API_KEY%22%3A%22%22%7D%7D"><img src="https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visual-studio-code" alt="Install in VS Code Insiders"></a>
25
+ <a href="cursor://anysphere.cursor-deeplink/mcp/install?name=testrail&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJ0cmFtLW1jcCJdLCJlbnYiOnsiVEVTVFJBSUxfVVJMIjoiIiwiVEVTVFJBSUxfVVNFUk5BTUUiOiIiLCJURVNUUkFJTF9BUElfS0VZIjoiIn19"><img src="https://img.shields.io/badge/Cursor-Install_Server-purple?style=flat-square&logo=cursor" alt="Install in Cursor"></a>
26
+
27
+ After installing, you will be prompted to fill in your TestRail credentials. See [Configuration](#configuration) below.
28
+
29
+ ## Manual Installation
30
+
31
+ ### Claude Desktop
32
+
33
+ Add to your Claude Desktop config file:
34
+
35
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
36
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "testrail": {
42
+ "command": "uvx",
43
+ "args": ["tram-mcp"],
44
+ "env": {
45
+ "TESTRAIL_URL": "https://yourinstance.testrail.io",
46
+ "TESTRAIL_USERNAME": "your-email@example.com",
47
+ "TESTRAIL_API_KEY": "your-api-key"
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Claude Code
55
+
56
+ ```bash
57
+ claude mcp add testrail \
58
+ -e TESTRAIL_URL=https://yourinstance.testrail.io \
59
+ -e TESTRAIL_USERNAME=your-email@example.com \
60
+ -e TESTRAIL_API_KEY=your-api-key \
61
+ -- uvx tram-mcp
62
+ ```
63
+
64
+ ### VS Code / VS Code Insiders
65
+
66
+ Create `.vscode/mcp.json` in your project (or add to your User Settings):
67
+
68
+ ```json
69
+ {
70
+ "servers": {
71
+ "testrail": {
72
+ "type": "stdio",
73
+ "command": "uvx",
74
+ "args": ["tram-mcp"],
75
+ "env": {
76
+ "TESTRAIL_URL": "",
77
+ "TESTRAIL_USERNAME": "",
78
+ "TESTRAIL_API_KEY": ""
79
+ }
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ VS Code supports `${input:variableName}` placeholders to prompt for values at startup.
86
+
87
+ ### Cursor
88
+
89
+ Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
90
+
91
+ ```json
92
+ {
93
+ "mcpServers": {
94
+ "testrail": {
95
+ "command": "uvx",
96
+ "args": ["tram-mcp"],
97
+ "env": {
98
+ "TESTRAIL_URL": "https://yourinstance.testrail.io",
99
+ "TESTRAIL_USERNAME": "your-email@example.com",
100
+ "TESTRAIL_API_KEY": "your-api-key"
101
+ }
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ ## Configuration
108
+
109
+ The server requires TestRail credentials via environment variables:
110
+
111
+ | Variable | Required | Description |
112
+ |---|---|---|
113
+ | `TESTRAIL_URL` | Yes | Your TestRail instance URL (e.g. `https://example.testrail.io`) |
114
+ | `TESTRAIL_USERNAME` | Yes | TestRail username or email |
115
+ | `TESTRAIL_API_KEY` | Yes* | TestRail API key |
116
+ | `TESTRAIL_PASSWORD` | Yes* | TestRail password (alternative to API key) |
117
+
118
+ *Either `TESTRAIL_API_KEY` or `TESTRAIL_PASSWORD` must be set. API key is recommended.
119
+
120
+ ## Development
121
+
122
+ ```bash
123
+ # Install dependencies
124
+ uv sync
125
+
126
+ # Run the server locally
127
+ uv run tram_mcp
128
+
129
+ # Run tests
130
+ uv run pytest
131
+
132
+ # Run a single test
133
+ uv run pytest path/to/test.py::test_name -v
134
+ ```
135
+
136
+ ## License
137
+
138
+ MIT
tram_mcp-0.1.0/main.py ADDED
@@ -0,0 +1,4 @@
1
+ from tram_mcp import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,44 @@
1
+ [project]
2
+ name = "tram-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server exposing TestRail API endpoints as tools for LLMs"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ authors = [
9
+ { name = "Matt Troutman", email = "git@trtmn.com" },
10
+ ]
11
+ keywords = ["mcp", "testrail", "testing", "api", "llm", "model-context-protocol"]
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Topic :: Software Development :: Testing",
21
+ ]
22
+ dependencies = [
23
+ "fastmcp>=2.12.4",
24
+ "python-dotenv>=1.1.1",
25
+ "testrail-api-module==0.7.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/trtmn/tram-mcp"
30
+ Repository = "https://github.com/trtmn/tram-mcp"
31
+ Issues = "https://github.com/trtmn/tram-mcp/issues"
32
+
33
+ [dependency-groups]
34
+ dev = ["pytest"]
35
+
36
+ [build-system]
37
+ requires = ["hatchling"]
38
+ build-backend = "hatchling.build"
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
42
+
43
+ [project.scripts]
44
+ tram_mcp = "tram_mcp:main"
File without changes
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from unittest.mock import MagicMock
4
+
5
+ import pytest
6
+
7
+ import tram_mcp.server as server
8
+
9
+
10
+ @pytest.fixture(autouse=True)
11
+ def _reset_client():
12
+ """Reset the global _client before and after every test."""
13
+ server._client = None
14
+ yield
15
+ server._client = None
16
+
17
+
18
+ @pytest.fixture
19
+ def mock_client():
20
+ """Provide a MagicMock wired into server._client with chained attr access."""
21
+ client = MagicMock()
22
+ server._client = client
23
+ return client