Skip to content

Commit 09a4fd9

Browse files
committed
Add contract coverage test and docs
1 parent 017baab commit 09a4fd9

3 files changed

Lines changed: 40 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ Every successful tool invocation returns structured payloads designed for agents
214214
- Applicability-domain definitions, policy defaults, and remediation steps live under `metadata/` with JSON Schema validation.
215215
- Predictive invocations persist audit bundles that can be fetched via metadata tools.
216216
- Governance workflows (SME review, policy approval, publication) are documented in `docs/model_cards_and_policies.md`.
217-
- Response contracts live under `docs/contracts/schemas/` and are enforced before MCP responses (and predictive HTTP endpoints) are returned; upstream failover policies are summarized in `docs/contracts/endpoint-matrix.md`.
217+
- Response contracts live under `docs/contracts/schemas/` (see `docs/contracts/README.md`) and are enforced before MCP responses (and predictive HTTP endpoints) are returned; upstream failover policies are summarized in `docs/contracts/endpoint-matrix.md`.
218218

219219
### Testing & quality gates
220220

docs/contracts/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Contract Metadata
2+
3+
All MCP tool responses are backed by JSON Schemas stored under `docs/contracts/schemas/`. Whenever you add a new tool or transport surface, follow these steps:
4+
5+
1. **Author the schema** – drop a Draft 2020-12 schema in the appropriate namespace (e.g., `common/`, `hazard/`, `predictive/`). Favor the shared schemas in `docs/contracts/schemas/common/` when possible.
6+
2. **Reference it in the tool definition** – include `"responseSchemaRef": schema_ref("namespace", "file.json")` in the resource's `get_tools()` entry (or expose a concrete `outputSchema`).
7+
3. **Update tests if needed**`tests/test_tool_contracts.py` enforces that every tool has either a `responseSchemaRef` or `outputSchema`, so missing contracts will fail CI automatically.
8+
9+
This workflow keeps MCP responses stable for downstream agents and makes future schema coverage straightforward.

tests/test_tool_contracts.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Ensure every MCP tool defines a response schema/output schema."""
2+
3+
from epacomp_tox.resources.bioactivity import BioactivityResource
4+
from epacomp_tox.resources.chemical import ChemicalResource
5+
from epacomp_tox.resources.chemical_list import ChemicalListResource
6+
from epacomp_tox.resources.cheminformatics import CheminformaticsResource
7+
from epacomp_tox.resources.exposure import ExposureResource
8+
from epacomp_tox.resources.hazard import HazardResource
9+
from epacomp_tox.resources.metadata import MetadataResource
10+
11+
12+
RESOURCE_FACTORIES = {
13+
"chemical": lambda: ChemicalResource(api_key="fake"),
14+
"chemical_list": lambda: ChemicalListResource(api_key="fake"),
15+
"cheminformatics": lambda: CheminformaticsResource(api_key="fake"),
16+
"bioactivity": lambda: BioactivityResource(api_key="fake"),
17+
"exposure": lambda: ExposureResource(api_key="fake"),
18+
"hazard": lambda: HazardResource(api_key="fake"),
19+
"metadata": lambda: MetadataResource(api_key="fake"),
20+
}
21+
22+
23+
def test_all_tools_declare_response_schemas() -> None:
24+
missing = []
25+
for name, factory in RESOURCE_FACTORIES.items():
26+
resource = factory()
27+
for tool in resource.get_tools():
28+
if not tool.get("responseSchemaRef") and not tool.get("outputSchema"):
29+
missing.append(f"{name}:{tool['name']}")
30+
assert not missing, f"Missing response schema for: {', '.join(missing)}"

0 commit comments

Comments
 (0)