medeval-mcp
# MedEval MCP (local)
Local-only Model Context Protocol gateway for the private MedEval medical-device regulatory workbench.
It lets an MCP client operate MedEval workspaces, canonicalized materials, evidence retrieval, CEP/CER generation and evaluation, workflow observability, and immutable document revisions. MedEval remains the system of record; this project is a thin, bounded adapter.
## Safety boundary
- stdio transport only; no network MCP listener
- connects to loopback by default, with explicit opt-in for trusted private-network IPs
- explicit workspace/task identifiers
- allowlisted local upload roots
- no delete, shell, deployment, or secret-management tools
- asynchronous starts return task IDs and must be polled, not duplicated
- product facts cannot be derived from external literature
- document edits require the current `base_revision_id`
See [SECURITY.md](SECURITY.md).
## Requirements
- Windows or another Python 3.11+ environment
- MedEval running at `http://127.0.0.1:8000`
- Python package dependencies from `pyproject.toml`
## Install
```powershell
cd C:\path\to\medeval-mcp
py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[test]"
Copy-Item .env.example .env
```
The MCP process reads normal environment variables. MCP clients generally supply them in their server configuration rather than loading `.env` automatically.
## Configure
Minimum local configuration:
```text
MEDEVAL_BASE_URL=http://127.0.0.1:8000
MEDEVAL_PROJECT_ROOT=C:\path\to\medeval
MEDEVAL_ALLOWED_FILE_ROOTS=C:\path\to\medeval;C:\path\to\materials
```
If MedEval enables `MEDEVAL_API_TOKEN`, give this MCP process the same `MEDEVAL_API_TOKEN`; it is sent as `X-API-Token`. A signed browser/session token can instead be supplied as `MEDEVAL_BEARER_TOKEN`.
### macOS client to a trusted LAN backend
When MedEval is listening on another computer in the same trusted LAN, use its literal private IP and opt in explicitly:
```text
MEDEVAL_BASE_URL=http://192.168.0.166:8001
MEDEVAL_ALLOW_PRIVATE_NETWORK=true
MEDEVAL_PROJECT_ROOT=/Users/your-name/MedEval
MEDEVAL_ALLOWED_FILE_ROOTS=/Users/your-name/MedEval:/Users/your-name/Documents
```
The MCP remains a local stdio process on the Mac. Public IP addresses and domain names are still rejected.
## Connect from Codex
Use [examples/codex.mcp.json](examples/codex.mcp.json) as the MCP server definition. The command must point to this project's `.venv` Python and use:
```text
-m medeval_mcp.server
```
Restart Codex after changing the MCP configuration, then ask it to call `medeval_health`.
## Bundled Codex plugin and Skill
This repository is also a Codex plugin package. The manifest at
`.codex-plugin/plugin.json` binds the local MCP server to the
`skills/medeval-regulatory` Skill, so a GitHub checkout contains both the tool
implementation and the model-facing workflow guidance.
The bundled `.mcp.json` uses `python3`, the repository root as its working
directory, and `./src` as `PYTHONPATH`. Install this project's Python
dependencies into the interpreter Codex launches before enabling the plugin.
If the local interpreter has a different command or virtual-environment path,
override the MCP command in the local Codex configuration.
The Skill contains generation safeguards that are intentionally more specific
than the low-level API defaults:
- create a typed `GenerationContract` before choosing a template;
- preserve zero-file product statements as provisional `USER_ASSERTED` facts;
- require explicit, exactly matching `template_ids` and `generation_strategy`;
- use a concise `regulatory_research_memo` for a scoped question instead of
silently expanding it into a CEP/CER;
- bind structured research modes and SourceRefs to contract claim IDs;
- distinguish execution completion from quality approval and release readiness;
- submit asynchronous work once, retain the task ID, and inspect status instead
of resubmitting.
For the root-cause map, before/after architecture, contracts, tests, backend
requirements, and migration notes, see
[`docs/current-mcp-analysis-handoff.md`](docs/current-mcp-analysis-handoff.md).
## Run manually
MCP stdio uses standard output for protocol messages, so a manual run appears idle:
```powershell
.\.venv\Scripts\python.exe -m medeval_mcp.server
```
Use an MCP client or Inspector to interact with it.
The bundled local launcher sets the loopback backend and upload roots before starting stdio:
```powershell
.\scripts\run_local.ps1
```
Protocol and backend smoke test:
```powershell
.\.venv\Scripts\python.exe scripts\mcp_smoke.py --health
```
## Tool surface
The local gateway provides 35 tools:
- workspace: health, project list, create/get workspace, instruction-only
sessions, workspace documents, and typed user assertions
- observability: run list, run detail, bounded agent context
- contracts: freeze/read `GenerationContract` and run deterministic preflight
- evidence: project documents, evidence search, section context, typed device
relationships, and time-bounded regulatory status
- ingestion: allowlisted local material upload and canonicalization
- research: regulatory/literature query planning, workspace-scoped external search,
bounded source-text extraction, and frozen generation context
- generation: template list, normal start, researched start, generation/task status,
and opt-in post-generation information completion
- evaluation: start evaluation
- revisions: list, bounded read, diff, optimistic-lock patch
`medeval_start_generation` has no template or strategy default. The caller must
pass a non-empty template list, an explicit strategy, and the exact frozen
contract. Mismatches fail preflight before model work begins.
`search_sources` on the low-level generation tool is compatibility metadata; it
does not itself run a search. For a CEP/CER that needs external evidence, use
`medeval_start_researched_generation`. It performs this closed loop:
1. build or accept bounded, claim-bound research queries with explicit modes;
2. execute up to four queries concurrently through MedEval's configured search;
3. extract bounded source text and store immutable SourceRefs plus structured
research receipts in the selected Agent workspace;
4. freeze the workspace version and integrity hash;
5. run the claim-by-source and consistency preflight;
6. create exactly one generation task only when preflight passes.
External material is always tagged `external_reference`; it may support SOTA,
regulatory, clinical-background, comparison, and published-evidence statements,
but cannot prove facts about the current device.
An execution terminal state is not release approval. A Word deliverable is
available only when deterministic validation, independent review, and rendered
page QA pass and the status reports `release_ready=true`.
After a task produces a releasable deliverable, `medeval_complete_generation_gaps` can run
the existing corpus completion and explicitly opt into online collection. It
writes a separate `*_completed` document and report, never overwriting the
approved deliverable. Poll it with `medeval_get_generation_completion`.
## Tests
```powershell
.\.venv\Scripts\python.exe -m pytest
```
The tests use mock HTTP transports and do not start LLM generation or consume model quota. A separate integration smoke test lists MCP tools and calls the already-running local `/api/health` endpoint.
## Not included yet
- remote Streamable HTTP transport
- `xiaoyuu.me` deployment
- multi-user API keys and workspace ownership
- remote upload staging
- destructive project/task deletion
TDQS
Scored across 21 tools
Tools generally have distinct purposes, but there is some overlap between get_run, get_task_progress, and get_generation_task, which could confuse an agent. Descriptions help clarify, but the boundaries are not perfectly crisp.
All tools share the 'medeval_' prefix and use a consistent snake_case verb_noun pattern (e.g., list_projects, create_workspace, read_document_revision). The one exception, medeval_health, is a minor deviation but does not break overall consistency.
21 tools is slightly heavy but justified given the broad domain covering workspaces, projects, evidence, generation, evaluation, and revisions. The count is within a reasonable range for such a server.
The tool surface covers most core workflows, but there are notable gaps: no workspace update/delete, no get_project, and no cancel/stop operations for generation or evaluation. These are gaps an agent might hit, though the main paths are present.