Consider two failure modes that have both been reported publicly. An unofficial MCP server silently forwards a copy of every message it sends to an attacker-controlled address. A widely installed MCP client package carries a remote-code-execution flaw for months before the CVE is published.
Authorization alone does not resolve compromised code or data exfiltration. A retained decision record could contribute to an investigation, alongside operational logs and other evidence. It would not itself detect either flaw or establish everything the server did.
MCP solved the integration problem. Thousands of servers connect AI agents to databases, file systems, APIs, and physical control systems through a single standardized interface. Major AI platforms have adopted it, and the Linux Foundation hosts the protocol. The ecosystem is real.
Integration, prevention and later evidence review are different tasks.
In March, the MCP project published its 2026 roadmap. That March 9 snapshot identifies audit trails and gateway behavior within enterprise readiness, while discussing additional security work separately. It is not evidence that the ecosystem has no governance work or that its implementation status has remained unchanged.
Allowlists, server inventories, drift detection and consent gates address important parts of MCP security. Monitoring records can also be protected with access controls, write-once storage, signatures or external custody. AGA addresses a narrower handoff: checking an exported gateway record offline, with a separately established expected key.
Errico et al. formalized the problem around three adversary types: content-injection attackers who embed malicious instructions in data sources agents process, supply-chain attackers who publish compromised servers or silently modify trusted ones, and agents that become unintentional adversaries by overstepping their scope. Among their open research problems are verifiable tool and server registries, because a user who finds a server has “no cryptographic assurance about its code or operational history”; elsewhere they call for hardening monitoring infrastructure with “integrity protections, access controls, and tamper-evident logging.”
Several MCP security analyses published in the past year point at the same gap. This article describes one way to fill part of it, and says which part ships today.
What governance actually requires
Access control asks is this entity authorized? Monitoring asks what activity can we observe? Logging preserves what a collector recorded, which may include independent observations rather than the agent's own report.
A separate evidence-review question cuts across those controls: what can someone else check from the retained record?
If an agent can modify its audit trail, that is a deployment risk to address with isolation and appropriate storage controls. Signing can make later alterations detectable against an expected key, but key protection, retention and ensuring that intended actions reach the recorder remain separate deployment requirements.
The architecture has four parts. A sealed reference: expected behavior fixed before execution begins, signed, and inaccessible to the governed entity. Measurement: runtime state compared against that reference, each comparison producing a signed receipt. A sealed decision: when measured state diverges from sealed state, the decision is signed without waiting for a human. Tamper-evident evidence: each recorded decision appended to a chain where altering an entry breaks verification, checkable offline. The published packages implement the decision and evidence parts for tool calls; scheduled measurement of servers is architecture, not shipped.
Beneath all four sits a two-process boundary. One process holds the signing key; when it runs under its own identity the other holds none, so the governed entity cannot sign a receipt. Whether its traffic can go around the boundary is a property of the deployment.
Keep the signing key out of the agent's reach.
How AGA records MCP tool calls
AGA works in three phases (Seal, Capture and Prove) that cover the four parts above. For each, here is the architecture and what ships.
Seal: fix the policy before the first call.
In the architecture, before an MCP server processes its first tool call, the gateway creates a signed Policy Artifact binding the server's identity (hashes of its binary and canonicalized configuration), the governing policy, and governance parameters. Without the signing key, modifying any field invalidates the signature. In the published aga-proxy, the policy is a JSON file listing permitted tools and constraints; the SHA-256 of its canonical JSON is signed into every receipt (reformatting the file does not change it), and nothing hashes the server's binary.
Current MCP registries are directories: a server registers its capabilities, and clients trust the registration. In the architecture, a sealed artifact binds what the server is at a point in time, so a server that behaves differently from what it advertised, or is modified after adoption, produces a hash mismatch at the next measurement. The published packages do not measure MCP servers. What aga-proxy does is decide and record every tools/call it evaluates (known issue 7 on /security describes the calls refused without a receipt).
Capture: decide each call, and in the architecture measure the server.
aga-proxy evaluates each tools/call against the policy (under an allowlist policy: the tool list, rate limits, and path and substring rules, which known issue 10 on /security qualifies), signs PERMITTED or DENIED (known issue 7 on /security describes the exceptions), and does not forward a call it denies. Its default profile, permissive, denies nothing on policy grounds; policy denial needs --profile standard or restrictive, or a --policy file in allowlist or denylist mode. In the architecture, two kinds of measurement also run.
Structural measurement (architecture, not shipped) computes a hash from the server's binary, configuration and runtime parameters and compares it with the sealed reference, which is how a modified server would be caught.
Behavioral measurement works at a different level: it compares tool invocation patterns (which tools, in what sequences, at what rates) with a baseline, which catches attacks that change what an agent does without changing what it is. aga-mcp-server 3.6.0 through 3.6.2 ships a rule-based version over its own governed tools, run when the client asks; statistical baselines are architecture.
In the architecture, the sealed artifact specifies the decision on drift, and the gateway seals it into a signed receipt. In aga-mcp-server 3.6.0 through 3.6.2 a mismatch puts the server in QUARANTINE, and a revocation, or a TTL expiry found at the next measurement, puts it in TERMINATE, both in process and outside the exported bundle, which shows the calls refused afterward and, for a revocation, the revoke_artifact call itself. The governed client can lift a quarantine, revocation or termination by calling attest_subject, and the exported bundle does not record that call. Effecting a decision beyond aga-proxy's own forwarding is wired per deployment.
The quarantine design, which does not ship, contains a server in a phantom environment: its connections to protected resources are severed at the deployment boundary while it keeps running, and every step is signed and appended to the receipt chain. What ships in aga-mcp-server 3.6.0 through 3.6.2 is narrower: it refuses each governed call with a GOVERNANCE_QUARANTINED error and records a DENIED receipt. aga-proxy has no quarantine mode. We described the design in our previous article.
The governed server holds no signing key when the gateway runs under its own identity, and then cannot sign a receipt. Whether traffic can bypass the gateway is a property of the deployment.
Prove: each recorded decision is a signed receipt.
Each decision aga-proxy records is a signed Decision Receipt (known issue 7 on /security describes the exceptions): the tool name, the decision and its reason, an arguments hash, the SHA-256 of the policy's canonical JSON, a timestamp, and the previous receipt's hash, linking it into the receipt chain. In aga-mcp-server 3.6.0 through 3.6.2, a measurement drift finding is signed in process and is not in the exported bundle.
Arguments are committed by SHA-256 hash, so a third party verifies the chain end to end without the argument contents; in 3.6.0 through 3.6.2, a path-constraint denial records the offending path in its signed reason, and a denied-pattern denial records the matched pattern. Against the gateway's pinned key, an added, altered, reordered, or truncated entry fails verification, though a field name repeated in the file still verifies, because the verifiers read the last copy (known issue 5 on /security). An earlier genuine export presented as the current one still verifies, because the verifier has no freshness input. Completeness of capture is bounded by the interception point: the chain proves the record, not that every action was recorded.
The chain is bound by a signed checkpoint over its count, head and Merkle root. Publishing that checkpoint to an append-only log that parties other than the key holder monitor is a deployer integration that is not shipped. Until those parties compare the checkpoints they saw, the key holder could re-sign a different history; a log the key holder runs alone does not prevent that.
The evidence package (signed Decision Receipts, Merkle inclusion proofs, the signed checkpoint and the public key) ships as a self-contained Evidence Bundle. Verification is six checks, seven with a pinned issuer key:
- Structural floor: the algorithm identifier and key are well-formed and every receipt matches the strict schema.
- Verify each Decision Receipt signature against the gateway's key.
- Validate receipt chain continuity via previous_receipt_hash linkage, with non-decreasing timestamps.
- Compute each leaf hash as SHA-256 of the canonical receipt, including its signature, verify Merkle inclusion proofs, and confirm the proof set is a bijection over the receipts.
- Verify the gateway-signed checkpoint binds the recomputed Merkle root, leaf count, and chain head.
- Envelope consistency: the bundle's stated roots match what was recomputed.
- Gateway key match, only when a pinned issuer key is supplied: confirm the bundle was signed by that key.
All of these checks work offline, with no callback to the originating system and no reliance on either side's logs; what remains is trust in the key you pinned. The in-browser verifier demonstrates this with zero AGA imports, using standard Ed25519 and SHA-256. The format is published, so any implementation can reproduce the check.
The three MCP adversaries
Errico et al. identify three adversary types that exploit different properties of the MCP architecture. Here is what the published packages do about each.
Content injection. Someone embeds malicious instructions in a support ticket, an email or a shared document, and the agent follows them. The published packages do not detect injection. What they do is narrower: aga-proxy denies tool calls outside the policy and records its decisions (known issue 7 on /security describes the calls refused without a receipt), so an injection that pushes the agent toward an unapproved tool leaves a signed DENIED receipt, and even partial attacker success leaves a signed, hash-chained record of the decisions that were governed. Statistical behavioral detection is architecture.
Supply chain compromise. A malicious actor publishes a compromised server, or modifies a trusted one after adoption. In the architecture, a sealed artifact binds the server's identity and measurement catches post-deployment modification. The published packages do not measure MCP servers, so 3.6.0 through 3.6.2 does not address this adversary beyond recording, and constraining, the calls made to the server.
Inadvertent scope escalation. An agent reads customer records, queries a database and sends an email in one interaction, crossing several security domains while trying to be helpful. aga-proxy's allowlist bounds which tools a governed agent can call through the gateway, and aga-mcp-server includes a delegation tool whose derived scopes can only shrink. Neither judges whether a sequence of individually permitted calls crossed an intended boundary.
Standards alignment
AGA maps onto the frameworks organizations are evaluating for MCP security. The claim is architectural alignment, well short of a compliance certification.
NIST AI RMF describes Measure and Manage functions for AI system governance. Signed receipts can contribute evidence to a specific review task; they do not satisfy those functions by themselves. We filed technical comments on both the NIST CAISI RFI on AI Agent Security (NIST-2025-0035) and the NCCoE AI Agent Identity and Authorization concept paper; both are kept as filed.
The EU AI Act's high-risk obligations phase in across 2027-2028 (December 2, 2027, for standalone high-risk systems; August 2, 2028 for those embedded in regulated products). Evidence bundles can form part of the Article 12 record-keeping a high-risk system needs. They do not by themselves meet Article 9 risk management or Article 14 human oversight.
Implementation
The AGA MCP Server is published on npm:
npm install @attested-intelligence/aga-mcp-server@3.6.6The package has two execution paths. aga-proxy governs another MCP server's tool calls; its agent port uses raw newline-delimited TCP, so a stdio MCP client needs a relay you provide. None ships. The MCP server's own toolset covers artifact operations, caller-supplied content measurement, a rule-based behavioral check, demonstration disclosure and delegation tools, bundle export and verification. Review the isolated-evaluation prerequisites and known issues before running either path.
The historical 3.6.0 release CI reviewed September 21, 2026 reported 428 tests. The retained conformance snapshot reports 61 classical cases across JavaScript, Go and Python, plus 28 composite cases across two language oracles. The harness re-serializes parsed cases, so leaf_index spelled 0.0 runs as an integer. These are historical bounded results, not current-package certification; see the exact conformance scope.
The specification defines the receipt and the checks for anyone building a compatible implementation, and the in-browser verifier reproduces them with zero AGA imports.
npm · Specification · Technology
What this changes
AGA doesn't replace the identity, authentication, and access control work already underway in the MCP community. It sits beneath that work. Once policy is defined and access is granted, the question that remains is what was decided about each call, and whether a third party can check that record without trusting either side's logs. The MCP roadmap puts governance and enterprise readiness on the agenda. The EU AI Act's high-risk record-keeping obligations phase in from December 2, 2027, as amended by Regulation (EU) 2026/1744 of July 8, 2026 (the Digital Omnibus on AI). The gap between what MCP connects and what anyone can check afterward is where disputes stall. MCP gave AI agents a standard way to use tools; what is still missing is a standard, verifiable record of what was decided about each call.
See the working implementation on npm.
AGA is a reference implementation of a published format for verifiable decision records: hash-bound policies, signed Decision Receipts, and Evidence Bundles that verify offline. The implementation is on npm. The evaluation path walks through it in working code.