An append-only record of every version of every MCP server's tool definitions that Glimind has observed — names, descriptions, schemas and annotations — organised as an RFC 6962 Merkle tree with Ed25519-signed tree heads. Anyone can check that a version was recorded (inclusion proof) and that history was never rewritten (consistency proof).
Signed tree head: root 74e9499842a0b96e6826ed11b8062800fb026b58d72521995f07fb436395fb48 at 2026-10-17T14:28:10.803Z (key glimind-dMIhngJmDctqNpqd, JWKS).
Hash the tool list your client received and ask the log whether it matches what the server currently advertises. A mismatch returns the exact tools that changed and a tool-poisoning scan of the new text.
// Pin and verify an MCP server's tool definitions (Node 18+, no dependencies).
import { createHash } from "node:crypto";
const stable = (v) => v === null || typeof v !== "object" ? JSON.stringify(v ?? null)
: Array.isArray(v) ? "[" + v.map(stable).join(",") + "]"
: "{" + Object.keys(v).filter((k) => v[k] !== undefined).sort().map((k) => JSON.stringify(k) + ":" + stable(v[k])).join(",") + "}";
export function manifestHash(tools) {
const c = tools.map((t) => ({ name: t.name, title: t.title ?? null, description: t.description ?? null,
inputSchema: t.inputSchema ?? null, outputSchema: t.outputSchema ?? null, annotations: t.annotations ?? null }))
.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
return createHash("sha256").update(stable(c)).digest("hex");
}
// tools = (await client.listTools()).tools
const res = await fetch("https://glimind.com/v1/manifest/verify", { method: "POST", headers: { "content-type": "application/json" },
body: JSON.stringify({ serverId: "<server id>", tools }) }).then((r) => r.json());
if (res.verdict !== "matches_current") throw new Error("Tool definitions changed: " + JSON.stringify(res.drift));
Agents can do the same over MCP with verify_tools({serverId, tools}). Records from before the log existed are labelled snapshot (seeded from the stored catalog on 2026-10-17); everything since is observed live.
GET https://glimind.com/v1/log/sth — signed tree headGET https://glimind.com/v1/manifest/<serverId> — current manifest + inclusion proof; /history for every version with diffsPOST https://glimind.com/v1/manifest/verify — {serverId?, tools}GET https://glimind.com/v1/log/proof?index=N, /v1/log/consistency?first=M&second=N, /v1/log/entries?start=I&end=J — RFC 9162 proofs and raw leaves for independent auditingAn append-only record of every version of every MCP server's tool definitions that Glimind has observed — names, descriptions, schemas and annotations — organised as an RFC 6962 Merkle tree with Ed25519-signed tree heads. Anyone can check that a version was recorded (inclusion proof) and that history was never rewritten (consistency proof).
Agents trust whatever a server's tools/list returns, and a server can change a description at any time — the way tool-poisoning and 'rug pull' attacks work. Pinning the manifest hash and verifying it against the log tells a client when the definitions it approved have changed.
No. Records come from the same handshake + tools/list liveness probe used for uptime; no tool is ever invoked.