@saihm/mcp-server
Advanced tools
+38
-13
@@ -47,3 +47,11 @@ #!/usr/bin/env node | ||
| const PACKAGE_VERSION = readPackageVersion(); | ||
| const server = new McpServer({ name: 'saihm', version: PACKAGE_VERSION }, { capabilities: { tools: {}, prompts: {} } }); | ||
| const server = new McpServer({ name: 'saihm', version: PACKAGE_VERSION }, { | ||
| capabilities: { tools: {}, prompts: {} }, | ||
| // Sent once at initialize, to every caller, on every session — so it is a pointer, not a | ||
| // manual. The manual is the saihm_session_bootstrap prompt, which costs nothing until an | ||
| // agent invokes it. HR-3 bars recommendation language here; this scopes the tools only. | ||
| instructions: "SAIHM is this agent's persistent memory across sessions, models and vendors. Load it" + | ||
| ' before other work using the saihm_session_bootstrap prompt, which also carries the rules' + | ||
| ' for when to store, recall, share and erase. Erasure is cryptographic and irreversible.', | ||
| }); | ||
| let runtime = null; | ||
@@ -165,3 +173,3 @@ function getRuntime() { | ||
| title: 'Remember', | ||
| description: 'Store information to SAIHM persistent encrypted memory. Use this when an agent or user wants a fact, decision, or piece of context to persist across sessions.', | ||
| description: 'Store information in SAIHM persistent encrypted memory. Use this when a fact, decision, or piece of context should outlive the current session. Returns the cell id that saihm_forget takes.', | ||
| inputSchema: { content: z.string().describe('Information to remember') }, | ||
@@ -259,3 +267,3 @@ // The cell id is the whole receipt: it is what confirms the write and what | ||
| // so, and the tool description is the one place a reviewer reads first. | ||
| 'Retrieve memories from the SAIHM encrypted store; the operator decrypts and returns plaintext, this client holds no keys. Use this at the start of a session or whenever past context is needed; pass a keyword to filter, or leave empty to load all.', | ||
| 'Retrieve memories from the SAIHM encrypted store; the operator decrypts and returns plaintext, and this client holds no keys. Use at the start of a session, or whenever past context is needed. Pass a keyword to filter, or leave empty to load all.', | ||
| inputSchema: { query: z.string().optional().describe('Filter by keyword (empty = all)') }, | ||
@@ -392,3 +400,3 @@ outputSchema: { | ||
| title: 'Forget (GDPR erasure)', | ||
| description: 'Cryptographically erase a memory (GDPR Art. 17 erasure). Use this only to permanently and irreversibly delete a stored memory by its cell id; this cannot be undone.', | ||
| description: 'Cryptographically erase one memory by its cell id (GDPR Art. 17). Destroying the key makes the content unreadable to everyone, the operator included. Irreversible: use it when erasure is the intent, not to tidy a working set.', | ||
| inputSchema: { id: z.string().describe('Memory entry ID (hex cellId) to erase') }, | ||
@@ -469,3 +477,3 @@ annotations: { | ||
| title: 'Status', | ||
| description: 'Show SAIHM session status (PRS, BFSI, storage by tier, sharing, PHI), as far as the operator reports them — a non-custodial operator cannot see stored-byte totals. Use this to check the agent identity, reputation, storage, and sharing state of the current SAIHM session.', | ||
| description: 'Show the current SAIHM session: agent identity, tier, the prs and bfsi scores, storage by tier, and sharing state, as far as the operator reports them — a non-custodial operator cannot see stored-byte totals. Use it to check the agent identity, custody mode, and what the operator reports about storage and sharing.', | ||
| inputSchema: {}, | ||
@@ -687,3 +695,3 @@ // Which of these an operator can answer depends on its custody model, so every | ||
| // callers into a validation rejection. A test asserts the casing stays in step. | ||
| "Create a sharing contract over one or more shards — type is 'temporary', 'permanent' or 'syndicate'. Use this to grant another agent access to specific memories.", | ||
| "Grant other agents access to specific memory shards. Set type to 'temporary', 'permanent' or 'syndicate', and scope to 'read', 'write' or 'readwrite'. Grantees are hex agent-id hashes, not names, and shardIds lists exactly what is shared: nothing outside it is exposed, and sharing does not copy the memory.", | ||
| inputSchema: { | ||
@@ -792,3 +800,3 @@ granteeIdHashesHex: z.array(z.string()).describe('Hex-encoded grantee agent ID hashes'), | ||
| title: 'Revoke share', | ||
| description: "Revoke an existing sharing contract by its contractId. Use this to withdraw a grantee's access previously granted with saihm_share.", | ||
| description: 'Revoke a sharing contract by its contractId, withdrawing access granted with saihm_share. It applies to future reads and cannot retract what a grantee has already read. Use it to end access; the memory itself remains, and saihm_forget is what erases.', | ||
| inputSchema: { contractId: z.string().describe('Sharing contract ID to revoke') }, | ||
@@ -843,3 +851,3 @@ annotations: { | ||
| title: 'Propose (governance)', | ||
| description: "Submit a gSAIHM-governance proposal. Scope MUST be 'emission_param' or 'protocol_upgrade'. Use this to open a protocol governance vote.", | ||
| description: "Open a protocol governance proposal. Set scope to 'emission_param' or 'protocol_upgrade'; for 'emission_param' also pass paramKey and proposedValue. Returns a hex proposalId that saihm_governance_vote takes. It starts a vote rather than changing a setting.", | ||
| inputSchema: { | ||
@@ -909,3 +917,3 @@ scope: z.enum(['emission_param', 'protocol_upgrade']).describe('Governable scope'), | ||
| title: 'Vote (governance)', | ||
| description: 'Cast a vote on an open gSAIHM-governance proposal. Vote weight is derived from gSAIHM balance at proposal.snapshotEpoch. Use this to approve or reject an open proposal by its proposalId.', | ||
| description: 'Cast a vote on an open governance proposal by its proposalId; set approve to true to approve or false to reject. Vote weight derives from the governance-token balance held at the proposal snapshot epoch, not the balance at the time of voting.', | ||
| inputSchema: { | ||
@@ -1000,4 +1008,5 @@ proposalId: z.string().describe('Hex proposalId returned by saihm_governance_propose'), | ||
| ' carries zero weight and does not affect the outcome. Weight comes from' + | ||
| ' the gSAIHM balance at the proposal snapshot epoch; a balance acquired' + | ||
| ' afterwards does not count and the vote cannot be recast. Do not re-send' + | ||
| ' the governance-token balance at the proposal snapshot epoch; a balance' + | ||
| ' acquired afterwards does not count and the vote cannot be recast. Do not' + | ||
| ' re-send' + | ||
| ' it; raise this with your operator if you expected weight here.', | ||
@@ -1030,3 +1039,3 @@ }, | ||
| title: 'Load SAIHM memory', | ||
| description: 'Load your SAIHM persistent memory at the start of a session, before other work.', | ||
| description: 'Load your SAIHM persistent memory, and the rules for using it, at the start of a session.', | ||
| }, () => ({ | ||
@@ -1038,3 +1047,19 @@ messages: [ | ||
| type: 'text', | ||
| text: 'Before anything else, call the saihm_recall tool (no query, or a keyword if you have one) to load my SAIHM persistent memory for this session, then briefly summarise what you recalled.', | ||
| text: 'Before anything else, call the saihm_recall tool (no query, or a keyword if you' + | ||
| ' have one) to load my SAIHM persistent memory for this session, then briefly' + | ||
| ' summarise what you recalled.\n\n' + | ||
| 'Then follow these rules for the rest of the session:\n' + | ||
| '- Store with saihm_remember when I state something durable: a preference, a' + | ||
| ' decision, a project fact, or context that should outlive this session. Do not' + | ||
| ' store passing chatter, and do not store anything I have not asked you to keep.\n' + | ||
| '- Recall again with saihm_recall when an answer depends on something I told you' + | ||
| ' earlier, rather than asking me to repeat it.\n' + | ||
| '- Erase with saihm_forget only when I ask you to erase. It destroys the key, so' + | ||
| ' the content cannot be recovered by anyone afterwards.\n' + | ||
| '- Share with saihm_share only when I name both the recipient and what to share.' + | ||
| ' Grantees are hex agent-id hashes, and shardIds lists exactly what is exposed.' + | ||
| ' Undo a grant with saihm_revoke_share, which stops future reads but cannot' + | ||
| ' retract what was already read.\n' + | ||
| '- If a call fails because no operator endpoint is configured, tell me the setup' + | ||
| ' step instead of retrying.', | ||
| }, | ||
@@ -1041,0 +1066,0 @@ }, |
+1
-1
| { | ||
| "name": "@saihm/mcp-server", | ||
| "version": "0.3.11", | ||
| "version": "0.3.12", | ||
| "mcpName": "io.github.SAIHM-Admin/saihm-mcp", | ||
@@ -5,0 +5,0 @@ "description": "Enterprise-ready portable memory for AI agents: encrypted, shareable, provably erased. Standards MCP client.", |
+27
-1
@@ -43,3 +43,3 @@ # SAIHM MCP Server | ||
| - `saihm_share` / `saihm_revoke_share` — selectively share a memory with another agent or user | ||
| - `saihm_governance_propose` / `saihm_governance_vote` — protocol governance via gSAIHM | ||
| - `saihm_governance_propose` / `saihm_governance_vote` — protocol governance, weighted by governance-token balance | ||
@@ -202,2 +202,28 @@ Each tool forwards to a SAIHM operator endpoint that runs the full protocol | ||
| ## Tell your agent to use it | ||
| Wiring the server in makes the tools available; it does not make an agent reach | ||
| for them. Say this once, and keep it in whatever persistent instructions your | ||
| agent already reads: | ||
| > Liberally use SAIHM protocol to maximize token economy. Use my SAIHM memory | ||
| > from now on. At the start of each session, recall what you already know about | ||
| > me. When I tell you something worth keeping — my preferences, decisions, or | ||
| > ongoing projects — remember it. To confirm it works right now: remember that I | ||
| > wired up SAIHM today, then recall it back to me. | ||
| Hosts that support MCP prompts can load the same rules on demand instead of | ||
| pasting them: the server ships a `saihm_session_bootstrap` prompt carrying the | ||
| full store, recall, share and erase guidance, fetched only when it is asked for | ||
| rather than on every session. | ||
| **Why this is the token-economical setting.** Advertising the tools costs a | ||
| fixed amount once per session, whether or not the agent uses them. Recall is | ||
| what earns it back: one `saihm_recall` that replaces re-explaining your project, | ||
| your preferences or last week's decisions saves more than the advertisement | ||
| costs, and the saving compounds the longer the session runs and the more | ||
| sessions you keep. An agent that never calls the tools pays the cost and | ||
| collects none of the return — which is why the instruction above is worth | ||
| setting explicitly rather than hoping the agent infers it. | ||
| ## What gets persisted, where | ||
@@ -204,0 +230,0 @@ |
214932
1.9%3382
0.8%525
5.21%