Assay

io.github.Rul1anPublished by GitHub account Rul1anv3.1.0Updated Oct 24, 2026

The firewall for MCP tool calls. Block, audit, replay with evidence bundles.

VerifiedSTDIODesktop onlyDeveloper ToolsSecurity & Monitoring

Overview

AI-generated overview

Assay is a local policy gate and evidence recorder for MCP tool calls, allowing or denying privileged actions and producing offline-verifiable audit bundles.

What you can do
Assay sits between an agent and routed MCP servers, deciding each tools/call request before it is forwarded and recording the reason for every allow or deny. It exports decisions and bounded observations into tamper-evident evidence bundles that a reviewer can verify offline, and classifies claims as verified, self-reported, inferred, or absent through its Trust Basis and Trust Card artifacts. It also supports policy files, CI integration such as GitHub Actions and SARIF output, and optional kernel-level observation on supported Linux hosts.
When to use it
Use it when an assistant already has MCP tool access and you want a small, reviewable CI artifact that shows which privileged tool calls were allowed or denied and what was actually observed. It fits teams that need bounded auditability and offline replay rather than a hosted dashboard or a single trust score.
Requirements
Runs as a local process over stdio. The release installer covers Linux and macOS; published CLI archives also cover Windows x86_64. Core enforcement and bundle verification need no hosted backend or API key. Source builds require Rust, and the Python wheels target specific CPython versions on macOS and Linux. Optional eBPF/LSM features require a supported Linux host.
Before you install
The installer is binary-only and does not include the bounded quickstart assets; checksums prove byte equality with the published sidecar, not producer identity. Enforcement is fail-closed and denies are cautions rather than verdicts on intent, while an allow only means the call was forwarded. Basic mcp wrap does not automatically create an evidence bundle, and Assay ships no aggregate safety score, so read each artifact's coverage and non-claims before relying on it.

Installation

In SourceWeft

  1. Open Assay in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

Assay

The open, recomputable evidence profile for privileged MCP tool actions.
Assay records what a privileged tool call decided, what was observed, and what stays unproven, so a reviewer can replay the claim offline instead of trusting the agent's account of itself. In enforcement mode, the proxy gate for routed MCP tools/call requests is deterministic and fail-closed, and the enforcing proxy is the reference producer rather than the contract itself. Optional eBPF/LSM instrumentation on supported Linux hosts adds kernel-level observations. CI-native, no backend, bounded by design.

[Crates.io] [CI] [License]

Quickstart · How it works · See it work · MCP example · OWASP MCP Top 10 · Discussions


Agents got real tool access through MCP — and tool poisoning, rug pulls, and confused-deputy OAuth came with it. Assay sits at the tool-call boundary and does three things, in order.

One golden path: the release-pinned agent journey records the nine driven CLI/MCP steps and their exit/stdout contracts. Its protected-action fixture lives in examples/privileged-action-gate/.

Enforce, prove, stay honest

  • Enforce. In enforcement mode, the gate decides tools/call requests routed through it before forwarding, with the precise reason for each allow or deny. Separate controls on supported Linux hosts include cgroup eBPF IPv4/TCP connect filtering (whose hook error path allows connections) and Landlock TCP-connect port allowlisting. assay sandbox --enforce refuses an unavailable backend or conflicting filesystem policy unless --allow-audit-fallback is explicit. --enforce-net requires --enforce; active Landlock network enforcement rejects policies it cannot express as TCP-port allowlists, even with audit fallback enabled.
  • Prove. Configured producers can record decisions and bounded observations for export into offline-verifiable, tamper-evident evidence bundles. The privileged-action flow carries the verdict, pre-call establish journey, and declared-vs-observed conformance for CI review without a hosted backend. assay mcp wrap --decision-log records tool-call decisions; assay evidence prepare-incident-package turns that log into an incident package verify-incident-package accepts, with the surface grades the verifier derives. The package is not a count of all calls, not completeness of capture, not proof of what the server did, and an allow is not proof a human accepted.
  • Stay honest. Trust Basis classifies supported claims as verified, self_reported, inferred, or absent; its gates check the declared claim boundaries. A tool returning "success" is the provider's assertion, never proof. Assay ships no single safety score; read each artifact’s source, coverage and non-claims before relying on it.

Quickstart

bash
# Fast path: release installer for Linux and macOS.curl -fsSL https://getassay.dev/install.sh | sh
# Confirm the command resolves; if setup fails, run `assay doctor`.assay --version
# Source-build alternative (requires Rust):cargo install assay-cli --version 6.21.0 --locked
python3 examples/mcp-quickstart/run.py

For v6.21.0, run the last command from a source checkout or an extracted published CLI archive. The installer is binary-only and does not carry the bounded quickstart assets. The live getassay.dev installer verifies the selected archive against its published SHA-256 sidecar before extraction. Set ASSAY_REQUIRE_PROVENANCE=1 to additionally require GitHub artifact provenance; the default reports provenance_not_requested and strict success reports provenance_verified. A checksum proves byte equality with the published sidecar, not producer identity. Provenance identifies the source and build, not runtime safety or semantic correctness.

Captured runner output (the bundled local mock performs no external action):

text
assay quickstart: PASSmcp_requests=initialize,tools/list,tools/calldecision=allow tool=read_filedecision_artifact=.assay/quickstart/decisions.ndjsonnon_claim=forwarded_to_local_mock_only

[Assay decides each MCP tool call before it runs, fail-closed, with the reason]

Released surfaces:

  • Static project manifests are shipped for Claude Code and Cursor; Codex uses the equivalent TOML entry documented in the editor MCP recipe. Manifest presence is not host-discovery proof. assay mcp config-path supports Claude Desktop and Cursor only.
  • Published v6.21.0 CLI archives cover Linux x86_64/arm64, macOS x86_64/arm64, and Windows x86_64. The Python wheels cover CPython 3.12, 3.13, and 3.14 on macOS x86_64/arm64 and Linux x86_64; other interpreters and platforms are not claimed.
  • Published assay-mcp-server archives cover Linux x86_64/arm64. MCPB and server.json package descriptors are also published; their presence is not host-discovery proof.
  • CI: GitHub Action. Core flows need no hosted backend or API key. New to the threat model? The OWASP MCP Top 10 mapping states, per risk, what Assay covers and deliberately does not.

What ships

OutputWhat it is
Policy gateassay mcp wrap — deterministic allow/deny before tools run, with the reason.
Evidence bundleOffline-verifiable, tamper-evident archive for audit and replay.
Trust Basis / Trust CardCanonical trust-basis.json (bounded claim classification) plus review-friendly trustcard.{json,md,html}.
External receiptsEval outcomes, runtime decisions, and model inventory as bounded receipts with JSON Schema contracts.
Tool-decision logsFor handled known-tool calls, the assay-mcp-server stdio server emits an info-level tool_decision event when enabled by its log filter; decision contains a JSON-encoded observed decision entry with projected target fields.
SARIF / CIGitHub Action, Security-tab integration, policy gates on PRs.
AttestationSign an evidence bundle as a DSSE-wrapped in-toto v1 Statement with the evidence-bundle/v1 predicate.
text
  Agent ──► Assay ──► MCP Server              ├─ ✅ ALLOW / ❌ DENY  (policy, with reason)              ├─► 📋 Evidence bundle (offline-verifiable)              └─► 📊 Trust Basis → Trust Card → SARIF / CI

Current release: v6.21.0. CHANGELOG.md and release notes remain the authority for released behavior; merged changes after the tag are Unreleased, and crates.io publication is separate from merge state. Launch definition and support commitment: docs/LAUNCH.md.

Is this for me?

Yes if you already have eval output, runtime decisions, inventory artifacts, or MCP tool-call tests, and you want a small reviewable CI artifact instead of a dashboard — bounded auditability, not a scalar trust badge.

Not yet if you need Assay to judge model correctness for you, want a hosted dashboard as the product, or want a compliance claim rather than a bounded evidence boundary. Assay is not a trust-score engine, a generic eval dashboard, or a hosted observability product — see what it is and is not.

See it work

An agent tries a privileged action — github.add_deploy_key — through the enforcing proxy, decided per call before it forwards, offline against a local mock (no real credentials):

bash
cd examples/privileged-action-gate && ./run.sh

[privileged-action PR-gate demo]

A deny is fail-closed caution, not a verdict on intent; an allow is the decision to forward, never proof the action happened. Declared-vs-observed conformance is recorded beside the verdict, never as a gate. Full walkthrough: privileged-action-gate.

Pick your path

You haveWhat you getStart here
Promptfoo JSONL from CI evalsEval outcome receipts + verified bundle + Trust Basis diffPromptfoo JSONL
OpenFeature EvaluationDetailsDecision receipt + verified bundleOpenFeature
CycloneDX ML-BOM model componentInventory receipt + verified bundleCycloneDX ML-BOM
MCP tool callsAllow/deny audit trail + observed-behavior evidenceMCP Quick Start
A GitHub PR gateTrust Basis diff, gate status, SARIF/JUnit-ready outputCI Guide
A Runner archive / coverage annotationCoverage descriptors + claim-class cells + a claimed-vs-observed checkCoverage-honesty walkthrough

The workflow stays small: import or record a bounded outcome, bundle and verify it, compile trust-basis.json, gate the Trust Basis diff. Assay doesn't make the upstream tool the source of truth; it makes the evidence boundary inspectable. For privileged tool actions, the MCP proxy records each tools/call as a structured tool-decision surface — keeping the asserted-versus-verified line honest.

Policy is simple

yaml
version: "2.0"name: "my-policy"tools:  allow: ["read_file", "list_dir"]  deny: ["exec", "shell", "write_file"]schemas:  read_file:    type: object    properties:      path: { type: string, pattern: "^/app/.*" }    required: ["path"]

assay init --from-trace trace.jsonl generates the runtime-observation policy used by the trace-generation flow (files, network, and processes); it is not an MCP authorization policy. Migrate a legacy MCP constraints: policy with assay policy migrate. See Policy Files.

Why Assay

Canonical evidenceAssay's evidence model is the stable contract; OpenTelemetry and protocol adapters (ACP / A2A projection profile / UCP) map into it.
DeterministicThe policy gate uses explicit rules; its decision depends on the request, policy and applicable session state. This does not make live evaluators or external effects deterministic.
Bounded claimsExplicit about verified vs visible vs absent — no score-first UX.
Offline-firstNo backend required for core enforcement and bundle verification.
Checkable provenanceWhich piece of the source-class and coverage model shipped when, as commits you can git log rather than claims you have to take — provenance, prior art credited first.

Learn more

Evidence epistemology, latency, and the internal Runner

Trust claims use explicit epistemology, not a single safety score: verified (direct evidence or offline verification), self_reported (emitted without independent corroboration), inferred (bounded, documented rules), absent (no trustworthy evidence). Assay ships no aggregate trust score or safe/unsafe badge as the main output — see ADR-033.

The historical fragmented-IPI experiment results, dated 2026-03-02 and naming commit 289a43ecc144, report 0.771ms p50 / 1.913ms p95 for the deterministic set. The harness times complete local mock tools/call round trips, including JSON-RPC transport and the tool response. These reported timings do not isolate policy-decision overhead or establish current-release or end-to-end model performance.

Assay-Runner is an internal/experimental measured-run subsystem behind the delegated Linux/eBPF acceptance path. Its crates are included in the workspace publication process so dependent packages can resolve them; publication does not make Runner a standalone product or give its APIs a separate stability commitment.

Ecosystem

Related projects for evidence generation, verification, and reviewability; each has its own interface and scope:

  • assay-action — GitHub Action: verify bundles, PR summaries, SARIF (Marketplace).
  • Assay-Harness — recipe, gate, and report layer over canonical evidence artifacts.
  • observed-effect-v0 — worked examples of the bounded observed-effect evidence record and its neutral carriers (in-toto, SCITT, MCP evidenceRef).
  • gateway-evidence-replay — deterministic offline replay verifier for gateway-path evidence bundles.
  • RGE-Bench — a conformance kit for evidence reviewability, maintained separately under its own machine-checked neutrality guard. Reproduction there is digest-scoped and does not carry forward: the v1 71-vector digest sha256:e769822bc6c9e31085da7b1a17b163b9747fe0d04314fbb8685d4e612087c7cb and the historical v2 digest sha256:ba0e3795d75c788fa48313ab462493f22d78759851d1b3275d8117051bb22fd0 (95 vectors) each carry one reported independent implementation by a second author on a different stack. JM-Lab reported the v2 95/95 reproduction on 2026-08-24, from the contract text and author-supplied inputs without reading expected. Neither reproduction transfers to the current 104-vector v3 candidate digest sha256:93f8ae9654eb5a16dee28d882087669cae5183e02e116ba1e8071a30594cfb6a, which the record lists as unreproduced. See its REPRODUCTIONS.md.

Open profile: privileged-mcp-action/v0

privileged-mcp-action/v0 is a composition and verification contract over evidence records that already exist: what a privileged MCP tool call decided, what was observed of its effect, and what stays unproven. It adds no new envelope and no aggregate verdict.

It ships with a 14-vector conformance corpus (5 accept, 9 reject) whose digest is a candidate: it is not called reproduced until a non-author implementation derives the expected outcomes from the specification text alone.

That reproduction is open, and the invitation is real: #1840. Any language, any stack. The invitation names the exact commit the current digest describes. The clean-room protocol provides an opaque, attested inputs pack, a one-command scoring action, and an implementation-report template without supplying verifier logic or expected outcomes. The corpus README states the authorship boundary and the claim ceiling.

Contributing

bash
cargo test --workspacecargo clippy --workspace --all-targets -- -D warnings

See CONTRIBUTING.md and GitHub Discussions.

License

MIT

Source: README.md at commit 6b259f6

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v3.1.0LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts