Skip to main content
Glama
SAIHM-Admin

@saihm/mcp-server-pro

Official

SAIHM — memory for AI agents

Portable memory for AI agents. Your assistant remembers what matters — across sessions, across models, across vendors. Share a memory with someone else's agent, take it back, or erase it for good.

npm version license Star on GitHub Sponsor SAIHM Subscribe on YouTube Follow on X

Enjoyed them? Like the videos, subscribe to the SAIHM channel, and turn on notifications with the bell 🔔 to hear about new videos and updates.

Prefer to read? The SAIHM manual (PDF) is a decision-maker's guide to SAIHM and SHM.

AI assistants forget everything when the session ends. SAIHM gives yours a memory that doesn't — one that follows you to a different assistant, a different model, or a different company's product.

Encrypted at rest, by default. Every memory is encrypted on your own machine before it goes anywhere, and SAIHM stores only that ciphertext. Nobody else can read your memories — not the storage, not SAIHM. There is nothing to switch on.

Start free — one command

npx -y @saihm/mcp-server-pro free-join

No card and no wallet. You need a browser and a GitHub account once, for a quick sign-in that confirms you're a real person:

  1. The command creates your key on this machine and shows a link and a short code.

  2. Open the link, sign in to GitHub, enter the code and approve.

  3. The command finishes by itself and shows where your key is saved.

No GitHub account? Start at https://saihm.net/free instead: you sign in with Google, and the page gives you your new key. Save it to a file only you can read, and point SAIHM_MASTER_SECRET_FILE at that file in your client's settings below. Never paste the key itself into a settings file. Your key is ready, so skip "Join SAIHM": a join would make a second, different key.

Then add SAIHM to your AI client, restart it, and say "Recall my SAIHM memories." You're running.

Prefer not to touch a terminal? Add SAIHM to your client first, then say "Join SAIHM" to your assistant. It runs the same setup and gives you the same link and code to approve.

If a join is interrupted, join again on the same machine: it reuses the key it already created, so you keep the same identity. To cancel a join, stop it and don't enter the code; the code expires on its own. Keep the key file either way. Joining in detail.

Related MCP server: Hippocampus

Add SAIHM to your AI client

The configurations below for Claude Code, Gemini CLI and the OpenAI Agents SDK are presented as tested (which clients are checked); the others are documented from each vendor's own documentation. Every configuration is subject to change at the vendor's discretion.

SAIHM runs on your machine as a local MCP server that your AI client starts with npx, so you need Node.js 20 or later. The package is @saihm/mcp-server-pro on npm, and the official MCP Registry lists it as io.github.SAIHM-Admin/saihm-mcp-server-pro.

Find your client below, add its block, and restart the client. Three tips:

  • Keep the file valid. A trailing comma, or a non-breaking space copied from an email or a web page, makes a JSON settings file invalid. Paste through a plain-text editor.

  • Keep the start-up setting. The first start downloads the package. Where a block sets a longer start-up time, keep it, so the tools appear on the first try.

  • Download it once first. Run npx -y @saihm/mcp-server-pro --version in a terminal. It downloads the package, prints its version and exits, so the client's first start is quick.

Each block follows that client's own documentation. Before every release, the server is started from these blocks in Claude Code, Gemini CLI and the OpenAI Agents SDK to confirm it connects. Each client's fine print is in the reference.

Claude Code (Anthropic)

One command adds SAIHM for all your projects:

claude mcp add --env SAIHM_ENDPOINT_URL=https://saihm.net/mcp --transport stdio --scope user saihm -- npx -y @saihm/mcp-server-pro

If the tools don't appear after the first start, give the server more time: MCP_TIMEOUT=60000 claude, or run npx -y @saihm/mcp-server-pro --version once in a terminal and start Claude Code again. claude mcp list shows whether it connected. For Claude Code on the web, see Hosted agent environments.

Claude Desktop (Anthropic)

Open Settings > Developer > Edit Config, add the "saihm" entry inside mcpServers, then quit and reopen Claude Desktop:

{
  "mcpServers": {
    "saihm": {
      "command": "npx",
      "args": ["-y", "@saihm/mcp-server-pro"],
      "env": { "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp" }
    }
  }
}

Claude Desktop starts the server with the Node.js installed on your machine, so install Node.js first. If the tools don't appear the first time, run npx -y @saihm/mcp-server-pro --version in a terminal, then quit and reopen Claude Desktop.

Codex CLI (OpenAI)

Add this to ~/.codex/config.toml, or to a project's .codex/config.toml:

[mcp_servers.saihm]
command = "npx"
args = ["-y", "@saihm/mcp-server-pro"]
env = { SAIHM_ENDPOINT_URL = "https://saihm.net/mcp" }
startup_timeout_sec = 60

Check it with codex mcp list, or /mcp inside Codex.

OpenAI Agents SDK (Python)

import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStdio

async def main():
    async with MCPServerStdio(
        name="saihm",
        params={
            "command": "npx",
            "args": ["-y", "@saihm/mcp-server-pro"],
            "env": {"SAIHM_ENDPOINT_URL": "https://saihm.net/mcp"},
        },
        client_session_timeout_seconds=60,
    ) as saihm:
        agent = Agent(name="Assistant", mcp_servers=[saihm])
        result = await Runner.run(agent, "Recall my SAIHM memories.")
        print(result.final_output)

asyncio.run(main())

The 60-second timeout gives the first npx download time to finish. Pass secrets from the environment, never as literals in your code.

Gemini CLI (Google)

Add this to ~/.gemini/settings.json (all projects) or .gemini/settings.json (one project):

{
  "mcpServers": {
    "saihm": {
      "command": "npx",
      "args": ["-y", "@saihm/mcp-server-pro"],
      "env": { "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp" }
    }
  }
}

Or install the Gemini CLI extension, which carries the same entry: gemini extensions install https://github.com/SAIHM-Admin/saihm-mcp-server-pro.

Run Gemini CLI in a folder you trust, since it starts local servers only there. Check with gemini mcp list, or /mcp inside Gemini CLI.

Since 2026-06-18, Google no longer serves personal Google accounts in the Gemini CLI: signing in with one answers "This client is no longer supported for Gemini Code Assist for individuals". As of October 2026 the Gemini CLI still works with a Gemini API key, or with a Gemini Code Assist Standard or Enterprise licence.

Antigravity CLI (Google)

Add this to ~/.gemini/config/mcp_config.json (all projects) or .agents/mcp_config.json in a project:

{
  "mcpServers": {
    "saihm": {
      "command": "npx",
      "args": ["-y", "@saihm/mcp-server-pro"],
      "env": { "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp" }
    }
  }
}

Type /mcp inside Antigravity CLI to see whether it connected. If the tools don't appear the first time, run npx -y @saihm/mcp-server-pro --version in a terminal, then reload the server there.

Grok Build (xAI)

Add this to ~/.grok/config.toml, or to a project's .grok/config.toml:

[mcp_servers.saihm]
command = "npx"
args = ["-y", "@saihm/mcp-server-pro"]
env = { SAIHM_ENDPOINT_URL = "https://saihm.net/mcp" }
startup_timeout_sec = 60

Grok Build also picks up an existing saihm entry from ~/.claude.json or a project's .mcp.json, so if you already added it for another client you may not need this step. Check it with grok mcp list, or grok mcp doctor saihm.

GitHub Copilot in VS Code (Microsoft)

Add this to .vscode/mcp.json in a workspace, or to your user mcp.json (run MCP: Open User Configuration). VS Code uses servers here, not mcpServers:

{
  "servers": {
    "saihm": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@saihm/mcp-server-pro"],
      "env": { "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp" }
    }
  }
}

Or add it to your user profile from a terminal (bash, zsh or Command Prompt):

code --add-mcp "{\"name\":\"saihm\",\"command\":\"npx\",\"args\":[\"-y\",\"@saihm/mcp-server-pro\"],\"env\":{\"SAIHM_ENDPOINT_URL\":\"https://saihm.net/mcp\"}}"

MCP: List Servers shows the server, and its Show Output action shows the log. If the tools don't appear the first time, run npx -y @saihm/mcp-server-pro --version in a terminal, then restart the server from MCP: List Servers. For the GitHub Copilot cloud agent, see Hosted agent environments.

Other MCP clients

For clients that run local MCP servers from an mcpServers block, such as Cline, Cursor or Windsurf, add the "saihm" entry inside the existing mcpServers object:

{
  "mcpServers": {
    "saihm": {
      "command": "npx",
      "args": ["-y", "@saihm/mcp-server-pro"],
      "env": { "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp" },
      "timeout": 60
    }
  }
}

timeout is in seconds in Cline. If your client documents another unit, follow its documentation.

If the tools don't appear the first time, run npx -y @saihm/mcp-server-pro --version in a terminal. It downloads the package, prints its version and exits. Then restart Cline.

Agent frameworks

Building agents in Python? The same encrypted memory plugs into the major frameworks. Each adapter needs Node.js 20 or later, like this server, and encrypts inside your process, so Python never holds a key.

Framework

What you get

Install

LangGraph

A long-term memory store for your graph

pip install saihm-langgraph (repository)

CrewAI

One memory your whole crew shares

pip install saihm-crewai (repository)

LangChain

Chat history you own

pip install "saihm-adapters[langchain]"

LlamaIndex

Chat memory, and a retriever for RAG

pip install "saihm-adapters[llamaindex]" and [rag]

AutoGen

A memory your agent owns

pip install "saihm-adapters[autogen]"

saihm-adapters brings them all together, with live demos.

Things to say

You don't call tools by name — you talk to your assistant. Some starters:

Liberally use SAIHM protocol to maximize token economy.

Recall my SAIHM memories before you start.

Remember that I prefer short answers and no preamble.

Set an invariant to doubly confirm before any SAIHM forget action.

Share that note with my colleague's agent until 5:00 pm today.

How much of my SAIHM allowance is left?

Forget everything I told you about the Henderson account.

Tool

What it does

saihm_remember

Encrypts on your machine, then stores it

saihm_recall

Fetches and decrypts on your machine

saihm_forget

Permanently erases. No undo

saihm_status

Your usage and settings

saihm_share

Grants one memory to one agent, optionally with an expiry

saihm_revoke_share

Withdraws that grant

Every tool is labelled for your AI tool to read, including which are read-only and which one destroys data — so hosts that ask "are you sure?" before destructive actions know when to ask. The reference has the full tool list.

"Forget" really means forget. The key to that memory is destroyed, so the stored copy becomes permanently unreadable — by you, by SAIHM, by anyone holding a backup of it. This is how SAIHM answers a GDPR Article 17 erasure request, and it is why there is no undo. The answer confirms the erasure once the service's record of the key's destruction comes back with it.

Your memories follow your key

Your memory belongs to your key, not to a computer — that's what makes it portable. The key is created on your machine and never sent anywhere, which is exactly why nobody else can read your memories. Keep a copy of the key file somewhere safe: SAIHM cannot make you another one. Setup shows where the file is, and upgrading to a paid plan keeps the same key and every memory.

Using a second computer, or a hosted agent? Three ways:

  • Same memory, anywhere — on the machine that has your key, run:

    npx -y @saihm/mcp-server-pro export-identity

    It saves two values to a file only you can read: SAIHM_IDENTITY (your key, sealed) and SAIHM_IDENTITY_PASSPHRASE (the passphrase that opens it). Set both as environment variables or secrets wherever the memory should follow you, then start a new session. Don't say "Join SAIHM" there: a join starts a new, empty memory. Together the two values are your identity: keep them in a password manager, never in a chat or a repository, and delete the export file. On a paid plan, see exporting your identity first.

  • Copy the key file — put it at ~/.saihm/free-identity.key on the other machine (or point SAIHM_MASTER_SECRET_FILE at it) before the server starts, use the same settings as the first machine (on a paid plan, SAIHM_TIER and SAIHM_PAYMENT_METHOD too), and say "Recall my SAIHM memories."

  • Keep work and personal apart — start fresh on the second machine and share across instead: "Share these notes with my work agent until 5:00 pm." A share can be revoked or given an expiry, so the two stay separate.

Hosted agent environments

A hosted agent session usually starts on a fresh machine and discards its home directory when it ends, so a key created there would be lost with it. Bring your identity in instead: set the two export-identity values in the environment's own settings — never in the chat — and start a new session, because the environment reads its variables when a session starts. The server runs locally in the session and needs to reach saihm.net, and npm for npx. The steps below follow each host's own documentation; the reference covers proxies and the finer points.

  • Claude Code on the web — add both values under the environment's Environment variables. Anyone who uses that environment can read them, so use a dedicated environment that only you use, for repositories you trust. Choose Custom network access, add saihm.net, and check Also include default list of common package managers, so npx can still reach npm. Then pass the values through the repository's .mcp.json:

    {
      "mcpServers": {
        "saihm": {
          "command": "npx",
          "args": ["-y", "@saihm/mcp-server-pro"],
          "env": {
            "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp",
            "SAIHM_IDENTITY": "${SAIHM_IDENTITY:-}",
            "SAIHM_IDENTITY_PASSPHRASE": "${SAIHM_IDENTITY_PASSPHRASE:-}",
            "SAIHM_TIER": "${SAIHM_TIER:-}",
            "SAIHM_PAYMENT_METHOD": "${SAIHM_PAYMENT_METHOD:-}",
            "CLAUDE_CODE_REMOTE": "${CLAUDE_CODE_REMOTE:-}"
          }
        }
      }
    }

    The same file still works on your own machine. Never add SAIHM_MASTER_SECRET_FILE or SAIHM_MASTER_SECRET_HEX to it: either would commit your key or clash with the identity. If the tools don't appear, run claude mcp list in the session, and set MCP_TIMEOUT=60000 in the environment variables to give the server longer to start.

  • GitHub Copilot cloud agent — store the values as Agents secrets (repository Settings → Secrets and variables → Agents) named COPILOT_MCP_SAIHM_IDENTITY and COPILOT_MCP_SAIHM_IDENTITY_PASSPHRASE. The server runs beside every command the agent runs, so use this only in a repository whose code you trust. Map the secrets in the repository's MCP configuration (Settings → Copilot → MCP servers):

    {
      "mcpServers": {
        "saihm": {
          "type": "local",
          "command": "npx",
          "args": ["-y", "@saihm/mcp-server-pro"],
          "tools": ["saihm_recall", "saihm_remember", "saihm_status"],
          "env": {
            "SAIHM_ENDPOINT_URL": "https://saihm.net/mcp",
            "SAIHM_IDENTITY": "$COPILOT_MCP_SAIHM_IDENTITY",
            "SAIHM_IDENTITY_PASSPHRASE": "$COPILOT_MCP_SAIHM_IDENTITY_PASSPHRASE",
            "SAIHM_EPHEMERAL_HOME": "1"
          }
        }
      }
    }

    Copilot runs the listed tools without asking, so this list leaves out saihm_forget and the sharing tools. By default, Copilot code review can call the read-only tools on any pull request, so your memories could reach review comments: unless you want that, turn off Allow Copilot to use MCP tools when reviewing pull requests.

  • Elsewhere — this should work on any host that runs local MCP servers, lets the server read both values, and lets it reach saihm.net and registry.npmjs.org. Put the values in the host's own secrets or environment settings, scoped to you alone, in an environment only you use: the agent, and every command it runs, may be able to read them. Add SAIHM_EPHEMERAL_HOME=1 there if its home directory does not persist. Hosts that only connect to remote MCP servers cannot run this package.

Where it can tell that the home directory is temporary, a join refuses to create a key that would be lost with it.

See it run

  • Live demos across every major model — offline, about a minute each, no account: https://saihm-admin.github.io/saihm-demos/. Store a memory in Claude, GPT, DeepSeek, Qwen, Kimi, or GLM, then prove you can erase it.

  • Token benchmark — recalling a bounded set of memories instead of re-sending the whole conversation cut input tokens by 62.8%–85.9% across a realistic multi-session task. Open, offline, reproducible: https://github.com/SAIHM-Admin/saihm-token-benchmark.

What it costs

Start free. The free tier is a fixed, one-time allowance of writes, reads, and shares for trying SAIHM on real infrastructure — it doesn't reset or refill. No card, and nothing to cancel. Your assistant shows what's left and warns you as it runs low, so nothing fails by surprise.

Paid plans are monthly; prices are on the pricing page. Upgrading keeps the same key and every memory you already have:

SAIHM_MASTER_SECRET_FILE=$HOME/.saihm/free-identity.key \
SAIHM_TIER=FREE \
  npx -y @saihm/mcp-server-pro upgrade PRO

That prints a checkout link tied to your identity. Pay, then add two lines to your config's env block and restart:

"SAIHM_TIER": "PRO",
"SAIHM_PAYMENT_METHOD": "stripe"

A paid plan needs both lines: without SAIHM_PAYMENT_METHOD, which names the payment rail to check, the server won't start. The upgrade command's link is card checkout, and goes with stripe. It keeps your key and every memory on it. Stablecoin is paid on the website's join page and goes with stablecoin. Paying there starts a new identity with its own key. The memories on a key you already have stay on that key and do not move to the new one, so to upgrade the key you have, use the card link.

If something isn't working

What you see

What to do

No SAIHM tools appear, and no error anywhere

The client stopped waiting before npx finished its first download. Keep the start-up setting in your client's block, and check that the file is valid JSON

Every other tool vanished too

The settings file is no longer valid JSON: look for a trailing comma, or non-breaking spaces from a copy and paste

The memory tools say the join is waiting for approval

Open the link the join gave, sign in, enter the code and approve. The join then finishes by itself, and the next memory call works

Tools appear but every call fails

The machine cannot reach the endpoint (saihm.net, unless you set another). In a hosted environment, allow it in the network settings

A hosted session keeps asking to join

The environment has no identity of yours: see Hosted agent environments

A different memory than you expected

This machine has its own key rather than yours

Proxies, erasure answers and everything else are in the full troubleshooting table.

How it works

Everything is encrypted on your machine before it is sent, and decrypted on your machine after it comes back. What SAIHM stores is unreadable ciphertext, and no key that opens it. To erase something, its key is destroyed — which is why erasure is immediate and final rather than a promise that a copy was deleted somewhere.

  • Post-quantum by design. ML-DSA-65 signs every memory, and ML-KEM-768 protects sharing.

  • Non-custodial. The hosted service at https://saihm.net provides the durable storage, yet only ever holds ciphertext and never a key.

  • Erasure that travels. Each forget also writes a notice, so anything built from that memory — an index, a mirror, an extracted fact — can drop it too.

  • Fast recall on your device. With the standard setup, this client keeps a local copy of the memories you have already opened, so a recall fetches only what is new. That copy is not encrypted, only your user account can read it, and forget removes a memory from it too.

  • Everything encrypted at rest, if you prefer. Set SAIHM_RECALL_CACHE=0 and this client keeps no local copy, so every memory SAIHM holds at rest is ciphertext. The trade-off is speed: each recall then fetches all your memories again.

The technical reference has the security model, where the encrypted memories are stored, and every setting.

Configuration

Most people need none: the blocks above set the one setting that matters, and the rest have working defaults. Every setting is listed in the reference.

For developers

Use SAIHM from your own Node.js code. The developer reference covers identity records, following shares, changes to your own cells, warm start, structured tool results and errors.

npm install @saihm/mcp-server-pro
import { SaihmProClient } from '@saihm/mcp-server-pro';

// Boot from env: SAIHM_ENDPOINT_URL, SAIHM_MASTER_SECRET_FILE (or _HEX)
//   self-onboard (recommended): + SAIHM_PAYMENT_METHOD + SAIHM_TIER (omit SAIHM_AUTH_HEADER)
//   static token (advanced):    + SAIHM_AUTH_HEADER="Bearer <JWT>"
const saihm = SaihmProClient.bootFromEnv();

// Store — encrypted before it leaves the process.
const { cellId } = await saihm.remember('remember this');

// Recall — decrypted after it returns.
const cell = await saihm.recallOne(cellId);
console.log(cell?.plaintext); // 'remember this'

// Recall everything (client-side keyword filter; the endpoint has no plaintext to filter on).
const matches = await saihm.recall('this');

// Update an existing cell (a fresh monotonic sequence is issued automatically). When the endpoint reports
// shares of the cell left on the previous version, `shares` in the result reports their re-issue.
await saihm.remember('new contents', { cellId });

// Forget — crypto-shred.
await saihm.forget(cellId);

// Share a cell with another agent, end-to-end authenticated. Pin the grantee's agentIdHash
// out-of-band; the library rejects directory key-substitution.
await saihm.share({
  cellId,
  recipientRecord, // the grantee's published identity record (hex)
  recipientPinnedAgentIdHashHex, // pinned out-of-band
  expiryEpoch, // optional whole HOURS since the UNIX epoch (498192n = 2026-11-01 00:00 UTC); omit or null for no time bound
});
await saihm.revokeShare(cellId, recipientPinnedAgentIdHashHex);

// Read a cell another agent shared TO you (the recipient side of `share`). Pin the
// sharer's agentIdHash out-of-band; the library verifies the sharer's signature and
// returns null when there is no live grant (e.g. revoked, or the sharer crypto-shredded it).
const shared = await saihm.recallShared({
  sharerPinnedAgentIdHashHex, // the sharer's agentIdHash, pinned out-of-band
  sharerRecord, // the sharer's published identity record (hex)
  cellId,
});
console.log(shared?.plaintext);

// Operator-observable metadata only (no plaintext).
const status = await saihm.status();

SHM — Super-Human Memory

SAIHM keeps memory safe. SHM, Super-Human Memory, makes it work efficiently: it is the layer on top of SAIHM that organises memory and brings the right part of it forward, by meaning, before the agent asks. It keeps tasks apart and the context window clean, so one agent can take on work that today needs several, and a mistake corrected once stays corrected.

SHM runs on your side, next to your agent, over the memories your agent can read, so none of this requires your plaintext to leave home. It ranks them with hybrid retrieval and an optional local reranker, brings forward only what the current task needs, within a budget you set, and keeps what it stores encrypted under a key you hold. When a memory is erased in SAIHM, SHM removes it from its index, its caches and everything it derived from it.

npm install @saihm/shm

SHM needs Node.js 20.20 or later.

How SHM and this client fit together. SHM works through this MCP server, version 0.13.0 or later, which keeps SHM in step with your SAIHM memory:

  • The change feed tells SHM which of your memories were written, so SHM reads them again.

  • The erasure feed tells SHM which memories were erased, so SHM removes them and everything it derived from them.

  • Share states tell SHM which memories other agents have shared with you, and which of those shares have ended.

  • Structured tool results give SHM each answer in a form it checks before acting on it.

  • Warm start lets SHM save an encrypted snapshot of its state and pick up where it left off in a new session or on another device.

The reference lists the tools and files SHM uses.

The SAIHM manual covers both: chapter 4 for what SHM adds, chapter 5 for its levers and recipes, and chapter 9 for why to choose SAIHM and SHM together.

Support SAIHM

If SAIHM is useful to you, here is how to help it reach more people:

  • Star it on GitHub. Stars help other developers find SAIHM.

  • Share it with a colleague, your team, or anyone whose assistant keeps forgetting.

  • Follow @SAIHMemory on X for news and updates.

  • Sponsor it through GitHub Sponsors, monthly or one-time.

  • Follow along on YouTube: like the videos, subscribe to the channel, and turn on notifications with the bell 🔔 for new videos and updates.

Discount codes

Upgrading? Run the upgrade command in What it costs, then enter one of these codes in the promotion-code box at checkout:

Code

Offer

SAIHM-90-OFF

90% off your first payment, for new customers

SAIHM-75-OFF

75% off your first payment

SAIHM-50-OFF

50% off for four months

SAIHM-25-OFF

25% off for six months

One code per checkout, while the offers last.

License

Apache-2.0 © SAIHM

Available Tools

9 tools
saihm_forgetForget (GDPR erasure)A
DestructiveIdempotent

Cryptographically erase one memory by its cell id (GDPR Art. 17). Destroying the wrapped key leaves the content unreadable to everyone, the operator included. Irreversible: use it when erasure is the intent, not to tidy a working set. With warmStart "delete", it instead destroys one encrypted warm-start snapshot, its key first.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoMemory cell id (hex) to erase. Required unless warmStart is "delete".
tokenNoWith warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. Blank otherwise.
warmStartNo"delete" destroys the snapshot named by snapshotId instead of a memory. Only snapshotId and token go with it. Leave it blank to erase a memory by id.
snapshotIdNoWith warmStart "delete": the snapshot to destroy. Blank otherwise.

Output Schema

ParametersJSON Schema
NameRequiredDescription
atNo
epochNo
errorNo
reasonNo
timingNo
deletedNo
completeNo
sharesPurgedNo
destructionAnchorNo

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds real value beyond them: the mechanism (destroying the wrapped key) and the consequence (unreadable to everyone, operator included). That is exactly the kind of context an agent needs before an irreversible call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences with the destructive intent and irreversibility front-loaded before the mode variant. Slight redundancy with the schema on the warmStart branch and the trailing "its key first" is a touch cryptic, keeping it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and annotations carry the safety profile. The description covers mechanism, consequence, reversibility, and the dual memory/snapshot mode, leaving nothing an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, and the schema already documents the warmStart="delete" branch, id format, and token pattern in more detail than the description. The description restates the mode switch but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("cryptographically erase one memory by its cell id") with the GDPR framing that pins the intent. An agent can distinguish it from siblings like saihm_revoke_share or saihm_remember without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use and when-not ("use it when erasure is the intent, not to tidy a working set"), plus a clear branch for the snapshot mode. It does not name a concrete alternative tool for unsharing/tidying, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_governance_proposePropose (governance)A

Open a protocol governance proposal: set scope to 'emission_param' or 'protocol_upgrade', and for 'emission_param' also pass paramKey and proposedValue. Protocol governance is not enabled for this client yet — the tool is present so the surface stays stable, and calling it returns a 'governance unavailable' error rather than opening a vote.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeYesGovernable scope
paramKeyNoParameter key (when scope=emission_param)
proposedValueNoProposed value as string

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate it is not read-only (readOnlyHint=false), but the description adds crucial behavior: the tool is a stub and will return a 'governance unavailable' error. This goes beyond the annotations and sets correct expectations for the agent's action. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences front-load the main purpose and conditional parameters, then immediately note the limitation. No wasted words, and the critical caveat is placed at the end without obscuring the primary intent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's conditional parameters and non-functional status, the description covers every piece an agent needs: which scope is required, what extra parameters are needed for each scope, and the exact failure behavior. It is complete and self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and paramKey's schema description already mentions 'when scope=emission_param'. However, the description also clarifies that proposedValue is also conditional on emission_param, which the schema does not explicitly state. This adds meaningful conditional logic beyond what is in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('open') and a clear resource ('protocol governance proposal'), and distinguishes its function from the sibling vote tool. It explicitly states the two scopes and the conditional parameters, and even clarifies the current non-functional state, so an agent knows exactly what the tool is meant to do.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit instructions: set scope to 'emission_param' or 'protocol_upgrade' and, for 'emission_param', also pass paramKey and proposedValue. It also explicitly warns the tool is not enabled and will return an error, effectively telling the agent not to rely on it. This is clear and complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_governance_voteVote (governance)A

Cast a vote on an open protocol governance proposal by its proposalId, with approve set to true to approve or false to reject. Protocol governance is not enabled for this client yet — the tool is present so the surface stays stable, and calling it returns a 'governance unavailable' error rather than recording a vote.

ParametersJSON Schema
NameRequiredDescriptionDefault
approveYestrue = approve, false = reject
proposalIdYesHex proposalId

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses a critical behavioral trait beyond annotations: despite appearing write-oriented, the tool is stubbed and returns a 'governance unavailable' error without recording a vote. This adds important context beyond the readOnly/idempotent/destructive hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no fluff. The primary action is stated first, and the critical unavailable-error behavior is front-loaded in the second sentence before any unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with full schema coverage, the description fully covers invocation, parameter semantics, and the actual behavioral outcome. No output schema exists, but the description explicitly discloses the error response, so nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, with both proposalId and approve documented. The description restates the approve true/false semantics and ties the action to proposalId, but adds little beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: cast a vote on an open protocol governance proposal by proposalId. It clearly differentiates the voting action from the sibling propose tool and explains the approve semantics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly indicates that casting a vote is the intended action and that governance is not enabled, so calling the tool will return an error rather than succeed. It does not explicitly name alternatives, but the purpose and current non-functional status make appropriate usage unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_joinJoin SAIHM (activate free memory)A

Activate free SAIHM persistent memory for this agent. Call this when the user asks to join, sign up for, or set up SAIHM. Where no identity is configured, a join creates a NEW, EMPTY memory: first ask whether they already have a SAIHM identity (from another machine or an earlier session) - if so, do not join; they bring it with export-identity instead. In a hosted or cloud session that starts fresh each time, do not join there either: they join on a machine they keep, then bring that identity in the same way. Pass newIdentity: true once they confirm they want a new one here. It self-generates a sovereign memory key on this device and starts a one-time human approval — the tool returns a URL and short code for the user to open and enter. After the user approves, the join finishes by itself and the memory tools work; there is no need to call saihm_join again. No payment.

ParametersJSON Schema
NameRequiredDescriptionDefault
newIdentityNotrue once the user confirms they have no SAIHM identity to bring here and want a new, empty memory

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the mutation/idempotency/open-world profile; the description adds substantive behavior: it self-generates a sovereign memory key on-device, triggers a one-time human approval returning a URL and short code, completes asynchronously without a second call, and involves no payment. This is exactly the extra context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then branches into the two do-not-join cases and the approval mechanics. Well organized, though 'the join finishes by itself' and 'there is no need to call saihm_join again' are mildly redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description covers the return value (URL plus short code), the post-approval state (memory tools work), and the no-payment guarantee. An agent has everything needed to call this correctly and to tell the user what to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single parameter's schema description already spells out the confirmation precondition. The description's 'Pass newIdentity: true once they confirm' restates rather than extends the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Activate free SAIHM persistent memory for this agent.' It is immediately distinguishable from siblings like saihm_remember, saihm_recall, and saihm_status, which operate on an existing memory rather than creating one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('when the user asks to join, sign up for, or set up SAIHM') and explicit when-not-to-use with alternatives: ask about an existing identity first and route to export-identity, and do not join in fresh hosted/cloud sessions. This is unusually complete routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_recallRecallA
Read-onlyIdempotent

Retrieve your memories from SAIHM and decrypt them in this process; the server never sees plaintext. Use this at the start of a session, or whenever past context is needed. Pass query to filter by keyword, or leave it out to load everything. Pass cellId alone to read one of your own cells. To read a single cell another agent shared with you, pass their sharerPinnedAgentIdHashHex and sharerRecord together with the cellId; that path is read-only. Pass listOnly to list your cells' versions without their content. Pass sharesOnly to list every pointer shared with you, a page at a time, where the endpoint offers it. With warmStart "latest", it instead restores the newest encrypted warm-start snapshot into the payload file named by token; "list" lists them.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoWith listOnly or sharesOnly: the next value of the previous page.
queryNoFilter your OWN memories by keyword (empty = all). Ignored when reading one cell by cellId.
tokenNoWith warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file. Blank otherwise.
cellIdNoThe cell id to read: alone, one of your own cells; with the sharer fields, the shared cell (required then).
listOnlyNoList your own cells' versions (cellId, seq, commitment) without reading any content. Pages: pass the answer's next as after until next is null.
warmStartNo"latest" restores the newest snapshot into warm-start/latest-<token>.bin (read it, then remove it); "list" lists snapshots. Only token goes with it. Leave it blank to recall memories.
sharesOnlyNoList every pointer shared with you, a page at a time and never cut, without reading any memory. Pages: pass the answer's next as after until next is null. Answers shares_paging_unsupported where the endpoint does not offer it: then recall without it.
shareEntriesNoWith the share events feed on, also return every entry of the share map; without it, only its summary.
sharerRecordNoThe SHARER's published identity record (hex fields). Required with sharerPinnedAgentIdHashHex.
sharerPinnedAgentIdHashHexNoRead a cell shared TO you: the SHARER's agentIdHash (hex), pinned out-of-band. When set, sharerRecord and cellId are also required.

Output Schema

ParametersJSON Schema
NameRequiredDescription
asOfNo
nextNo
cellsNo
countNo
errorNo
foundNo
totalNo
sharedNo
timingNo
memoriesNo
servedByNo
snapshotNo
snapshotsNo
sharedKeptNo
shareStatesNo
sharedSkippedNo
sharedTruncatedNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/non-destructive, yet the description adds real behavioral content: decryption happens client-side and the server never sees plaintext, the shared-cell path is read-only, warmStart writes a snapshot file that must be read then removed, and sharesOnly returns shares_paging_unsupported on unsupported endpoints. These are side effects and failure modes annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and safe-decryption guarantee, then one sentence per mode, so every sentence earns its place across eight branching behaviors. The warmStart sentence is dense and mixes two modes into one clause, which slightly hurts readability for an otherwise well-structured block.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and annotations carry the safety profile. Given ten optional parameters and a nested sharer record, the description still covers the mutually exclusive modes, the required-argument trios, pagination via after/next, and one error case, leaving nothing an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description exceeds it by explaining parameter interplay rather than restating fields — query is ignored when reading by cellId, and sharerPinnedAgentIdHashHex/sharerRecord/cellId form one required trio. It does not, however, add format or value-level detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (retrieve and locally decrypt your memories) and enumerates the distinct read modes it supports. It is clearly the read path in a family containing saihm_remember, saihm_forget and saihm_share, but it never names a sibling, so the differentiation is implicit rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use framing ('at the start of a session, or whenever past context is needed') and then routes on argument combinations: query to filter vs omit to load all, cellId alone vs with sharer fields, listOnly, sharesOnly, and warmStart latest/list. Each branch is tied to a condition, which is exactly the guidance an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_rememberRememberA

Store information in SAIHM persistent memory. Encryption happens in this process and the key never leaves it, so the server holds ciphertext it cannot read. Use this when a fact, decision, or piece of context should outlive the current session. Pass an existing cellId to update that cell instead of adding a new one; when the endpoint reports that the update left shares of the cell on the previous version, they are re-issued for the new version and the result counts them, and a share that was not re-issued needs saihm_share again. Returns the cell id that saihm_forget takes. With warmStart "put", it instead stores an encrypted warm-start snapshot of the payload file named by token.

ParametersJSON Schema
NameRequiredDescriptionDefault
tokenNoWith warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file. Blank otherwise.
cellIdNoExisting cell id (hex) to update; omit to create a new cell
contentNoInformation to remember. Required unless warmStart is "put".
warmStartNo"put" stores the payload file warm-start/put-<token>.bin as an encrypted snapshot, then removes the file. Only coversThrough and token go with it. Leave it blank to remember content.
coversThroughNoWith warmStart "put": the change feed position the payload covers, the cursor of a position marker. Blank otherwise.

Output Schema

ParametersJSON Schema
NameRequiredDescription
atNo
seqNo
bytesNo
errorNo
cellIdNo
timingNo
shardIdNo
createdAtNo
commitmentNo
snapshotIdNo
coversThroughNo
commitmentHashNoDeprecated: the same value as commitment, kept for existing readers.
sharesReissuedNo
sharesIncompleteNo
sharesNotReissuedNo

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write/openWorld/non-idempotent, and the description adds substantial context on top: the encryption model (key never leaves the process, server holds unreadable ciphertext), the share re-issue side effect on updates, and the warmStart snapshot behavior including file removal. This is genuinely useful behavioral disclosure beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is correctly front-loaded, but the share re-issue clause is a dense run-on ('...they are re-issued for the new version and the result counts them, and a share that was not re-issued needs saihm_share again') that is hard to parse. The warmStart branch is tacked onto the end, making the single paragraph feel overloaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter tool with two operating modes (content store vs warmStart snapshot), the description covers both modes, the encryption guarantee, and cross-references saihm_forget/saihm_share. With an output schema present it need not detail return values, and it is largely complete, though the update/share interaction remains the least clear part.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it explains that cellId switches to update mode, that warmStart 'put' consumes token/coversThrough and stores a snapshot, and how shares interact with updates. It adds value over the schema rather than merely restating it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('Store information in SAIHM persistent memory') and clarifies the create-vs-update mode via cellId, distinguishing it from the read sibling (saihm_recall) and the delete sibling (saihm_forget). It never explicitly names saihm_recall as the read counterpart, so full sibling differentiation is implied rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this when a fact, decision, or piece of context should outlive the current session' gives a clear triggering condition, and it names saihm_share as the follow-up when a share is not re-issued. It lacks an explicit when-not statement (e.g., prefer saihm_recall to read), leaving one inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_revoke_shareRevoke shareA
Idempotent

Withdraw a grant made with saihm_share, naming the same cellId and the recipient's recipientHex. It applies to future reads and cannot retract what the recipient has already read. Use it to end access; the memory itself remains, and saihm_forget is what erases.

ParametersJSON Schema
NameRequiredDescriptionDefault
cellIdYesThe shared cell id
recipientHexYesThe grantee's agentIdHash (hex) to revoke

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description adds the critical limitation 'It applies to future reads and cannot retract what the recipient has already read' and clarifies that the memory itself survives. These details meaningfully shape an agent's expectations about side effects and are not present in the schema or annotations. There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero filler: the first states the operation, the second discloses the main behavioral caveat, and the third gives the usage alternative. The key action is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema and no nested objects, this description covers the operation, the exact parameter relationship, the temporal limitation, and the sibling tool to use instead. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds relational meaning by instructing the caller to reuse the same cellId and recipientHex from the original saihm_share call, which is not explicitly stated in the schema descriptions. This small but valuable addition justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Withdraw a grant made with saihm_share'. It clearly differentiates itself from saihm_forget by noting 'the memory itself remains, and saihm_forget is what erases', so an agent can distinguish revoking access from erasing memory without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit when-to-use instruction: 'Use it to end access'. It also names the alternative saihm_forget and the condition for erasure, and it tells the agent to name 'the same cellId and the recipient's recipientHex', tying usage to the original grant.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_shareShareA

Grant one other agent access to a single memory cell, named by cellId. Identify the recipient by their recipientPinnedAgentIdHashHex, pinned out-of-band, and their recipientRecord. Set scope to 'read', 'write' or 'readwrite'. Only that one cell is exposed, and sharing re-wraps its key rather than copying the memory.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeNoAccess scope (blank = read)
cellIdYesThe cell to share
expiryEpochNoOptional expiry in whole HOURS since the UNIX epoch (decimal string), not seconds: floor(unix_ms / 3600000). Example: "498192" is 2026-11-01 00:00 UTC. Blank = no expiry
recipientRecordYesThe grantee's published identity record (hex fields)
recipientPinnedAgentIdHashHexYesThe grantee's agentIdHash (hex), pinned out-of-band

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-read-only, non-idempotent, open-world, non-destructive. The description adds genuinely non-obvious behavior beyond that: sharing re-wraps the cell key rather than copying the memory, and exposure is limited to exactly one cell. It does not explain why the operation is non-idempotent or what happens on repeat shares, so it is not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the action and target, then recipient identification, then scope, then the exposure/key-wrap caveat. Every sentence carries distinct information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with a nested recipient object and no output schema, the description covers the security model and exposure limits well. It omits success/failure behavior, permission requirements on the caller, and any mention of expiryEpoch, which the schema carries but the narrative does not.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents every parameter including the tricky expiryEpoch hour-encoding. The description restates cellId, the scope values, and the out-of-band pinning requirement, adding intent but little syntax or format detail beyond the schema; expiryEpoch is not mentioned at all. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (grant access) plus specific resource (a single memory cell named by cellId), with the granting counterpart to sibling saihm_revoke_share implicit in the wording. The scope guarantee ('Only that one cell is exposed') further sharpens what the tool is and is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: you call it when you want to give one other agent access to one cell, and the recipient must already be pinned out-of-band. But no explicit when-to-use/when-not and no sibling is named as an alternative or complement, leaving routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

saihm_statusStatusA
Read-onlyIdempotent

Show the current SAIHM session: the agent identity, which this client derives locally, plus the tier, custody mode, shard and sharing counts, and bfsi score the server reports. No plaintext appears, because the server holds none. Use it to check which identity is active and what is stored and shared.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
bfsiNo
tierNo
errorNo
timingNo
custodyNo
featuresNo
agentIdHashNo
snapshotEpochNo
activeShardCountNo
seqStateDegradedNo
activeSharingContractsNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safe read profile (readOnly, idempotent, non-destructive). The description adds genuinely non-obvious behavior: the identity is derived locally by the client, and no plaintext appears because the server holds none. That privacy/architecture context is real value beyond the structured fields, though it omits any session prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the verb and the returned fields, followed by the privacy note and the use case. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description covers scope, data handling, and usage. The only omission is whether a session must first be established (e.g. via saihm_join) before the status is meaningful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, which is the baseline-4 case. The schema is empty and fully covered, so there is nothing further the description needs to specify.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Show the current SAIHM session') and enumerates exactly what is returned: agent identity, tier, custody mode, shard and sharing counts, and bfsi score. It is unmistakably distinct from the write-oriented siblings (remember, forget, share, revoke_share).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use it to check which identity is active and what is stored and shared' gives a clear triggering context, so the agent knows when to reach for it. It stops short of naming alternatives or when-not conditions, but for a status read that is a small gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.14.1
    • Changedsaihm_forget6 fields changed
      • changedInput schema / properties / snapshotId / description
        Previous value: -"With warmStart \"delete\": the snapshot to destroy."New value: +"With warmStart \"delete\": the snapshot to destroy. Blank otherwise."
      • changedInput schema / properties / snapshotId / pattern
        Previous value: -"^[0-9a-f]{64}$"New value: +"^$|^[0-9a-f]{64}$"
      • changedInput schema / properties / token / description
        Previous value: -"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call."New value: +"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. Blank otherwise."
      • changedInput schema / properties / token / pattern
        Previous value: -"^[a-z0-9]{16,32}$"New value: +"^$|^[a-z0-9]{16,32}$"
      • changedInput schema / properties / warmStart / description
        Previous value: -"\"delete\" destroys the snapshot named by snapshotId instead of a memory. Only snapshotId and token go with it."New value: +"\"delete\" destroys the snapshot named by snapshotId instead of a memory. Only snapshotId and token go with it. Leave it blank to erase a memory by id."
      • changedInput schema / properties / warmStart / enum
        Previous value: -[
        -  "delete"
        -]New value: +[
        +  "",
        +  "delete"
        +]
    • Changedsaihm_recall8 fields changed
      • changedInput schema / properties / after / description
        Previous value: -"With listOnly: the next value of the previous page."New value: +"With listOnly or sharesOnly: the next value of the previous page."
      • addedInput schema / properties / sharesOnly
        Added value: +{
        +  "description": "List every pointer shared with you, a page at a time and never cut, without reading any memory. Pages: pass the answer's next as after until next is null. Answers shares_paging_unsupported where the endpoint does not offer it: then recall without it.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / token / description
        Previous value: -"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file."New value: +"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file. Blank otherwise."
      • changedInput schema / properties / token / pattern
        Previous value: -"^[a-z0-9]{16,32}$"New value: +"^$|^[a-z0-9]{16,32}$"
      • changedInput schema / properties / warmStart / description
        Previous value: -"\"latest\" restores the newest snapshot into warm-start/latest-<token>.bin (read it, then remove it); \"list\" lists snapshots. Only token goes with it."New value: +"\"latest\" restores the newest snapshot into warm-start/latest-<token>.bin (read it, then remove it); \"list\" lists snapshots. Only token goes with it. Leave it blank to recall memories."
      • changedInput schema / properties / warmStart / enum
        Previous value: -[
        -  "latest",
        -  "list"
        -]New value: +[
        +  "",
        +  "latest",
        +  "list"
        +]
      • addedOutput schema / properties / sharedSkipped
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / total
        Added value: +{
        +  "type": "number"
        +}
    • Changedsaihm_remember6 fields changed
      • changedInput schema / properties / coversThrough / description
        Previous value: -"With warmStart \"put\": the change feed position the payload covers, the cursor of a position marker."New value: +"With warmStart \"put\": the change feed position the payload covers, the cursor of a position marker. Blank otherwise."
      • changedInput schema / properties / coversThrough / pattern
        Previous value: -"^[!-~]{1,64}$"New value: +"^$|^[!-~]{1,64}$"
      • changedInput schema / properties / token / description
        Previous value: -"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file."New value: +"With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file. Blank otherwise."
      • changedInput schema / properties / token / pattern
        Previous value: -"^[a-z0-9]{16,32}$"New value: +"^$|^[a-z0-9]{16,32}$"
      • changedInput schema / properties / warmStart / description
        Previous value: -"\"put\" stores the payload file warm-start/put-<token>.bin as an encrypted snapshot, then removes the file. Only coversThrough and token go with it."New value: +"\"put\" stores the payload file warm-start/put-<token>.bin as an encrypted snapshot, then removes the file. Only coversThrough and token go with it. Leave it blank to remember content."
      • changedInput schema / properties / warmStart / enum
        Previous value: -[
        -  "put"
        -]New value: +[
        +  "",
        +  "put"
        +]
    • Changedsaihm_share4 fields changed
      • changedInput schema / properties / expiryEpoch / description
        Previous value: -"Optional expiry as a UNIX-epoch count (decimal string)"New value: +"Optional expiry in whole HOURS since the UNIX epoch (decimal string), not seconds: floor(unix_ms / 3600000). Example: \"498192\" is 2026-11-01 00:00 UTC. Blank = no expiry"
      • changedInput schema / properties / expiryEpoch / pattern
        Previous value: -"^[0-9]+$"New value: +"^$|^[0-9]+$"
      • changedInput schema / properties / scope / description
        Previous value: -"Access scope (default read)"New value: +"Access scope (blank = read)"
      • changedInput schema / properties / scope / enum
        Previous value: -[
        -  "read",
        -  "write",
        -  "readwrite"
        -]New value: +[
        +  "",
        +  "read",
        +  "write",
        +  "readwrite"
        +]
  2. 5 tool updatesv0.13.0
    • Changedsaihm_forget6 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Memory cell id (hex) to erase"New value: +"Memory cell id (hex) to erase. Required unless warmStart is \"delete\"."
      • addedInput schema / properties / snapshotId
        Added value: +{
        +  "description": "With warmStart \"delete\": the snapshot to destroy.",
        +  "pattern": "^[0-9a-f]{64}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / token
        Added value: +{
        +  "description": "With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call.",
        +  "pattern": "^[a-z0-9]{16,32}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / warmStart
        Added value: +{
        +  "description": "\"delete\" destroys the snapshot named by snapshotId instead of a memory. Only snapshotId and token go with it.",
        +  "enum": [
        +    "delete"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "id"
        -]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "at": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "complete": {
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "deleted": {
        +      "const": true,
        +      "type": "boolean"
        +    },
        +    "destructionAnchor": {
        +      "type": "string"
        +    },
        +    "epoch": {
        +      "type": "string"
        +    },
        +    "error": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "code": {
        +          "type": "string"
        +        },
        +        "status": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "code",
        +        "status"
        +      ],
        +      "type": "object"
        +    },
        +    "reason": {
        +      "enum": [
        +        "not-found",
        +        "not-attested"
        +      ],
        +      "type": "string"
        +    },
        +    "sharesPurged": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "timing": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "admission": {
        +          "anyOf": [
        +            {
        +              "enum": [
        +                "reserved",
        +                "shared"
        +              ],
        +              "type": "string"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "serverMs": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "totalMs": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "serverMs",
        +        "totalMs",
        +        "admission"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedsaihm_join1 field changed
      • addedInput schema / properties / newIdentity
        Added value: +{
        +  "description": "true once the user confirms they have no SAIHM identity to bring here and want a new, empty memory",
        +  "type": "boolean"
        +}
    • Changedsaihm_recall17 fields changed
      • addedInput schema / properties / after
        Added value: +{
        +  "description": "With listOnly: the next value of the previous page.",
        +  "type": "string"
        +}
      • changedInput schema / properties / cellId / description
        Previous value: -"The shared cell id to read. Required when reading a shared cell."New value: +"The cell id to read: alone, one of your own cells; with the sharer fields, the shared cell (required then)."
      • addedInput schema / properties / listOnly
        Added value: +{
        +  "description": "List your own cells' versions (cellId, seq, commitment) without reading any content. Pages: pass the answer's next as after until next is null.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Filter your OWN memories by keyword (empty = all). Ignored when reading a shared cell."New value: +"Filter your OWN memories by keyword (empty = all). Ignored when reading one cell by cellId."
      • addedInput schema / properties / token
        Added value: +{
        +  "description": "With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file.",
        +  "pattern": "^[a-z0-9]{16,32}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / warmStart
        Added value: +{
        +  "description": "\"latest\" restores the newest snapshot into warm-start/latest-<token>.bin (read it, then remove it); \"list\" lists snapshots. Only token goes with it.",
        +  "enum": [
        +    "latest",
        +    "list"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / asOf
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / cells
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "cellId": {
        +        "type": "string"
        +      },
        +      "commitment": {
        +        "type": "string"
        +      },
        +      "seq": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "cellId",
        +      "seq",
        +      "commitment"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "code": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "status"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / found
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / next
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / servedBy
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / sharedKept
        Added value: +{
        +  "enum": [
        +    "newest",
        +    "oldest"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / snapshot
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "bytes": {
        +          "type": "number"
        +        },
        +        "coversThrough": {
        +          "type": "string"
        +        },
        +        "createdAt": {
        +          "type": "string"
        +        },
        +        "snapshotId": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "snapshotId",
        +        "createdAt",
        +        "bytes",
        +        "coversThrough"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / snapshots
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "bytes": {
        +        "type": "number"
        +      },
        +      "coversThrough": {
        +        "type": "string"
        +      },
        +      "createdAt": {
        +        "type": "string"
        +      },
        +      "snapshotId": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "snapshotId",
        +      "createdAt",
        +      "bytes",
        +      "coversThrough"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / timing
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "admission": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "reserved",
        +            "shared"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "serverMs": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "totalMs": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "serverMs",
        +    "totalMs",
        +    "admission"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "count",
        -  "memories",
        -  "shared",
        -  "sharedTruncated"
        -]
    • Changedsaihm_remember15 fields changed
      • changedInput schema / properties / content / description
        Previous value: -"Information to remember"New value: +"Information to remember. Required unless warmStart is \"put\"."
      • addedInput schema / properties / coversThrough
        Added value: +{
        +  "description": "With warmStart \"put\": the change feed position the payload covers, the cursor of a position marker.",
        +  "pattern": "^[!-~]{1,64}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / token
        Added value: +{
        +  "description": "With warmStart: 16 to 32 characters from a-z and 0-9, chosen at random for this call. It names the payload file.",
        +  "pattern": "^[a-z0-9]{16,32}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / warmStart
        Added value: +{
        +  "description": "\"put\" stores the payload file warm-start/put-<token>.bin as an encrypted snapshot, then removes the file. Only coversThrough and token go with it.",
        +  "enum": [
        +    "put"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "content"
        -]
      • addedOutput schema / properties / at
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / bytes
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / commitment
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / commitmentHash / description
        Added value: +"Deprecated: the same value as commitment, kept for existing readers."
      • addedOutput schema / properties / coversThrough
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / createdAt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "code": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "status"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / snapshotId
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / timing
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "admission": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "reserved",
        +            "shared"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "serverMs": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "totalMs": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "serverMs",
        +    "totalMs",
        +    "admission"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "cellId",
        -  "seq",
        -  "shardId",
        -  "commitmentHash",
        -  "sharesReissued",
        -  "sharesNotReissued",
        -  "sharesIncomplete"
        -]
    • Changedsaihm_status4 fields changed
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "code": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "status"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / features
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": {},
        +      "properties": {
        +        "warmStart": {
        +          "anyOf": [
        +            {
        +              "additionalProperties": {},
        +              "properties": {
        +                "token": {
        +                  "const": "required",
        +                  "type": "string"
        +                }
        +              },
        +              "type": "object"
        +            },
        +            {
        +              "items": {},
        +              "type": "array"
        +            },
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "type": "number"
        +            },
        +            {
        +              "type": "boolean"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / timing
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "admission": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "reserved",
        +            "shared"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "serverMs": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "totalMs": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "serverMs",
        +    "totalMs",
        +    "admission"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "agentIdHash",
        -  "tier",
        -  "custody",
        -  "activeShardCount",
        -  "activeSharingContracts",
        -  "bfsi",
        -  "snapshotEpoch",
        -  "seqStateDegraded"
        -]
  3. 2 tool updatesv0.10.0
    • Changedsaihm_recall4 fields changed
      • addedInput schema / properties / shareEntries
        Added value: +{
        +  "description": "With the share events feed on, also return every entry of the share map; without it, only its summary.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / memories / items / properties / commitment
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memories / items / properties / grant
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / shareStates
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "asOf": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "counts": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "ended": {
        +          "type": "number"
        +        },
        +        "erased": {
        +          "type": "number"
        +        },
        +        "live": {
        +          "type": "number"
        +        },
        +        "stale": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "live",
        +        "stale",
        +        "ended",
        +        "erased"
        +      ],
        +      "type": "object"
        +    },
        +    "entries": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "cellId": {
        +            "type": "string"
        +          },
        +          "commitment": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "copiesInvalidBefore": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "endedAt": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "endedBy": {
        +            "anyOf": [
        +              {
        +                "enum": [
        +                  "event",
        +                  "reconciliation"
        +                ],
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "expiryEpoch": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "grant": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "scope": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "senderVerified": {
        +            "type": "boolean"
        +          },
        +          "seq": {
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "sharer": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "enum": [
        +              "live",
        +              "stale",
        +              "ended",
        +              "erased"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "sharer",
        +          "cellId",
        +          "status",
        +          "grant",
        +          "scope",
        +          "expiryEpoch",
        +          "seq",
        +          "commitment",
        +          "senderVerified",
        +          "endedAt",
        +          "endedBy",
        +          "copiesInvalidBefore"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "since": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "startedAt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "stopped": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "unsupported",
        +            "tier",
        +            "erased"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "required": [
        +    "since",
        +    "complete",
        +    "asOf",
        +    "stopped",
        +    "startedAt",
        +    "counts"
        +  ],
        +  "type": "object"
        +}
    • Changedsaihm_remember4 fields changed
      • addedOutput schema / properties / sharesIncomplete
        Added value: +{
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / sharesNotReissued
        Added value: +{
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / sharesReissued
        Added value: +{
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "cellId",
        -  "seq",
        -  "shardId",
        -  "commitmentHash"
        -]New value: +[
        +  "cellId",
        +  "seq",
        +  "shardId",
        +  "commitmentHash",
        +  "sharesReissued",
        +  "sharesNotReissued",
        +  "sharesIncomplete"
        +]
  4. 2 tool updatesv0.2.2
    • Changedsaihm_recall3 fields changed
      • addedOutput schema / properties / shared
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "cellId": {
        +        "type": "string"
        +      },
        +      "expiryEpoch": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "scope": {
        +        "type": "string"
        +      },
        +      "sharer": {
        +        "type": "string"
        +      },
        +      "verified": {
        +        "const": false,
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "sharer",
        +      "cellId",
        +      "scope",
        +      "expiryEpoch",
        +      "verified"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / sharedTruncated
        Added value: +{
        +  "type": "boolean"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "count",
        -  "memories"
        -]New value: +[
        +  "count",
        +  "memories",
        +  "shared",
        +  "sharedTruncated"
        +]
    • Changedsaihm_status5 fields changed
      • changedOutput schema / properties / activeShardCount / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / activeSharingContracts / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / bfsi / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / seqStateDegraded
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "agentIdHash",
        -  "tier",
        -  "custody",
        -  "activeShardCount",
        -  "activeSharingContracts",
        -  "bfsi",
        -  "snapshotEpoch"
        -]New value: +[
        +  "agentIdHash",
        +  "tier",
        +  "custody",
        +  "activeShardCount",
        +  "activeSharingContracts",
        +  "bfsi",
        +  "snapshotEpoch",
        +  "seqStateDegraded"
        +]
  5. 9 tool updatesv0.2.1
    • First observedsaihm_forget
    • First observedsaihm_governance_propose
    • First observedsaihm_governance_vote
    • First observedsaihm_join
    • First observedsaihm_recall
    • First observedsaihm_remember
    • First observedsaihm_revoke_share
    • First observedsaihm_share
    • First observedsaihm_status

TDQS

A4.2/5.0

Scored across 9 tools

Disambiguation4/5

Core memory operations (remember/recall/forget) and access operations (share/revoke_share) have clearly distinct purposes with no real overlap. The main wrinkle is that remember, recall, and forget each overload a warmStart parameter for snapshot management, muddying their boundaries, and the two governance stubs are present but always error.

Naming Consistency4/5

All tools share a predictable saihm_ prefix, which aids grouping. However, the convention is slightly mixed: most are simple verbs (remember, recall, forget, share, join) or verb_noun (revoke_share), while the governance tools flip to noun_verb (governance_propose, governance_vote).

Tool Count5/5

Nine tools is well-scoped for a memory-plus-sharing-plus-governance domain, with each tool covering a distinct capability. Nothing feels redundant or padded aside from two intentionally inert governance stubs.

Completeness3/5

CRUD for memory cells (remember/recall/forget), sharing (share/revoke_share), status, and onboarding (join) are covered. But the join description references an 'export-identity' flow that has no corresponding tool, and the two governance tools are non-functional stubs, leaving notable gaps in the advertised surface.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for context-aware memory and retrieval with hybrid search, dual-phase memory, and boundary-first security.
    3
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Open-source MCP memory server providing persistent, cross-platform context for AI tools via a knowledge graph with encrypted storage.
    7 npm
    13
    AGPL 3.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    A local-first memory MCP server that enables storing, searching, and managing personal memories with hybrid keyword and semantic recall, all on-device.
    13 npm
    MIT