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

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.

Everything is encrypted on your own machine before it goes anywhere, so nobody else can read your memories. Not the storage, not SAIHM.

Start free — one command

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

That's it. No card, no account to fill in, nothing to invent. It sets up your identity on this machine and prints a one-time sign-in to confirm you're a real person. Open the link, enter the short code, approve.

Then point your AI tool at it. This works in Claude Desktop, Claude Code, Cursor, Cline, and anything else that speaks MCP — add the "saihm" entry inside your existing mcpServers section:

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

Restart the connection and say "Recall my SAIHM memories." You're running.

Two details in that config are load-bearing:

  • Keep timeout: 60. Some tools allow as little as 1.5 seconds for a server to start, which isn't long enough for npx to fetch and launch a package. A server that misses the deadline is skipped silently — the tools simply never appear, and nothing in the chat says why.

  • No trailing commas. These files are strict JSON. A stray comma doesn't just break this entry; it invalidates the whole file and every other tool you had configured disappears with it.

Prefer not to touch a terminal? Add the config above first, then say "Join SAIHM" to your assistant. It does the same setup for you.

Related MCP server: Hippocampus

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. Two further tools, saihm_governance_propose and saihm_governance_vote, are registered for a roadmap feature and are not yet active.

"Forget" really means forget. The key to that specific 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.

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 during setup 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 prints the file's location when it runs — that's the line to keep. The same key carries through if you upgrade to a paid plan: same identity, same memories, nothing migrated.

Using a second computer? Two ways:

  • Same memory, both machines — put your key file on the second machine, set up the config there, and say "Recall my SAIHM memories."

  • Work and personal kept 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.

See it run

  • Live demos across every major model — offline, about a minute each, no account: https://citw2.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/citw2/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. 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"

Both are needed — a paid plan without SAIHM_PAYMENT_METHOD refuses to start, because that setting names which payment rail to check. stripe is one option; stablecoin is another, and your assistant can tell you what your operator accepts.

If something isn't working

What you see

Usual cause

No SAIHM tools appear, and no error anywhere

timeout too low — see the config above

Every other tool vanished too

A trailing comma broke the settings file

Tools appear but every call fails

SAIHM_ENDPOINT_URL unreachable

"no identity"

Setup hasn't run on this machine yet

A different memory than you expected

This machine has its own key rather than yours

status mentions seq-state

A small local safeguard file couldn't be read or written. Your memories are unaffected — see SAIHM_SEQ_STATE_PATH below

forget worked but mentions a feed

The erasure stands — only the notification line couldn't be written. See SAIHM_ERASURE_FEED below

How it works

In plain terms. Everything is encrypted on your machine before it is sent, and decrypted on your machine after it comes back. What's stored 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.

For the technically inclined.

  • Encrypt before send — remember encrypts client-side; recall decrypts client-side. Your plaintext, master secret, and key-encryption key never leave this process.

  • Post-quantum — ML-DSA-65 for identity and signing, ML-KEM-768 for authenticated sharing, via @saihm/client-pro.

  • Crypto-shred erasure — forget destroys the endpoint-side wrapped data-encryption key, rendering the cell undecryptable (GDPR Art. 17).

  • Erasure that travels — forget also appends one line to a per-identity feed, so anything that derived from a cell — an index, a mirror, an extracted fact — can be told to drop it too. An erasure that stops at this substrate is not an erasure. On by default; SAIHM_ERASURE_FEED=0 turns it off.

  • Standard transport — POST {method, params} with Authorization: Bearer <JWT>; the endpoint binds your tenant from the JWT. HTTPS only, with loopback http permitted for local development.

  • Self-onboarding — with no SAIHM_AUTH_HEADER set, the client proves control of your identity and mints its own short-lived token, refreshing transparently. You paste one config once and never re-paste a token. Cancelling a subscription stops the next refresh, so access ends naturally.

Security model

Property

Guarantee

Confidentiality vs the endpoint

The endpoint holds ciphertext, wrapped DEKs, and public keys only — no key able to decrypt.

Integrity / authenticity

Every cell is ML-DSA-65-signed over its contents, including the sequence number.

Anti-replay

The signed monotonic sequence is rejected by the endpoint if it does not strictly increase.

Tenant isolation

Your agentIdHash (the JWT sub) namespaces your state; a write whose signed identity differs from the JWT is rejected.

Authenticated sharing

Grantee public keys are pinned out-of-band and verified before any secret is bound to them; on the recipient side, recallShared pins the sharer's key and verifies the cell signature before returning any plaintext.

Erasure

Destroying the endpoint-side wrapped DEK crypto-shreds the cell.

Local recall cache

When the recall cache is on, memories this device has opened are also kept unencrypted in a mode-600 file beside your key. forget removes the memory from it; SAIHM_RECALL_CACHE=0 keeps no local copy.

Erasure cascade

Each forget appends one line to $SAIHM_HOME/tenants/<agentIdHash>/erasures.ndjson. The line carries the cell id, the identity and the time — never cell content.

Where encrypted cells are stored

This client encrypts cells and hands the ciphertext to whichever operator endpoint SAIHM_ENDPOINT_URL points at; that operator chooses and configures the durable storage behind it — typically a local IPFS / Kubo node first, then a Filecoin deep-archive provider. Storage is operator-configured by design: the protocol never locks anyone to a single provider. Running your own endpoint means provisioning that storage yourself.

Prefer not to run storage at all? The hosted operator at https://saihm.net provides durable storage and is non-custodial — because this client encrypts every cell locally, the hosted operator only ever stores ciphertext and never holds a key.

Configuration

Most people need none of this: the setup above sets one variable and the rest have working defaults.

Env

Required

Meaning

SAIHM_ENDPOINT_URL

no

https://…/mcp (or http:// for 127.0.0.1/localhost only). Defaults to https://saihm.net/mcp — set it only to reach a different operator.

SAIHM_MASTER_SECRET_FILE

see note

Path to a mode-600 file holding the hex master secret. The preferred way to supply a key, because it keeps the key out of a config file that may be synced or shared. Takes precedence over SAIHM_MASTER_SECRET_HEX.

SAIHM_MASTER_SECRET_HEX

see note

The master secret inline, ≥ 64 hex characters (≥ 32 bytes), high-entropy, client-held, never sent. Prefer the file form: anything inline lands in the config file itself.

SAIHM_SELF_JOIN

no

Controls the saihm_join onboarding tool — the one that answers "Join SAIHM". On by default; set to 0 to remove it and expose only the canonical eight tools.

SAIHM_HOME

no

Where the identity file lives ($SAIHM_HOME/free-identity.key, mode 600), where per-restart bookkeeping is kept, and where the erasure feed is written unless SAIHM_ERASURE_FEED_DIR overrides it. Defaults to ~/.saihm.

SAIHM_AUTH_HEADER

no

Bearer <JWT>, used verbatim. Omit to self-onboard (recommended) — the client mints and refreshes its own token, so there is nothing to paste or re-paste.

SAIHM_TIER

self-onboard only

Plan label recorded in encrypted metadata (FREE, PRO, …). Required when self-onboarding; otherwise resolved via status().

SAIHM_PAYMENT_METHOD

paid self-onboard

Entitlement rail (stripe, stablecoin, …) for a paid plan. Not used by the free tier. Ignored when SAIHM_AUTH_HEADER is set.

SAIHM_SEQ_STATE_PATH

no

Overrides where the anti-rollback bookkeeping is written. Running as an MCP server this is on by default at $SAIHM_HOME/seq.<id>.json; set it only to relocate it. The default location is ours to manage: if it can't be written, the tally stays in memory for the session and status says so. A location you set is yours: if it can't be written, calls fail and name the path, so a safeguard you asked for never goes quiet without telling you. status reports this as seq-state=… followed by rollback-guard=persisting (writes still work, so the next one rewrites the file) or memory-only-this-run (it retries at the next restart). Either way, if the file couldn't be READ at startup the safeguard starts from scratch and rebuilds as each memory is next read — so an older copy of a memory would not be caught during that window. At the default location that window is about accidental corruption rather than an attacker: writing to that file takes the same access that reads the identity key sitting beside it. Somewhere you relocate it to, that no longer follows — give it the protection you give $SAIHM_HOME.

SAIHM_RECALL_CACHE

no

Controls the recall cache: the memories this device has already opened, kept so that recall asks the service only for new ones. On by default when your key is the self-join identity file in SAIHM_HOME; set to 0 to keep no local copy. The copy is unencrypted in a file readable only by your user (mode 600), beside the key; forget removes a memory from it, and a memory erased from another device leaves it at the next recall.

SAIHM_RECALL_CACHE_PATH

no

Where the recall cache is written. With a cache, a recall fetches only what has changed since the last one; without a cache it fetches every memory, every time — measured on 2026-09-17 against ~208 memories on the hosted endpoint: a warm recall took 24 ms with a cache and 818 ms without, and because the cache is a file it survives a restart — the FIRST recall of a new process took 114-115 ms with a populated cache against 1,022-1,094 ms without. Only the very first run, which builds the cache, pays the full fetch. The cache defaults ON only for an identity that boots from the key file in $SAIHM_HOME (that installation already keeps its key and sequence marks there). For any other key source — including SAIHM_MASTER_SECRET_FILE pointing elsewhere, or an inline secret — it is OFF unless you set this, and the client says so once on its first recall. The file holds your memories as plaintext at rest, which is why it is not simply on for everyone: it is your decision. SAIHM_RECALL_CACHE=0 turns it off in every case, an explicit path included, and silences the notice.

SAIHM_STATE_DIR

no

Where transient operator state (such as checkout-url.txt) is written. Does not relocate your identity or its bookkeeping.

SAIHM_ERASURE_FEED

no

Controls the erasure feed — one line appended per forget, so a consumer can drop whatever it derived from that cell. On by default; set to 0 to write nothing. Writing the line can never fail an erasure: the erasure is what you asked for and the line is a notification about it, so a feed that can't be written is reported beside the result and the erasure still stands.

SAIHM_EVENTS

no

Set to 1 to follow share events: from the moment the server starts, it long-polls the endpoint for shares made to you (new, updated, stale, ended, erased). saihm_recall then returns a summary as shareStates when it lists memories, beside shared, with every entry when the call passes shareEntries: true, and the map is written to share-states.json beside the erasure feed for other processes to read (see Following shares below). Off by default. The map and the position in the feed survive a restart (see SAIHM_SHARE_MAP_STORE); a sender is marked verified only after a shared memory is read and its signature checked. Endpoints that do not offer events are left alone.

SAIHM_SHARE_MAP_STORE

no

Where the share feed keeps its position between runs: file (the default) writes feed-state.json beside the erasure feed, so a restart asks the endpoint only for what it missed; off keeps everything in memory, and the client fetches the whole share listing at every start. A root that cannot be written falls back to memory on its own, so this needs no setting where there is nowhere to write. Only read when the feed is on.

SAIHM_ERASURE_FEED_DIR

no

Overrides the feed's root. Defaults to SAIHM_HOME, then ~/.saihm; the feed itself is at <root>/tenants/<agentIdHash>/erasures.ndjson, and the directory is created the first time a tool runs. Must be an absolute path — a relative one resolves against the working directory, so one identity would write to a different file depending on where the process started while a consumer reported the feed missing. Deliberately not SAIHM_STATE_DIR: a feed is identity-scoped, so it has to move with the identity or not at all, and a consumer refuses a line from an identity it is not watching.

Note: a master secret is required, from one source or the other — but setup creates and configures it for you, which is why the config above has neither.

For developers

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; 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();

The derived saihm.agentIdHash is the sub the endpoint binds your tenant to — when self-onboarding the client proves it via ML-DSA; with a static SAIHM_AUTH_HEADER it must equal the JWT sub. Publish saihm.identityRecord so other agents can share to you.

Constructing SaihmProClient directly writes nothing to your home directory; the per-restart bookkeeping is opted into by the MCP server's boot path, or by setting SAIHM_SEQ_STATE_PATH explicitly.

Following shares (optional). With SAIHM_EVENTS=1, or saihm.startShareEvents() in your own process, the client long-polls the endpoint and keeps a map of the shares made to you: saihm.shareStates(), and shareStates in the saihm_recall result. The summary is on every recall that lists memories: since, complete, asOf, stopped, startedAt and counts (live, stale, ended, erased). The entries are added only when the call passes shareEntries: true; without it they are absent, which is not the same as empty. Each entry names the sharer and cell, a status (live, stale, ended or erased), the grant, the sharer's latest seq and commitment when known, and senderVerified, which is true only after a read checked the sharer's signature. Every time is ISO-8601 UTC with milliseconds (YYYY-MM-DDTHH:MM:SS.sssZ). To read it safely:

  • Treat a cached copy of a shared memory as erased when its entry is erased, or when the copy was made before the entry's copiesInvalidBefore (count a copy made up to 5 minutes after that time as made before it, for clock skew).

  • An entry whose endedBy is reconciliation may have been erased rather than revoked: treat its copies as possibly erased.

  • Conclude anything from a missing entry only when since is set and complete is true. Until then the map may still be catching up, and a live entry may be out of date. A map with since null or complete false is no baseline to compare a later map against: only a complete map replaces one.

  • The map is as of asOf, the time of the latest answer from the endpoint or completed catch-up; it is null until the first. While the network is down asOf stops advancing and complete stays as it was, so compare asOf with your clock when you need a current map.

  • stopped says why the client stopped following: unsupported (the endpoint offers no feed), tier (the plan has none) or erased (the identity was erased). complete is then false until a later catch-up completes. startedAt is when this process started following, so a null asOf reads as starting or as stopped.

  • The map and the position in the feed survive a restart, so since carries over and a new process asks the endpoint for what it missed rather than for the whole listing. since may therefore be EARLIER than startedAt: it is when the map this process resumed was first complete, not when this process began. Before 0.11.0 since always followed startedAt; do not use the two together to tell one run from another. A restored map is NOT complete until this process has had an answer: complete is false and asOf null until then, which is exactly the state above in which nothing may be concluded from a missing entry. saihm.stopShareEvents() ends the polling.

For other processes, the client writes the summary and every entry to <root>/tenants/<agentIdHash>/share-states.json, beside the erasure feed and under the same root (SAIHM_ERASURE_FEED_DIR, then SAIHM_HOME, then ~/.saihm). It is owner-only (file 0600, directory 0700), replaced whole, written soon after the map, since, complete or stopped changes and at least once a minute, and left in place when the process ends; its asOf shows its age. The client never reads it back. Several processes of one identity each keep their own map and may each write the file: it is replaced under a lock and only by a map whose asOf is not older, and its since is the writer's. Until a new process has its first answer, the file may still be an earlier process's. No file means no feed has run for that identity under that root; it asserts nothing.

The position itself is kept in <root>/tenants/<agentIdHash>/feed-state.json, in the same directory and with the same owner-only modes, and this file the client does read back. Nothing in it is trusted: a state that is missing, unreadable, malformed, too large or older than the endpoint keeps events for is ignored, and the client starts cold as it always did. Set SAIHM_SHARE_MAP_STORE=off to keep the position in memory only; a root that cannot be written does the same without being asked. Several processes of one identity may each write the file, and each write holds a position and the map that goes with it together, so whichever was written last is a pair a later process can resume from.

A shared read (saihm_recall with the sharer and cell) returns the commitment of the version it opened and, when the endpoint sends it, the grant that served the read, named as in the entries, so a copy compares with its entry exactly.

Errors. Non-2xx responses throw SaihmEndpointError carrying status and a typed code (e.g. BLIND_BAD_EXPIRY, BLIND_STALE_SEQ, governance_unavailable). Branch on the code rather than the message.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMemory cell id (hex) to erase

TDQS

A4.5/5.0
Behavior5/5

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

Adds significant behavioral detail beyond the destructiveHint annotation: the key destruction makes content unreadable even to the operator, and the operation is irreversible. This fully informs the agent of consequences.

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 short sentences each carry unique information: the action, the cryptographic consequence, and the usage caveat. No filler or repetition of schema details.

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 one-parameter destructive tool with no output schema, the description fully covers what it does, why it is irreversible, and when to invoke it. 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?

Schema coverage is 100% and the schema already describes the single parameter as 'Memory cell id (hex) to erase.' The description echoes 'cell id' without adding format, source, or validation details, so 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?

States a specific verb ('cryptographically erase'), a specific resource ('one memory by its cell id'), and legal context (GDPR Art. 17). Clearly distinguishes from sibling tools that remember, recall, share, or revoke.

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?

Explicitly says to use it only when erasure is intended and not 'to tidy a working set,' which guides when NOT to use it. It does not name a specific alternative like saihm_revoke_share, but the exclusion is actionable enough.

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. 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, call saihm_join again to finish; the memory tools then work. No payment and no website visit.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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

The description adds behavioral context beyond annotations: it explains the two-step process with human approval, generation of a sovereign key, and the return of a URL/code. This complements the openWorldHint and idempotentFalse annotations. However, it does not mention potential side effects (e.g., calling again after joining), though that is minor given the setup nature.

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?

The description is four sentences long, front-loading the core action. Every sentence adds value: function, when to call, step-by-step process, and a note about no payment. It is well-structured and free of fluff.

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?

Given no output schema and no parameters, the description covers the activation process completely: triggers, human approval, return value, and post-approval steps. It could mention error states (e.g., if approval fails), but overall it is sufficiently complete for agent use.

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 input schema has zero parameters and schema coverage is 100%, so the description does not need to add parameter info. According to guidelines, 0 parameters yields a baseline of 4, which is appropriate here as there is no missing information.

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 clearly states the tool's purpose: 'Activate free SAIHM persistent memory for this agent.' It uses a specific verb ('Activate'/'Join') and resource ('SAIHM persistent memory'), and the context of sibling tools (e.g., saihm_remember, saihm_forget) distinguishes this as the setup/join tool, making it unambiguous.

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?

The description explicitly says 'Call this when the user asks to join, sign up for, or set up SAIHM,' providing clear when-to-use guidance. It also outlines a two-step process (call first, then after approval call again). It does not explicitly state when not to use (e.g., if already joined), but the scenario is well-defined and distinct from siblings.

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. To read a single cell another agent shared with you, pass their sharerPinnedAgentIdHashHex and sharerRecord together with the cellId; that path is read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoFilter your OWN memories by keyword (empty = all). Ignored when reading a shared cell.
cellIdNoThe shared cell id to read. Required when reading a shared cell.
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
countYes
sharedYes
memoriesYes
shareStatesNo
sharedTruncatedYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already provide readOnlyHint, idempotentHint, and destructiveHint. The description adds valuable behavioral context beyond those: decryption happens locally, the server never sees plaintext, and the shared-cell path is read-only. This enriches the agent's understanding without contradicting any annotation.

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?

The description is compact and well-structured: core operation first, then usage timing, then filtering behavior, then the special shared-cell path. Every sentence contributes distinct, useful information with no filler.

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 output schema, annotations, and full schema coverage, the description covers invocation timing, filtering, and the shared-cell special case. Nothing essential is missing for an agent to decide when and how to call this tool 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, but the description adds meaningful parameter relationships: query is ignored when reading a shared cell, and sharerPinnedAgentIdHashHex, sharerRecord, and cellId are used together. This goes beyond the individual field descriptions.

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 clearly states a specific action ('Retrieve your memories from SAIHM') and adds meaningful detail about local decryption. It distinguishes the normal memory-recall path from the shared-cell read path, and the name/title are not merely restated.

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?

The description explicitly tells the agent when to use it ('at the start of a session, or whenever past context is needed') and explains the query/all-memories choice. It does not explicitly list when-not-to-use cases or name sibling alternatives, so it falls just short of a 5.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
cellIdNoExisting cell id (hex) to update; omit to create a new cell
contentYesInformation to remember

Output Schema

ParametersJSON Schema
NameRequiredDescription
seqYes
cellIdYes
shardIdYes
commitmentHashYes
sharesReissuedYes
sharesIncompleteYes
sharesNotReissuedYes

TDQS

A4.5/5.0
Behavior4/5

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

The description discloses important behavioral traits beyond the annotations: encryption happens in-process, the key never leaves, the server holds ciphertext it cannot read, and the update behavior around re-issued shares. It also notes that a share not re-issued needs saihm_share again. The annotations already indicate readOnlyHint=false, destructiveHint=false, and idempotentHint=false, and the description adds meaningful context about the encryption and share re-issuance behavior. It doesn't contradict the annotations. A 4 is appropriate because it adds rich behavioral context, though it doesn't cover every possible edge case.

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?

The description is a single paragraph that front-loads the core purpose and then provides necessary detail about encryption and update behavior. It is somewhat dense and could be split into clearer sentences, but every sentence earns its place. The structure is acceptable, though the share re-issuance explanation is a bit convoluted.

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?

The description covers the core purpose, encryption behavior, update semantics, and the relationship to saihm_share and saihm_forget. It mentions the return value (cell id that saihm_forget takes). With an output schema present and annotations covering safety, the description is fairly complete. It could be slightly clearer about the exact conditions for re-issuance, but overall it provides enough context for an agent to call the tool 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 description coverage is 100%, so the schema already documents both parameters. The description adds meaning by explaining that cellId is for updating an existing cell and that omitting it creates a new cell, and it explains the update behavior around shares. This goes beyond the schema's simple descriptions, so a 4 is justified.

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 and resource: 'Store information in SAIHM persistent memory.' It clearly distinguishes the tool from siblings by stating it is for facts/decisions/context that should outlive the session, and it explicitly mentions updating an existing cell via cellId. This is a clear, specific purpose that an agent can act on.

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 explicitly states when to use the tool: 'Use this when a fact, decision, or piece of context should outlive the current session.' It also provides guidance on when to pass an existing cellId to update rather than create, and it mentions the relationship to saihm_share and saihm_forget. This is strong usage guidance with clear conditions and alternatives.

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 (default read)
cellIdYesThe cell to share
expiryEpochNoOptional expiry as a UNIX-epoch count (decimal string)
recipientRecordYesThe grantee's published identity record (hex fields)
recipientPinnedAgentIdHashHexYesThe grantee's agentIdHash (hex), pinned out-of-band

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already signal a mutating, non-destructive, open-world operation. The description adds useful behavioral detail beyond the annotations: 'Only that one cell is exposed' and 'sharing re-wraps its key rather than copying the memory.' There is no contradiction with annotations.

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?

The description is front-loaded with the core action and is reasonably compact. Each clause adds relevant detail, though some restatement of schema fields such as scope values and recipient identifiers makes it slightly less tight than it could be.

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 mutating share operation with five parameters and no output schema, the description covers recipient identity requirements, scope choices, the single-cell scope, and the key-rewrap side effect. The schema covers expiry. It lacks explicit alternative routing and response/error behavior, but the essentials for a correct call are present.

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. The description mostly restates schema facts such as the recipient being pinned out-of-band and the scope enum values, rather than adding new parameter-level meaning. It does not materially extend the schema's parameter documentation.

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 names a specific verb and resource: 'Grant one other agent access to a single memory cell, named by cellId.' It also clarifies recipient identification and scope values. It does not explicitly distinguish itself from sibling tools like saihm_revoke_share, but the grant-vs-revoke action is sufficiently clear.

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?

The description clearly conveys the mechanics of sharing and how to identify the recipient, but it does not state when to use this tool over alternatives such as saihm_revoke_share, saihm_remember, or saihm_recall. Usage context is implied rather than explicitly framed.

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
bfsiYes
tierYes
custodyYes
agentIdHashYes
snapshotEpochYes
activeShardCountYes
seqStateDegradedYes
activeSharingContractsYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false. The description adds valuable context beyond that: no plaintext is returned because the server holds none, and it clarifies that the identity is derived locally while counts/tier/bfsi come from the server. This helps an agent predict response behavior.

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 no filler. The primary action and result are front-loaded, and the follow-up sentences add only essential behavioral and usage context.

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 zero-parameter, read-only status tool with a rich annotation set and an output schema, the description covers everything an agent needs: what is shown, what is safe, and why no plaintext appears. Nothing meaningful 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?

The tool has zero parameters, so the schema already fully covers them (100% coverage). The description needs to do no parameter work, making the baseline 4 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?

The description states a specific verb ('Show') and a well-defined resource ('current SAIHM session'), then enumerates the exact contents: agent identity, tier, custody mode, shard and sharing counts, and bfsi score. This clearly distinguishes it from the mutation-focused sibling tools (join, share, forget, recall, vote).

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?

The description explicitly says 'Use it to check which identity is active and what is stored and shared,' which gives clear context for when this tool is appropriate. It does not explicitly name alternatives or exclusions, but among siblings that all perform actions, the read-only status role is unambiguous.

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. 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"
        +]
  2. 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"
        +]
  3. 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.4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: join, remember, recall, forget, share, revoke_share, status, governance_propose, governance_vote. No overlapping functionality; even share and revoke_share are explicit opposites.

Naming Consistency5/5

All tools follow a consistent 'saihm_' prefix and use snake_case with a verb_noun or noun_verb pattern (e.g., saihm_remember, saihm_governance_propose). The pattern is uniform across the entire surface.

Tool Count5/5

9 tools is well within the ideal range and each tool covers a distinct operation in the memory lifecycle and governance. No redundancy or bloat; the count is appropriate for the server's scope.

Completeness5/5

The tool set covers the full lifecycle: join, remember (create/update), recall (read), forget (delete), share/revoke_share (access control), status (monitoring), and governance propose/vote. No obvious gaps for the stated purpose.

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.
    10 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.
    16 npm
    MIT