Skip to main content
Glama
deanchong
by deanchong
README.md
# TestMonitor MCP server

A local Node.js MCP server that lets AI agents interact with TestMonitor through 173 tools generated from the official [TestMonitor REST API specification](https://docs.testmonitor.com/). Uses the official MCP SDK and stdio transport; no build step or public web server is needed.

Supports projects, members, applications, versions, requirements, risks, test cases and folders, test runs, test results, issues, comments, attachments, teams, users, webhooks, custom fields, and status lookups. See [TOOLS.md](./TOOLS.md) for the complete catalog. Available operations still depend on your TestMonitor permissions and subscription.

## Local installation (optional)

Requires Node.js 22 or later. Skip this manual installation if you use the `npx` configuration below.

```sh
git clone https://github.com/deanchong/testmonitor-mcp.git
cd testmonitor-mcp
npm ci
cp .env.example .env
```

Edit `.env` with your instance URL and Personal Access Token. In TestMonitor, open **My Account → API → Create token**. Keep the token private; `.env` is excluded from Git.

```dotenv
TESTMONITOR_URL=https://yourcompany.testmonitor.com
TESTMONITOR_TOKEN=your-token
TESTMONITOR_READ_ONLY=false
```

Start manually with:

```sh
node --env-file=.env src/index.js
```

The process waits for MCP messages on stdin. It is not an interactive command prompt. Protocol messages are the only stdout output. `npm start` also works when the environment variables are already exported; it does not automatically load `.env`.

## Connect your AI agent

Configure your AI agent harness to launch this server as a local **stdio MCP server**. The harness starts the process and discovers its tools. GitHub provides the downloadable package; each user supplies their own TestMonitor URL and token.

### Recommended: launch with npx

Requires Node.js 22+, npm (which includes `npx`), and Git on the machine running the harness. No manual clone or `npm ci` is needed for this option.

Add this entry to your harness's MCP configuration, preserving any existing servers. This example uses the common `mcpServers` structure; adapt the outer structure to your harness while keeping the command, arguments, and environment values:

```json
{
  "mcpServers": {
    "testmonitor": {
      "command": "npx",
      "args": [
        "--yes",
        "--package=github:deanchong/testmonitor-mcp#main",
        "testmonitor-mcp"
      ],
      "env": {
        "TESTMONITOR_URL": "https://yourcompany.testmonitor.com",
        "TESTMONITOR_TOKEN": "your-personal-access-token",
        "TESTMONITOR_READ_ONLY": "false"
      }
    }
  }
}
```

Replace the URL and token with your own values, then restart or reconnect your harness. Create a token in TestMonitor under **My Account → API → Create token**. Keep your configuration private or use your harness's secret-management mechanism. Set `TESTMONITOR_READ_ONLY` to `true` if you only need read access.

On launch, `npx` downloads the specified GitHub revision and installs its dependencies into npm's local cache when needed, then starts `testmonitor-mcp`. The harness communicates with that process over stdio, and the process calls your TestMonitor API. `--yes` allows package installation without an interactive prompt. The public repository alone does not automatically register or launch the server. See [npm exec / npx documentation](https://docs.npmjs.com/cli/v11/commands/npm-exec/).

If the harness cannot find `npx`, use its full executable path (`which npx` on macOS/Linux or `where npx` on Windows). Windows harnesses may require `npx.cmd` or their documented command-shell wrapper.

The example uses `#main`, which follows a moving branch. For repeatable startup, replace `main` with a reviewed commit's full SHA from this repository. npm caching means you should not assume every launch fetches the latest code. This repository does not need to be published to npm for the GitHub package command to work.

### Alternative: launch an installed copy with node

Complete **Local installation** above and configure the harness to launch your installed copy:

```json
{
  "mcpServers": {
    "testmonitor": {
      "command": "node",
      "args": [
        "--env-file=/absolute/path/to/testmonitor-mcp/.env",
        "/absolute/path/to/testmonitor-mcp/src/index.js"
      ]
    }
  }
}
```

Replace both placeholders with actual absolute paths. For Windows JSON, use escaped backslashes, such as `C:\\Users\\you\\testmonitor-mcp\\src\\index.js`. If your client cannot find Node, use its absolute executable path. Clients with a different configuration format need the same command and arguments. Restart or reconnect after changing settings. This option runs the local checkout; update it explicitly with `git pull --ff-only` followed by `npm ci`.

### npx versus node

| Command | Package setup | What runs |
|---|---|---|
| `npx` | Downloads the specified package and installs dependencies when needed; can reuse npm's cache | The package's `testmonitor-mcp` executable |
| `node` | You clone/download the project and install dependencies first | The local `src/index.js` file |

Both start the same Node.js MCP server. Choose `npx` for configuration-based installation or `node` for a local checkout you manage yourself. This project implements stdio only; a harness that accepts only remote MCP URLs needs a separately configured transport or gateway. The GitHub URL is not an MCP endpoint.

### Try the connection

Suggested agent requests:

- “List my TestMonitor projects.”
- “Find login test cases in project 7.”
- “Create a test case for a failed login in project 7.”
- “List result statuses, then record the outcome for test case 42 in run 5.”

## Tool arguments

Each tool publishes its JSON Schema to the agent. Arguments are grouped into `path`, `query`, and `body`; only applicable groups are present. Operation names follow the upstream operation IDs in snake_case. The upstream `GetTestRuneCollection` typo is exposed as `get_test_run_collection`.

List test cases:

```json
{
  "name": "get_test_case_collection",
  "arguments": {
    "query": {
      "project_id": 7,
      "query": "login",
      "limit": 25,
      "page": 1,
      "order": "-name",
      "filter": { "draft": false },
      "with": ["requirements", "risks"]
    }
  }
}
```

Create a test case:

```json
{
  "name": "post_test_case",
  "arguments": {
    "body": {
      "project_id": 7,
      "name": "Valid login",
      "instructions": ["Open the login page", "Enter valid credentials", "Submit"],
      "expected_result": "The dashboard is displayed"
    }
  }
}
```

Record a result (look up the actual status ID with `get_test_result_states_collection` first):

```json
{
  "name": "post_test_result",
  "arguments": {
    "body": {
      "test_case_id": 42,
      "test_run_id": 5,
      "draft": false,
      "test_result_status_id": 2,
      "description": "Dashboard displayed as expected."
    }
  }
}
```

Upload an attachment using `post_test_case_attachment`, `post_issue_attachment`, or `post_test_result_attachment`. The file is supplied as `{ "filename": "note.txt", "base64": "aGVsbG8=", "mimeType": "text/plain" }` in `body.file`, with the entity ID in `path`. Files are limited to 14 million base64 characters (approximately 10 MiB). The server does not read local files. Result create/update tools use JSON; add attachments separately after obtaining the result ID.

## Behavior and configuration

| Environment variable | Purpose |
|---|---|
| `TESTMONITOR_URL` | Required HTTPS instance URL, optionally ending in `/api/v1` |
| `TESTMONITOR_TOKEN` | Required Personal Access Token |
| `TESTMONITOR_READ_ONLY` | `true` exposes and permits only GET tools; defaults to `false` |
| `TESTMONITOR_TIMEOUT_MS` | Request timeout, default `30000`, range 1–300000 |
| `TESTMONITOR_TOOLS` | Optional comma-separated exact tool names; unknown names fail startup |

Use the tool allowlist to reduce the catalog for agents with tool-count limits, for example:

```dotenv
TESTMONITOR_TOOLS=get_project_collection,get_test_case_collection,post_test_case,get_test_run_collection,get_test_result_states_collection,post_test_result
```

- Tool responses contain `{ status, ok, data }` and optionally `retryAfter`. HTTP failures set MCP `isError: true`. TestMonitor validation details are retained.
- Collections return one page with the original `data`, `links`, and `meta` envelope. Request subsequent pages explicitly with `query.page`. The API's documented limit is 5–100, with a default of 15.
- Filters use bracket notation, nested custom-field filters are supported, and array filters use the JSON-array form documented in the introduction. Relations use comma-separated values. Descending sort values are added to upstream enums because the introduction explicitly documents them.
- Requests use Bearer authentication, HTTPS, a fixed configured origin, redirect rejection, cancellation, and a timeout. Responses are capped at 10 MiB.
- Failed requests are not retried automatically, avoiding duplicate writes. Inspect errors before deciding whether another attempt is appropriate; timed-out writes may have succeeded remotely.
- Writes, deletes, comments, user administration, and webhooks operate on the live instance. MCP annotations identify mutations; they are hints for the agent, not an approval system. Use TestMonitor account permissions, read-only mode, and an allowlist to constrain access.
- Schemas preserve upstream validation and incomplete definitions. The API remains authoritative for business rules and fields whose types are underspecified. Deprecated endpoints remain available and are identified in their descriptions.

## Development and validation

```sh
npm run generate
npm run check
npm test
```

The tests use the MCP client over in-memory transport and a real stdio child process, with mocked HTTP responses. They cover tool discovery, schema validation, JSON writes, batch requests, pagination/filter encoding, multipart uploads, access restrictions, and errors. They do not access a live TestMonitor instance.

The checked-in [spec/openapi.yaml](./spec/openapi.yaml) is the official version 8.3.1 specification retrieved on 2026-09-06 from [docs.testmonitor.com/openapi.yaml](https://docs.testmonitor.com/openapi.yaml). It is kept for reproducible generation and retains its upstream license metadata. The upstream license name and URL disagree; this project does not reinterpret them. To update, replace that file with a reviewed upstream specification, run `npm run generate`, review the generated changes, and run tests. Runtime startup never downloads documentation.

Source layout: `scripts/generate.js` builds the catalog; `src/client.js` handles HTTP; `src/server.js` validates and dispatches MCP tools; `src/index.js` starts stdio transport. `src/operations.json` and `TOOLS.md` are generated files.

Maintenance

ActivityMaintained
ResponsivenessNo issues