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 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 aftercreate_component_versionrejects 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: withapply=Falsenothing 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 withapply=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 disambiguatecomponent_idrather 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.
Release files for miqa-mcp 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| miqa_mcp-0.2.1.tar.gz | 8.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| miqa_mcp-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.2 kB
Release files / miqa_mcp-0.2.1.tar.gz
| Download URL | miqa_mcp-0.2.1.tar.gz |
|---|---|
| Size | 8.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6a247fd1fa2173569e314ee91efb7fb3340c0e3e6908106340b8418264effef4
|
|
BLAKE2b-256 checksum How to use checksums |
85ad648ae4ef78bd998baf4a07f6c41eb042ac3c378701401be817c04172b451
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.14
|
Release files / miqa_mcp-0.2.1-py3-none-any.whl
| Download URL | miqa_mcp-0.2.1-py3-none-any.whl |
|---|---|
| Size | 7.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
204b0dbdcba87b5ae9fbc38e42bab69902d3e6b3a379962a2e1b16832e14a89b
|
|
BLAKE2b-256 checksum How to use checksums |
688287956e61cc9f43ccf07d0cf73b18794710e7802994e30ea6d42faa49860c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.14
|