DocsGetting started

Quickstart

Ten minutes on a fresh machine: install, run the proxy in front of an MCP server, see every tool call screened, and verify an attestation without trusting this site. Node 20+ and pnpm are the only requirements — the verifier ships as WebAssembly, so no Rust or Solana toolchain is needed to use Blindseal.

01

Install and run

shell
$ git clone <repo> blindseal && cd blindseal
$ ./scripts/quickstart.sh          # installs, builds the dashboard, verifies the sample attestation
$ BLINDSEAL_MOCK=1 pnpm -C packages/proxy exec tsx src/index.ts run --mock
blindseal (MOCK): local API on http://127.0.0.1:7777
  dashboard: http://127.0.0.1:7777/#token=…

The proxy serves the dashboard from its own origin with a Content-Security-Policy that allows the WebAssembly verifier and nothing else. Open the printed URL — the token is in the fragment and never leaves memory.

02

Point an agent

In the agent’s MCP config, launch the upstream server through blindseal. Every tool call and result passes the four detection layers locally before it reaches the agent or the server.

json
"mcpServers": {
  "github": { "command": "blindseal", "args": ["--", "github-mcp"] }
}

03

Attest a screened action

An attestation is a Groth16 proof that a specific tool call was screened under a committed policy by a specific detector version and that the deterministic layers passed. Proving runs locally on CPU and takes a while; it is asynchronous by design.

shell
$ blindseal attest call.json --target-program ErAS5x2oUky3aCJPasSKNaf8USVE9of5vzHHCPWwSEVG --out attestation.json
decision d_…: clean (audit #12 0x…)
proving (this takes a while on CPU)…
attestation written: attestation.json

The decision is appended to the hash-chained audit log before proving starts, content-free: only ids, the verdict and the payload hash.

04

Verify it — anywhere

shell
$ blindseal verify attestation.json        # off-chain, the wasm verifier
$ blindseal submit attestation.json        # Solana mainnet: verifies on chain, consumes the nullifier
$ blindseal submit attestation.json --check   # has this nullifier been consumed?

Or drop the file on the verify page: it runs the same verifier in your browser and uploads nothing. submit compares the RPC’s genesis hash with mainnet-beta’s before sending; there is no other cluster.

05 / 17 endpoints

API reference

The local API the dashboard speaks. Auth: Authorization: Bearer <token>. Same-origin only; the browser never contacts an RPC — on-chain reads go through the proxy.

MethodPathDescription
GET/api/statusProxy status: connection, policy root, detector version, audit head, L3 mode.
GET/api/decisionsList decisions; filters verdict/server/tool/from/to, cursor pagination.
GET/api/decisions/:idOne decision with all layer results and commitments.
POST/api/decisions/:id/revealReveal the raw payload (requires X-Confirm: reveal). Never stored.
GET/api/audit/headThe current hash-chain head.
GET/api/audit/entriesContent-free entries in a range (from/to).
POST/api/audit/verifyRecompute the chain from genesis → { ok, brokenAt? }.
POST/api/audit/discloseSigned disclosure for a range { from, to }.
GET/api/policyThe committed policy: root, version, leaf count, rules.
PUT/api/policyReplace rules; the proxy recomputes the Merkle root.
POST/api/policy/dry-runScreen a payload without logging or chaining it.
GET/api/attestationsList attestations; filter by status.
POST/api/attestationsRequest an attestation for a decision with an action.
POST/api/attestations/:id/submitSubmit to Solana mainnet → tx signature.
GET/api/nullifiers/:nullifierOn-chain status of a nullifier (mainnet, read server-side).
GET/api/tee/quoteThe L3 TEE quote (when L3 runs in a TEE).
WS/eventsLive stream: decision, status, policy, attestation frames.