Daemon

The gateway and manifest pinning

One local MCP endpoint serves every plugged server and refuses any tool list that no longer matches its signed manifest.

How a session runs

Your agentClaude Code, Cursor, VS Code, Windsurf
tools/list
daemon mcplocal stdio gateway
every list
Hash checkkeccak256(JCS(tools))
match only
Publisher endpointGitHub, Supabase, house
The gateway hashes each server's tool list on every session and every tools/list, and compares it with the hash in the Servers contract.

The gateway proxies remote HTTP servers and local stdio servers alike. It reads the pinned manifest hash for each listing from the Servers contract, caches it for 60 seconds, and checks the live tool list against it before your agent sees anything.

The manifest hash

A manifest is the canonical tool list of a server: every tool's name, description and input schema, sorted by name, serialised with JCS (RFC 8785), then hashed with keccak256.

const tools = (await client.listTools()).tools
  .map(t => ({ name: t.name, description: t.description ?? "", inputSchema: t.inputSchema ?? {} }))
  .sort((a, b) => a.name < b.name ? -1 : 1);
const manifestHash = keccak256(toBytes(jcs(tools)));

The publisher kit at /sdk/publish.mjs exports this exact function, so a publisher can check a hash before signing it.

What a refusal looks like

If the hashes differ, the gateway drops that server for the session and tells the agent it is unavailable. The changed descriptions never reach the model. The keeper sees the same drift on its next probe (every 60 seconds) and flags the server, which puts 30% of the stake behind it at risk.

A publisher that wants to change its tools signs the new manifest first with publish(serverId, newHash). That is never a breach.

Secrets

Tokens such as GITHUB_TOKEN or SUPABASE_ACCESS_TOKEN stay in ~/.daemon/secrets (mode 600) and are sent only to the publisher's own endpoint. Daemon's servers never receive them.

The listing screen

Before the curator pins a manifest, it runs a published screen and refuses manifests that contain hidden Unicode, instructions to call other tools or read local files, or text aimed at the model inside a schema. A probe cannot judge intent, so the screen runs once at listing and drift detection covers every change after it.