mcp-tool-provenance is a small, zero-dependency library with two independent capabilities — result stamping and surface triage — that share nothing but the vendored envelope types. No I/O, no global state, no framework coupling, no MCP SDK dependency.
| Module |
Responsibility |
mcp_tool_provenance/envelope.py |
stamp() — wrap a tool result with a _toulmin (5-key) + _tags (4-key) envelope, non-destructively. is_stamped() — predicate that an envelope is present and complete. _coerce_toulmin / _coerce_tags normalize either a vendored value object or a plain dict to the canonical envelope dict. TOULMIN_KEYS, TAG_KEYS. |
mcp_tool_provenance/triage.py |
triage() — build a MECE surface map {real_dispatch, read_only, native_only}. drift_check() / assert_no_drift() — the anti-inflation gate (report / raise). surface_summary() — the honest reportable split. DriftReport, DriftError, BUCKETS, classified_set(). |
mcp_tool_provenance/_vendor/toulmin_argument/ |
Vendored toulmin-argument v1.0.0 — the ToulminArgument value object used in the envelope. |
mcp_tool_provenance/_vendor/provenance_tags/ |
Vendored provenance-tags v1.0.0 — the ArtifactTags four-dimension tag block used in the envelope. |
mcp_tool_provenance/__init__.py |
Re-exports the public API (incl. the vendored value objects) + __version__. |
# Stamping
tool handler ──► result dict ──► stamp(result, toulmin=…, tags=…) ──► {**result, _tool?, _toulmin, _tags}
(result unchanged; new dict returned)
# Triage / gate
tool registry (source of truth) ─┐
├─► drift_check(registry, classification) ──► DriftReport(ok, unclassified, multiply_classified, …)
classification = triage(...) ────┘ │
surface_summary(...) ──► honest counts (executes_server_side, native_only_count)
| Seam |
How to use it |
| Envelope inputs |
stamp(..., toulmin=, tags=) each accept either the vendored value object (ToulminArgument / ArtifactTags) or a plain dict — build the envelope however your code prefers. |
| Tool name |
stamp(..., tool_name=) — optional; recorded under _tool only when non-empty. |
| The registry |
drift_check(registry, ...) takes the caller's source-of-truth tool list (e.g. the keys of your adapter dict). The buckets are fixed; the tools are yours. |
| Report vs. raise |
drift_check() reports drift (returns a DriftReport); assert_no_drift() raises DriftError carrying that report — pick per call site (runtime probe vs. CI gate). |
| Runtime dependencies |
None. The envelope types are vendored (pure stdlib) — see KERNEL_SYNC.md. |
| Persistence / transport |
Caller-owned — the library only produces dicts and reports; it never talks to a DB or an MCP socket. |
- Stamping is non-destructive. The input payload is never mutated; a fresh dict is returned with the original keys verbatim plus the envelope.
- The envelope shape is fixed.
_toulmin always has exactly the five argument keys; _tags always has exactly the four tag keys.
- Triage is MECE or it fails. A classification is valid only when every registry tool is in exactly one of the three fixed buckets —
drift_check is the enforcement, not a convention.
- Domain-neutral. No default value, bucket, or tool name references any industry or product. The buckets describe what a tool does (dispatch / read / guidance), not what domain it serves.