# Testing

> This skill should be used when the user asks to "run tests", "run the test suite", "check test results", "why are tests failing", "debug test failures", "add a test", "write a test", "update EXPECTED_TOOL_COUNT", "run protocol tests", "run integration tests", "test against InfluxDB", or needs to run, analyze, extend, or troubleshoot the MCP server test suite.

- Skill: `influxdata/testing` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add influxdata/testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/influxdata/testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: influxdata (https://skillmd.com/u/influxdata)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/influxdata/testing

---


# Testing the InfluxDB MCP Server

Two-layer test suite using vitest. Protocol tests run without InfluxDB.
Integration tests require a live instance and are gated behind an env var.

## Prerequisites

Build before testing — tests spawn the compiled `build/index.js`, not source:

```bash
npm run build
```

## Running Tests

### Protocol tests (no InfluxDB needed)

```bash
npm test
```

Runs `tests/protocol.test.ts` only. Integration tests are skipped
automatically. Expected runtime: <1 second.

These tests spawn the real server as a child process using the MCP SDK's
`StdioClientTransport`, perform the `initialize` handshake, and assert on
protocol responses. No InfluxDB connection is made — protocol requests
(`tools/list`, `resources/list`, `prompts/list`, `ping`) are answered
entirely from the server's in-memory registrations.

### Integration tests (live InfluxDB)

Start InfluxDB 3 Core via the provided Docker Compose file:

```bash
npm run test:infra:up
```

This starts an ephemeral Core container on port `8181` using a static admin
token from `tests/fixtures/admin-token.json` (Docker secrets pattern,
`--object-store memory` — no persistent state).

Run integration tests against it:

```bash
source env.test.example && npm run test:integration
```

Tear down when done:

```bash
npm run test:infra:down
```

For a custom InfluxDB instance (different port, Enterprise, etc.), set the
env vars directly instead of sourcing the example file:

```bash
INFLUX_TEST_ENABLED=true \
INFLUX_DB_INSTANCE_URL=http://localhost:8281/ \
INFLUX_DB_TOKEN=<your_token> \
INFLUX_DB_PRODUCT_TYPE=enterprise \
npm run test:integration
```

Tests call `health_check`, `list_databases`, and `execute_query` through the
MCP protocol.

### Watch mode

```bash
npm run test:watch
```

Reruns on file changes. Useful during development.

## What the Tests Cover

| Test                 | What it verifies                                                                                           |
| -------------------- | ---------------------------------------------------------------------------------------------------------- |
| Initialize handshake | Server starts, SDK handshake succeeds, capabilities reported                                               |
| Server version       | Name is `"influxdb-mcp-server"`, version is defined                                                        |
| Tool count           | `tools/list` returns exactly `EXPECTED_TOOL_COUNT` tools                                                   |
| Tool structure       | Each tool has `name`, `description`, `inputSchema` with `type: "object"`                                   |
| Core tool names      | Spot-checks `health_check`, `execute_query`, `write_line_protocol`, `list_databases`, `create_admin_token` |
| Resource URIs        | 4 resources with correct `influx://` URIs                                                                  |
| Resource structure   | Each resource has `name`, `uri`, `description`                                                             |
| Prompt names         | 3 prompts: `list-databases`, `check-health`, `load-context`                                                |
| Ping                 | Server responds to ping                                                                                    |
| Unknown tool error   | Calling nonexistent tool throws `McpError`                                                                 |

## Analyzing Failures

### `EXPECTED_TOOL_COUNT` mismatch

The most common failure after code changes. The constant in
`tests/protocol.test.ts` (line 7) must match the actual tool count.

**After adding or removing a tool**, update the constant and comment in
`tests/protocol.test.ts` (the source of truth). Then update the breakdown
below for documentation.

To find the current count, start the server briefly and check stderr:

```bash
npm run build && INFLUX_DB_INSTANCE_URL=http://localhost:19999/ \
INFLUX_DB_TOKEN=fake INFLUX_DB_PRODUCT_TYPE=core \
node build/index.js &
sleep 1 && kill $!
```

Look for: `[MCP] Server initialized with N tools, N resources, N prompts`

The tool count breakdown by category file:

- `help.tools.ts` (2) + `write.tools.ts` (1) + `database.tools.ts` (4)
- `query.tools.ts` (3) + `token.tools.ts` (6) + `cloud-token.tools.ts` (5)
- `health.tools.ts` (1) = **22 total**
- `schema.tools.ts` (4 tools, currently disabled — commented out in
  `src/tools/index.ts`)

### "build/index.js not found"

Run `npm run build` first. The `tests/setup.ts` guard fails fast with this
message if the build artifact is missing.

### Initialize handshake timeout

The server process failed to start. Common causes:

- Build is stale after source changes — rebuild with `npm run build`
- Missing or invalid env vars — protocol tests use a fake config internally,
  so this usually means `createTestClient` was called with bad overrides

### Integration test: "HEALTHY" not found

InfluxDB instance is unreachable or unhealthy. Verify:

1. Instance is running: `curl http://localhost:8181/ping`
2. Token is valid
3. `INFLUX_DB_PRODUCT_TYPE` matches the actual instance type

### Two error paths in the server

When diagnosing tool call failures, note the server has two distinct error
paths (defined in `src/server/index.ts`):

- **Unknown tool name** → `throw new Error(...)` → SDK converts to `McpError`
  → client sees a rejected promise
- **Known tool, handler failure** → caught in try/catch → returns
  `{ content: [{ type: "text", text: "Error: ..." }], isError: true }`

Protocol tests assert the thrown error path. Integration tests assert the
content-based error path.

## Adding New Tests

### New protocol test

Add to `tests/protocol.test.ts` inside the `describe("MCP protocol compliance")`
block. Protocol tests use the shared `testClient` from `beforeAll`. No InfluxDB
is contacted — only test MCP protocol-level behavior.

### New integration test

Add to `tests/integration.test.ts` inside the
`describe.skipIf(!RUN)("live InfluxDB integration")` block. Call tools via
`testClient.client.callTool({ name: "...", arguments: {...} })` and assert
on the response `content[0].text`.

### Test helper

The `createTestClient(env?)` factory in `tests/helpers/mcp-client.ts` spawns
a real server process and returns a connected MCP `Client`. Override env vars
by passing a partial record. Always call `close()` in `afterAll`.

## Reviewing data-plane and admin changes

When a change adds or modifies a tool that talks to an InfluxDB endpoint
(writes, queries, database/token management), verify the actual API contract
and exercise it against a real instance. Tool descriptions, CHANGELOG entries,
and code comments are not authoritative on their own — confirm them.

### Verify the API contract first

Confirm the HTTP method, path, and request/response shape against both the
InfluxData docs knowledge source and the `influxdata/influxdb` source
(`influxdb3_server/src/http.rs` routing, `influxdb3_types/src/http.rs` structs).

Gotchas that have already bitten this repo:

- Core/Enterprise `update_database` retention is `PUT /api/v3/configure/database`
  with `retention_period` as a duration string (`"60d"`) — not `PATCH`, not
  `retention_period_ns`.
- Core can update retention since v3.2.0 (static docs wrongly say it's immutable).
- `/ping` and `/health` use `Token` auth even for core/enterprise (v1/v2 compat);
  the admin client uses `Bearer`. Both are intentional.

### Exercise it against a real instance

Admin endpoints (`/api/v3/configure/*`) need an admin token; `health_check`
does not, so a passing `health_check` does not prove the token works. Run a
self-contained Core for an admin-path test on a free port:

```bash
docker run -d --name mcp-it-core -p 8383:8181 \
  -v "$PWD/tests/fixtures/admin-token.json":/admin-token.json:ro \
  influxdb:3-core influxdb3 serve \
  --node-id local-test --object-store memory \
  --admin-token-file /admin-token.json

INFLUX_TEST_ENABLED=true INFLUX_DB_INSTANCE_URL=http://localhost:8383/ \
INFLUX_DB_TOKEN=apiv3_test INFLUX_DB_PRODUCT_TYPE=core \
npx vitest run tests/integration.test.ts

docker rm -f mcp-it-core
```

This uses the offline preconfigured admin token in `tests/fixtures/admin-token.json`
(token `apiv3_test`) — the `docker-compose.test.yml` pattern, but on a port you
choose so it does not collide with other local instances.

### Token gotcha

v3 tokens are base64 and can contain `+`, `/`, and `=`. Do not extract one with
`grep -oE 'apiv3_[A-Za-z0-9_-]+'` — it truncates at the first base64 character
and yields an invalid token (the server returns `401 "the request was not
authenticated"`).

## Additional Resources

### Reference Files

- **`.claude/skills/testing/references/test-architecture.md`** — Detailed
  test architecture, design decisions, and how protocol tests work without
  InfluxDB

