Skip to main content

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 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.

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)

Source distribution for miqa-mcp 0.2.1
File Size Uploaded
miqa_mcp-0.2.1.tar.gz 8.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for miqa-mcp 0.2.1
File Interpreter ABI Platform
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
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page