materials-semantic-mcp
by Tehscientist
README.md
# materials-semantic-mcp
An MCP server that gives agents **meaning, not access**: governed metric
definitions over a materials test lab, plus agent memory that can't enter
the system without a provenance label.
Built by a materials & clinical engineering manager who spent years running
V&V documentation, now applying the same discipline to agent systems. The
dataset is synthetic; the governance problems are real.
## The thesis
Give an agent your database and it will rediscover — differently each run —
what "first-pass yield" means, which joins are valid, and which numbers are
comparable. Give it a **semantic layer** and those meanings are defined
once, versioned, owned, and enforced. Agents don't need access to your
data. They need access to your definitions.
The same argument applies to what agents *learn*. Unlabeled model-generated
memory that becomes instruction is an **uncontrolled document** entering
your quality system. Here, every memory carries a provenance label — a
disposition record — and the write rules are enforced, not suggested.
## Architecture
```text
semantic/metrics.yaml ← definitions: formula, unit, grain, dimensions,
│ access rules, owner, lineage (SINGLE SOURCE OF TRUTH)
▼
src/semantic_layer.py ← interprets definitions (whitelist-validated at
│ load); computes metrics; rejects ungoverned
│ dimensions; withholds gated identities by role
▼
src/server.py (MCP) ← thin wiring: 5 agent tools, role injected by deployment
src/memory_admin.py ← operator CLI: the human gate (confirm/deprecate)
▲
src/memory.py ← provenance-labeled write-back (se10)
```
## Tool surface
| Tool | Contract |
|------|----------|
| `list_metrics` | Every governed metric with its definition — the menu is the documentation |
| `explain_metric` | Formula fields, source table, reviewed join path, definitions version |
| `query_metric` | Computes from the definition; disallowed dimensions rejected; gated dimensions withheld (aggregated away) below `engineering` role |
| `remember` | Agent writes require `observed` or `inferred` + a source; anything else is rejected |
| `recall` | Authority-ordered: authoritative > user-confirmed > observed > inferred; stale excluded by default |
Promotion and deprecation are deliberately absent from this table — see
"Where the human gate actually lives" below.
## Resources
Read-only views of the definitions — browse without calling a tool.
| Resource | Contract |
|----------|----------|
| `semantic://metrics` | Full text of `semantic/metrics.yaml`, the governed definitions |
| `semantic://metrics/{name}` | One metric's definition block; unknown names return error text |
## Provenance as disposition (the V&V translation)
| Label | Who establishes it | QMS analogue |
|-------|--------------------|--------------|
| `observed` | Agent, from direct evidence | Raw test record |
| `inferred` | Agent, by conclusion | Engineering judgment, unreviewed |
| `user-confirmed` | Human review | Reviewed & approved record |
| `authoritative` | Human designation | Controlled specification |
| *stale* (status, not label) | Time, via `sweep_stale` | Past review-by date |
Rules enforced at write time: agents may write `observed`/`inferred` only;
promotion requires a human; unlabeled writes are rejected; confirmed
memories never age out silently — humans deprecate them with a reason.
Memories also inherit the ACCESS ROLE of the session that wrote them, and
recall filters to at-or-below the caller's role — found live when a public
session recalled supplier-gated rates an engineering session had
remembered (se04 routing eval, 2026-07-09). Query-time masking means
nothing if gated data can round-trip through memory.
**Where the human gate actually lives.** Promotion (`confirm`) and
deprecation are NOT MCP tools — an agent-callable tool that stamps
"human" is a forgeable gate (found by adversarial review, 2026-07-09).
The agent-facing surface is exactly five tools: `list_metrics`,
`explain_metric`, `query_metric`, `remember`, `recall`. Promotions run
through the operator CLI and record who signed:
```bash
python src/memory_admin.py --memory-db data/memory.db list
python src/memory_admin.py --memory-db data/memory.db confirm 12 --by "Iver Olsen"
python src/memory_admin.py --memory-db data/memory.db deprecate 12 --reason "superseded"
```
## Quickstart
```bash
uv sync # or: pip install -e . --group dev
python src/generate_dataset.py --db data/lab.db # synthetic, seeded
python -m pytest tests/ -q # 58 tests (CI runs these on every push)
MCP_ROLE=engineering python src/server.py --db data/lab.db
```
Claude Desktop / Claude Code config:
```json
{
"mcpServers": {
"materials-semantic-layer": {
"command": "python",
"args": ["src/server.py", "--db", "data/lab.db"],
"cwd": "/path/to/materials-semantic-mcp",
"env": { "MCP_ROLE": "public" }
}
}
}
```
The role lives in the deployment environment, not the conversation — an
agent cannot talk its way into `engineering`.
## What the tests pin down
Metric math equals hand-written ground-truth SQL; populations honor their
`where` clauses (ESC-only, cracked-only); ungoverned dimensions and unknown
metrics reject; identity-gated dimensions are aggregated away for `public`
(one row, no per-supplier shape, no hidden ordering — masking labels is not
access control) and appear in full for
`engineering`; filter values are parameterized (injection-shaped input
returns zero rows, not a breach); provenance write rules, promotion gates,
supersede chains, and the stale sweep are all deterministic and covered.
## Data
Fully synthetic, generated by a seeded script shaped like a polymer test
lab: ESC (environmental stress cracking), wet-patch chemical exposure, and
tensile runs over resin batches from fictional suppliers — including one
problem supplier and one with sloppy paperwork, so governance questions
have answers worth finding. No real supplier, material, or employer data.
## Roadmap
- ~~Wire into the Materials RAG agent + 10-case routing eval~~ — done
(materials-rag branch `se04/semantic-mcp-wiring`; predictions grade as
honest declines until a validated prediction tool exists)
- Model-swap eval experiment: same tools, same gold sets, second lab's
model — publish the delta
- Blog: *The Semantic Layer for Agents* — definitions, not data
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues