Skip to content

PLAN — P56b Tool Definition Digest Binding (Q2 2026)

  • Date: 2026-04-29
  • Owner: Evidence / MCP Security
  • Status: Implemented
  • Scope: Bind supported assay.tool.decision evidence to a bounded MCP tool definition digest when a reviewed tool definition surface is available, without claiming tool safety, signature validity, or registry truth.

1. Goal

Make supported MCP decision evidence show which bounded tool definition surface was reviewed for the tool that was allowed, denied, or sent to approval.

P56a made the policy snapshot boundary self-describing. P56b adds the companion tool-definition boundary:

decision evidence
  + policy_snapshot_digest
  + tool_definition_digest

The point is reviewability. P56b does not make the tool safe, trusted, signed, approved, or globally registered.

P56b makes the reviewed MCP tool-definition boundary self-describing on supported assay.tool.decision events. It does not add tool truth, signature trust, registry trust, or implementation truth.

2. Current Seams

Assay already has three related surfaces:

  • ToolIdentity in crates/assay-core/src/mcp/identity.rs, currently made from server_id, tool_name, schema_hash, and meta_hash for pinning and drift detection.
  • MCP proxy discovery, which computes tool identity from tools/list responses and caches it for later tools/call decisions.
  • assay mcp tool sign / assay mcp tool verify, which use x-assay-sig, JCS, and DSSE-style PAE over a tool definition with the signature field removed.

Those seams are useful but not yet the same as a single, self-describing decision-evidence digest. P56b should create that reviewer surface without collapsing identity pinning, signing, and runtime decision evidence into one overbroad concept.

3. Supported v1 Surface

P56b v1 should be limited to supported MCP tool definitions observed from tools/list.

The bounded canonical input is a JSON object containing only:

  • name;
  • optional description;
  • optional input_schema;
  • optional server_id only when the observed tools/list definition is already emitted in a server-scoped context and omitting the server label would collapse distinct reviewed definitions.

Before canonicalization:

  • top-level fields are closed for v1: only name, description, input_schema, and conditionally server_id are allowed in the projection;
  • inputSchema and input_schema MUST normalize to input_schema;
  • description is part of the review boundary because it is agent- and reviewer-facing tool text;
  • description values MUST be trimmed at the boundary; if the trimmed value is empty, the field MUST be treated as absent; internal whitespace is preserved;
  • server_id MUST be absent unless the observed definition is server-scoped and omission would collapse distinct reviewed definitions;
  • the full normalized input_schema object MUST be included, not a reduced schema subset;
  • JSON object key ordering MUST NOT affect the digest;
  • no x-assay-sig field;
  • no provider metadata or vendor extension fields outside input_schema;
  • no top-level vendor extensions, annotations, display hints, or extra metadata blobs;
  • no runtime result payload;
  • no full registry object;
  • no inferred fields from a later tools/call.

The digest input is the JCS canonicalization of that bounded projection. Unsupported top-level fields are excluded before JCS canonicalization. Schema keywords inside input_schema are preserved as part of the reviewed schema surface rather than normalized into a smaller Assay-specific schema language. This means vendor-specific schema keywords inside input_schema remain part of the reviewed schema surface, while vendor/provider fields beside the tool definition are excluded.

The proposed decision-evidence projection is:

{
  "tool_definition_digest": "sha256:...",
  "tool_definition_digest_alg": "sha256",
  "tool_definition_canonicalization": "jcs:mcp_tool_definition.v1",
  "tool_definition_schema": "assay.mcp.tool-definition.snapshot.v1",
  "tool_definition_source": "mcp.tools/list"
}

If tool_definition_digest is present, the field cluster is atomic: tool_definition_digest_alg, tool_definition_canonicalization, tool_definition_schema, and tool_definition_source MUST also be present.

The v1 cluster values are closed:

  • tool_definition_digest_alg MUST be exactly "sha256";
  • tool_definition_canonicalization MUST be exactly "jcs:mcp_tool_definition.v1";
  • tool_definition_schema MUST be exactly "assay.mcp.tool-definition.snapshot.v1";
  • tool_definition_source MUST be exactly "mcp.tools/list".

Any later source, canonicalization, or schema widening requires a deliberate new version.

4. Relation to Existing ToolIdentity

ToolIdentity remains the runtime pin/drift surface. It should not be silently renamed into P56b.

tool_definition_digest is not a replacement for ToolIdentity.

For v1:

  • ToolIdentity may continue carrying schema_hash and meta_hash;
  • tool_definition_digest should be a separate canonical digest over the bounded tool definition projection;
  • the implementation may derive both from the same tools/list observation;
  • neither surface should invent identity when tools/list was not observed.
  • ToolIdentity may still be used for runtime drift/pinning even when no reviewable tool_definition_digest is present.

This keeps old policy-pin behavior compatible while giving reviewers a single digest for the reviewed tool definition boundary. Absence of tool_definition_digest must not be reinterpreted as absence of tool identity.

5. Relation to x-assay-sig, DSSE, and Transparency Logs

P56b does not require a signed tool.

When a signed tool definition is present, P56b should align with the existing tool-signing domain where possible:

  • x-assay-sig remains the signature carrier;
  • DSSE PAE remains part of the signing/verification path;
  • tool_definition_digest is the decision-evidence review digest;
  • future signature fields, if added, should be separate from digest visibility.

When a signed tool definition and a decision-visible tool_definition_digest are derived from the same observed tools/list surface, they SHOULD use the same bounded canonical projection, minus x-assay-sig, so review and verification do not diverge unnecessarily.

If signing uses that same bounded projection, any divergence between the signing input and the tool_definition_digest input must be treated as a deliberate versioned contract change, not an implementation detail.

P56b must not claim:

  • the signature was verified;
  • the signer is trusted;
  • a transparency-log entry exists;
  • the tool definition came from a trusted registry.

Those are later signing/provenance slices. P56b only makes the bounded tool definition digest visible beside the decision.

6. Implementation Shape

Recommended implementation slices:

  1. Add a small canonical tool-definition projection helper for the supported MCP tools/list shape.
  2. Add deterministic tests for key-order stability, inputSchema normalization, and absence of raw provider metadata.
  3. Cache a ToolDefinitionBinding beside the existing ToolIdentity in the MCP proxy discovery path.
  4. Thread the binding into supported assay.tool.decision emission paths.
  5. Add optional tool_definition_* fields to stable payload parsing as additive Evidence Contract v1 data.
  6. Update ADR-006 and Evidence Contract v1 with the v1 shape and non-goals.

Do not reconstruct a tool definition digest from a later tool call. Project only from an observed bounded definition surface.

7. Boundary

P56b is digest visibility, not tool truth.

It does not mean:

  • the tool is safe;
  • the tool is signed;
  • the signature is valid;
  • the signer is trusted;
  • the tool registry is authoritative;
  • the tool implementation matches the definition;
  • the tool result is safe;
  • the policy snapshot approved the tool definition.
  • the tool definition is retrievable, embeddable, or viewer-ready.

Missing tool_definition_digest means the tool-definition boundary is not visible, not that the tool is safe.

8. Acceptance

  • Supported tools/list to tools/call flows can emit assay.tool.decision with an atomic tool_definition_* field cluster.
  • Decision paths without an observed bounded tool definition omit the cluster rather than inventing a digest.
  • Tests prove digest determinism for equivalent bounded definitions.
  • Tests prove allowed top-level field subsets produce the same digest regardless of JSON key ordering.
  • Tests prove unknown top-level fields are excluded before digesting.
  • Tests prove inputSchema and input_schema normalize to the same digest.
  • Tests prove whitespace-only description handling is deterministic.
  • Tests prove server_id inclusion and omission follow the v1 server-scoping rule.
  • Tests prove x-assay-sig does not affect the digest.
  • Tests prove equivalent signed and unsigned observed definitions can carry the same digest when only x-assay-sig differs.
  • Tests prove provider metadata, top-level vendor fields, and raw tool bodies are not imported into the decision evidence path.
  • Tests prove half-present tool_definition_* clusters are not emitted.
  • Tests prove missing tool-definition digest visibility does not classify as safe or verified trust.
  • Docs clearly distinguish ToolIdentity, tool_definition_digest, x-assay-sig, DSSE, and future transparency-log verification.
  • No new Trust Basis claim, Trust Card schema bump, registry import, or signature-verification claim is introduced in P56b v1.