MCP Fusion/Security and governance/Contracts and lockfile

Contracts and lockfile

Ask AI about Vinkius

The behavioral contract of a connector: canonical SHA-256 surface digests, mcpfusion.lock, contract diff verdicts in CI, blast radius entitlements and HMAC attestation.

An AI connector is a public API whose consumer is a language model. Descriptions, required fields and error shapes are behavior. MCP Fusion turns that behavior into a materialized contract, hashes it, diffs it and locks it, so a change is a reviewable event rather than a silent drift. Governance is the workflow; this page is the machinery.

Materializing the contract

For each tool the framework compiles a ToolContract with four sections:

SectionContents
surfacedescription, actions, input schema digest
behavioregress schema digest, system rules fingerprint, destructive and read-only actions, middleware chain, affordance topology, cognitive guardrails
token economicsinflation risk, schema field count, unbounded collection flag
entitlementsfilesystem, network, subprocess, crypto, code evaluation

Entitlements are not declared by you. EntitlementScanner reads the handler source (its function text) and detects capabilities with regex families: fs.* and stream calls, fetch and HTTP clients, child_process and workers, crypto signing and ciphers, and code evaluation. Evasion heuristics catch the interesting cases: (0, eval), computed global access, non-literal require, String.fromCharCode reconstruction, base64 blobs, escape-sequence density above roughly 15%, and high Shannon entropy in long literals. A read-only action that writes files or spawns a process is a violation, not a warning.

The lockfile

bash
mcpfusion lock
mcpfusion lock --check

Each section is canonicalized to sorted-key JSON and hashed with SHA-256; the four section hashes compose into one per-tool digest, and the sorted per-tool digests compose into the server digest. The result is mcpfusion.lock:

json
{
  "lockfileVersion": 1,
  "serverName": "billing",
  "mcpfusionVersion": "...",
  "generatedAt": "...",
  "integrityDigest": "sha256:...",
  "capabilities": {
    "tools": {
      "billing": {
        "integrityDigest": "sha256:...",
        "surface": { "description": "...", "actions": [], "inputSchemaDigest": "..." },
        "behavior": { "egressSchemaDigest": "...", "systemRulesFingerprint": "...", "middlewareChain": [], "affordanceTopology": [] },
        "tokenEconomics": { "inflationRisk": "low", "schemaFieldCount": 8, "unboundedCollection": false },
        "entitlements": { "filesystem": false, "network": true, "subprocess": false, "crypto": false, "codeEvaluation": false }
      }
    }
  }
}

Serialization is deterministic (sorted keys, two-space indent, trailing newline), so the file is diffable in review. --check recomputes and exits non-zero when anything drifted: that exit code is the CI gate.

Diffing: what kind of change was that

diffContracts(before, after) classifies every delta, and the classification is the review policy:

VerdictExamples from the rules
BREAKINGtool renamed, input schema digest changed, action removed, destructive or read-only flag changed, a new required field, a Presenter removed, egress digest changed, system rules changed, inflation risk escalated, a handler gained an entitlement
RISKYidempotency flag changed, per-action schema changed, Presenter swapped, a guardrail removed (limit or byte cap set to null), middleware chain changed, state-sync or concurrency fingerprint changed, embedded presenters changed, a collection became unbounded
SAFEaction added, required field removed, tags removed, guardrail tightened, inflation risk reduced, collection bounded, entitlement lost
COSMETICdescription changed, tags added

A lost entitlement is SAFE because the blast radius shrank. An added entitlement is BREAKING because a reviewer must see it. That asymmetry is deliberate.

Attestation

Hashing proves two artifacts differ; attestation proves the one running is the one you approved. attestServerDigest(digest, { signer: 'hmac', secret }) signs the server digest with HMAC-SHA256 (secrets shorter than 32 characters are rejected in production), and at startup the server recomputes its digest and compares: on mismatch it refuses to boot with AttestationError. Signers are pluggable for a KMS or a transparency log, and comparison is constant-time. The trust capability is also exposed to clients as mcpfusionTrust.

Semantic probes

Descriptions are behavior too, and description drift is invisible to structural diffs. A semantic probe replays known-good inputs, sends the baseline and current outputs to a judge with the tool's contract, and scores similarity: at or above 0.95 is no drift, 0.75 low, 0.5 medium, below high. Failed probes degrade to a neutral medium score rather than blocking, and the module never calls the network on its own: you inject the judge adapter.

Self-healing in the error path

When a contract changes under a running agent, the failure is not a mystery: with selfHealing configured, validation errors embed a <contract_awareness> block carrying the BREAKING and RISKY deltas for the failing action (capped, five by default), plus the instruction to adapt. The agent learns the new contract in the same turn it violated the old one. See Errors.

Next steps