Metadata-Version: 2.4
Name: miqa-mcp
Version: 0.2.1
Summary: MIQA MCP Server
Author: MIQA / Magna Labs
License: MIT
Keywords: claude,fastmcp,mcp,miqa
Requires-Python: >=3.10
Requires-Dist: fastmcp>=2.0
Requires-Dist: miqatools>=2.0.0rc1
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# MIQA MCP

An MCP server built with FastMCP. It exposes MIQA test-reporting data — plus one
guarded write tool for creating component versions — to Claude Code (and any MCP
client) over stdio. It is a thin MCP surface on top of the
[`miqatools`](../magna-cli) library: the tools call `miqatools` wrappers, which
resolve credentials and talk to the MIQA v2 REST API. The surface is seven read
tools plus one guarded write tool.

The packaging shape — a console script that runs a stdio `main()`, configured via
environment variables — is what makes it registerable with `claude mcp add`.

Read tools (READ-ONLY; none mutate MIQA state):

- `find_runs_by_version(version_name: str, limit: int = 100) -> list` — find Test
  Chain Runs for a version name (newest-first; empty list if none match).
- `get_test_run(run_id: int, sample_ds_id: int | None = None) -> dict` — JSON details
  for a single Test Chain Run (optionally narrowed to one sample).
- `get_test_run_results(run_id: int, sample_ds_id: int | None = None)` — the
  assertion/result summary table (JSON or CSV depending on the server).
- `get_test_run_report(run_id: int, sample_ds_id: int | None = None, format="json")` —
  the sample-centric structured report (feature-flag gated on the server).
- `get_test_run_sample_metadata(run_id: int, sample_ds_id: int | None = None)` — the
  sample metadata for a run (only on servers deploying the sample-metadata routes).
- `get_test_run_environment(run_id: int, sample_ds_id: int | None = None)` — the
  captured test/execution environment (only on servers deploying the routes).
- `list_component_versions(component_id: int, limit: int = 100) -> list` — a
  component's versions, newest-first, as slim entries (id, name, date_created,
  confirmed, is_oneoff, hidden, docker_uri; no template JSON). The recovery path
  after `create_component_version` rejects a duplicate version name (409), and
  the way to confirm an applied create landed.

Write tool (guarded; the only tool that can mutate MIQA state):

- `create_component_version(trigger_id: str, component_id: int | None = None,
  docker_uri: str | None = None, command: str | None = None,
  version_name: str | None = None, apply: bool = False) -> dict` — create a new
  component version (docker uri bump and/or main-step command change) for a
  component reached by a trigger. It is **dry-run by default**: with
  `apply=False` nothing is persisted — the server validates the change and
  returns its verdict, the resolved main step, and a diff of the would-be
  version. The calling agent must present that diff to the user and obtain
  explicit confirmation before re-invoking with `apply=True`, which persists the
  new component version (it never starts a test run). All validation is
  server-side (watched docker repos, known variables, main-step resolution);
  server rejections (unwatched repo, unknown variable, ambiguous main step,
  duplicate name) are surfaced verbatim, and when a trigger reaches several
  components the tool returns a listing to disambiguate `component_id` rather
  than guessing.

Built on the standalone `fastmcp` package (jlowin). Requires Python >= 3.10.

## Configuration

The server reads its MIQA credentials from environment variables (resolved by the
`miqatools` client):

- `MIQA_SERVER_URL` — MIQA server hostname (e.g. `yourco.miqa.io`).
- `MIQA_API_KEY` — MIQA API key.

Claude Code injects these into the server subprocess via the `--env` block (see
"Register with Claude Code" below).

## Prerequisite: install miqatools first (not yet on PyPI)

This server depends on `miqatools>=2.0.0rc1`, which is **not yet published to PyPI**.
Until it is, install `miqatools` from its local checkout first (editable), then install
this server:

```
pip install -e ../magna-cli   # the miqatools library
pip install -e .              # this server
```

Once `miqatools` is published, `pip install .` (or `uvx miqa-mcp`) will resolve it from
PyPI automatically and this extra step goes away.

---

## 1. Install options

Because `miqatools` is not yet on PyPI (see "Prerequisite" above), install it locally
first, then install this server. A plain virtualenv with editable installs is best while
`miqatools` is unpublished:

```
python -m venv .venv
.venv/bin/pip install -e ../magna-cli   # miqatools (the library dependency)
.venv/bin/pip install -e .              # this server
```

The console script then lives at `.venv/bin/miqa-mcp`. It starts and waits silently on
stdin — that is correct: it is a stdio MCP server waiting for a client to speak the
protocol. Press Ctrl-C to stop; you normally let Claude Code launch it rather than running
it by hand.

### Eventual published form

Once both `miqatools` and this server are published to PyPI, the local-editable dance
collapses to a normal install (dependencies resolve automatically):

```
uvx miqa-mcp        # ephemeral
pipx install miqa-mcp
```

---

## 2. Register with Claude Code

`claude mcp add <name> [flags] -- <command> [args...]` registers a stdio server. Claude
Code launches `<command>` as a subprocess and speaks MCP over its stdin/stdout. The `--`
separates Claude's own flags from the subprocess command line.

Since `miqatools` is unpublished, install into a venv (see above) so `miqa-mcp` is on the
venv's PATH, then register that console script — passing MIQA credentials via `--env`:

```
claude mcp add miqa-mcp \
  --env MIQA_SERVER_URL=yourco.miqa.io \
  --env MIQA_API_KEY=your-key-here \
  -- /absolute/path/to/.venv/bin/miqa-mcp
```

If `miqa-mcp` is already on your PATH (activated venv or pipx install), the command is just
the script name:

```
claude mcp add miqa-mcp --env MIQA_SERVER_URL=yourco.miqa.io --env MIQA_API_KEY=your-key-here -- miqa-mcp
```

### Passing configuration via env

A stdio server cannot receive HTTP headers, so its configuration is passed as environment
variables, which Claude Code injects into the subprocess. Use `--env KEY=value` (short form
`-e KEY=value`), and put it before the `--` so it is read as one of Claude's own flags.

This server reads `MIQA_SERVER_URL` and `MIQA_API_KEY` from its environment (the
`miqatools` client resolves them), so both must be passed via `--env`:

```
claude mcp add miqa-mcp --env MIQA_SERVER_URL=yourco.miqa.io --env MIQA_API_KEY=your-key-here -- /absolute/path/to/.venv/bin/miqa-mcp
```

Repeat `--env` for each variable. This env-block mechanism is the stdio equivalent of the
`--header` flag that HTTP-transport servers use; stdio servers get their config through env,
not headers.

By default the server is registered at `local` scope (this project only). Add
`--scope user` to make it available across all your projects.

---

## 3. Verify

List registered servers — `miqa-mcp` should appear, and Claude Code will have started it
and confirmed the connection:

```
claude mcp list
```

You can also inspect just this one:

```
claude mcp get miqa-mcp
```

Inside a Claude Code session, the read tools surface as `find_runs_by_version`,
`get_test_run`, `get_test_run_results`, `get_test_run_report`,
`get_test_run_sample_metadata`, `get_test_run_environment`, and
`list_component_versions`, alongside the guarded write tool
`create_component_version`. With valid `MIQA_SERVER_URL` / `MIQA_API_KEY`
in the env, ask the session to find runs for a version name and it will call the MIQA
API through the server.

---

## 4. Remove

```
claude mcp remove miqa-mcp
```

If you installed with pipx and want to uninstall the package too:

```
pipx uninstall miqa-mcp
```

---

## 5. Run the tests

The test suite asserts the eight tools register on the FastMCP instance, that read
tools delegate to their `miqatools` wrappers, and that
`create_component_version` honors its dry-run/apply and component-disambiguation
contract (the wrappers are mocked, so no network is touched). Install `miqatools`
first, then this package with its dev extra:

```
.venv/bin/pip install -e ../magna-cli
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest
```

---

## 6. How this fits together

This server is a thin MCP surface — seven read tools plus one guarded write tool; all MIQA
client logic lives in the `miqatools` library. The reporting wrappers
(`find_tcrs_by_version`, `get_tcr_summary`, `get_tcr_report`), the existing
`get_tcr_info_json` helper, and the project-setup wrappers
(`get_trigger_template_context`, `create_component_version`,
`list_component_versions`) stay in `miqatools` as
client code; this repo only adds the FastMCP tools and the stdio entry point. The
packaging shape — console script -> stdio `main()` -> env-based config
(`MIQA_SERVER_URL`, `MIQA_API_KEY`) — is what `claude mcp add` launches.
