Mnemoverse Memory
Mnemoverse Memory is a hosted MCP server for persistent, cross-tool AI agent memory with outcome-based re-ranking and shared rooms.
Store durable memories (
memory_write): save preferences, decisions, lessons, project facts; optional domain/concepts; may be filtered by an importance gate.Retrieve memories (
memory_read,memory_list_recent): semantic search or newest-first feed, filtered by domain, time bounds, author exclusion, and cursor paging.Improve recall with feedback (
memory_feedback): rate memories helpful (+1) or harmful (-1) to raise or lower future ranking.Inspect memory stats (
memory_stats): total count, domains, learned associations, and average quality scores.Collaborate via shared rooms (
memory_create_room,memory_invite_to_room,memory_join_room,memory_list_rooms): create, invite to, join, and list rooms; use a room address asdomainto read/write shared memory.Explore association graph (
memory_graph): read concept-to-concept edges with weight, valence, and co-activation count.List vault secrets (
vault_list): see aliases and purposes of stored secrets; values are never returned.Use MCP prompts/resources:
recall,save_insight,what_do_you_know,setup_memory; open a saved memory by ID viamemory://item/{memory_id}.
Mnemoverse Memory
Persistent memory for AI agents over MCP. Tell it a recalled memory helped or misled, and it re-ranks what comes back next. Shared rooms let several agents work from one memory. One key or OAuth across Claude Code, Cursor, VS Code and ChatGPT.
@mnemoverse/mcp-memory-server is the MIT-licensed MCP server for the hosted Mnemoverse memory engine.
What is Mnemoverse Memory?
Mnemoverse is a hosted memory engine for AI agents, reached over the Model Context Protocol. Mnemoverse stores what your agents learn — decisions, preferences, lessons — and returns it in any connected tool, so one memory follows you across Claude Code, Cursor, VS Code and ChatGPT with one account: an API key in a local config, or an OAuth sign-in on the hosted endpoint. Mnemoverse re-ranks recall from outcomes: report that a recalled memory helped and a Rescorla-Wagner update on the prediction error raises it, report that it misled and it sinks — a different mechanism from similarity scoring, usable alongside it.
What is open source here, and what is not. This repository, the MCP server, is MIT, and so is the Python SDK. The memory engine they talk to is a hosted service with a free tier. Self-hosting the engine is available on Enterprise plans by agreement, when security or compliance requirements call for it; by default we run it for you.
Related MCP server: memmd-mcp
How it compares
Most agent memory today lives in one of three places. Per-tool instruction files — CLAUDE.md, .cursorrules, AGENTS.md — are versioned and readable, but each copy belongs to one repo and one tool, and nothing follows you to the next window. A vector store behind RAG retrieves by similarity, and similarity never changes because advice helped or misled. Local-first memory servers win on privacy and latency, and ask you to run and update the infrastructure yourself. Mnemoverse is the managed, cross-tool option in that landscape: nothing to deploy, one account everywhere, and ranking that moves with reported outcomes. If you need memory inside your own perimeter, a local-first server is the better choice; this one is hosted by default, with Enterprise self-hosting by agreement.
The consolidation stage of the engine — HDBSCAN clustering with Von Restorff protection, so distinctive memories are not absorbed into the average — is designed in and currently switched off on the hosted service; our docs say so rather than hide it.
⭐ If Mnemoverse saves you from re-explaining context to your agents, star the repo. It helps other builders find it.
Quick Start
No key: the hosted endpoint
If your client signs in over OAuth, you do not need a key at all. Create a free account at console.mnemoverse.com (no credit card), then connect the hosted endpoint.
Claude Code:
claude mcp add -s user --transport http mnemoverse https://mcp.mnemoverse.com/mcpThen run /mcp in a session, select mnemoverse and choose Authenticate.
Cursor, in .cursor/mcp.json:
{ "mcpServers": { "mnemoverse": { "url": "https://mcp.mnemoverse.com/mcp" } } }Claude Desktop, Windsurf, VS Code and ChatGPT: Remote MCP setup. The local server below is the other path: it runs on your machine and reads an API key.
1. Get a free API key
Sign up at console.mnemoverse.com — takes 30 seconds, no credit card.
Check the key before you put it in a config. Both forms ask for the key at a masked prompt and never pass it as a command argument, so it lands neither in your shell history nor in the process list.
macOS, Linux, Git Bash:
printf 'Mnemoverse API key: '; read -rs KEY; echo
printf 'X-Api-Key: %s\n' "$KEY" | curl -s -H @- https://core.mnemoverse.com/api/v1/memory/stats; unset KEYWindows PowerShell 5.1 and PowerShell 7:
$k = [Net.NetworkCredential]::new('', (Read-Host 'Mnemoverse API key' -AsSecureString)).Password
try { (Invoke-WebRequest https://core.mnemoverse.com/api/v1/memory/stats -Headers @{ 'X-Api-Key' = $k } -UseBasicParsing).Content }
catch { if ($_.ErrorDetails.Message) { $_.ErrorDetails.Message } else { (New-Object IO.StreamReader($_.Exception.Response.GetResponseStream())).ReadToEnd() } }; Remove-Variable kThe output contains | What it means |
JSON that includes | The key works. |
| That is the example key from these docs. Create a real one at the console. |
| Not the shape of a key: cut short in the paste, wrapped in quotes, or a different token entirely. |
| The shape is right and no such key exists. Copy it again from the console. |
| The key was revoked and will not work again. Create a new one. |
| No key reached the API: what you entered was empty. |
In the JSON, reason sits inside the details object (details.reason), next to details.keys_url, the console page where keys are created.
2. Connect to your AI tool
The two canonical setups, Claude Code and Cursor. Each writes the key once, at user scope, covering every project. Avoid a per-project config file for this: it lives inside the repository and can be committed with it, and a key belongs outside:
Claude Code — add via CLI:
claude mcp add mnemoverse -s user \
-e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY \
-e MNEMOVERSE_API_URL=https://core.mnemoverse.com/api/v1 \
-- npx -y @mnemoverse/mcp-memory-server@latestOn Windows (PowerShell), paste the same command as one line — PowerShell does not read the \ line continuations:
claude mcp add mnemoverse -s user -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -e MNEMOVERSE_API_URL=https://core.mnemoverse.com/api/v1 -- npx -y @mnemoverse/mcp-memory-server@latestCursor — click to install, or add the JSON below to ~/.cursor/mcp.json, the global config that covers every project. Do not put it in a project-level .cursor/mcp.json: that file lives inside the repository and is committed with it unless you exclude it, and this config holds your key.
The install button carries the placeholder key mk_live_YOUR_KEY, not yours, so the shortest path is to skip the button: add the JSON below to ~/.cursor/mcp.json, merging it with any servers already there, and put your own key in place. Get one at console.mnemoverse.com. If you did click the button, edit the same key in the mcp.json it wrote; Cursor keeps MCP environment values in that file, not in a settings form. Until the key is real the server starts and lists its tools, but every tool call is refused.
{
"mcpServers": {
"mnemoverse": {
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}VS Code — the VS Code extension signs in through the browser and needs no key; that's the default path. In VS Code's non-interactive Agent Host mode, servers that prompt for inputs like this one are not started; for unattended use there, put the key in the environment of the process that launches VS Code instead. To wire the MCP server directly instead, add this to .vscode/mcp.json (note: VS Code uses servers, not mcpServers). Never put a literal mk_live_ key in that file — it's committed with the repo. The inputs entry below prompts for the key instead: VS Code masks what you type and stores it in its own secret storage, not in the file:
{
"inputs": [
{
"type": "promptString",
"id": "mnemoverse-api-key",
"description": "Mnemoverse API key (starts with mk_live_). Optional to install and inspect — the server starts and lists its tools without a key; every actual tool call requires one. Get one free in ~30s at https://console.mnemoverse.com",
"password": true
}
],
"servers": {
"mnemoverse": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "${input:mnemoverse-api-key}",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}Windsurf — add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"mnemoverse": {
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}More MCP clients — same server, different config file:
Zed — add to ~/.config/zed/settings.json (Zed uses context_servers, and "source": "custom" is required):
{
"context_servers": {
"mnemoverse": {
"source": "custom",
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}JetBrains (AI Assistant) — Settings → Tools → AI Assistant → Model Context Protocol (MCP), then paste:
{
"mcpServers": {
"mnemoverse": {
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}Cline — MCP Servers → Configure (or edit cline_mcp_settings.json). Cline reads env values literally, so paste your real key — not a ${VAR} reference:
{
"mcpServers": {
"mnemoverse": {
"command": "npx",
"args": [
"-y",
"@mnemoverse/mcp-memory-server@latest"
],
"env": {
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY",
"MNEMOVERSE_API_URL": "https://core.mnemoverse.com/api/v1"
}
}
}
}Continue — add ~/.continue/mcpServers/mnemoverse.yaml (Continue uses YAML):
mcpServers:
- name: mnemoverse
command: npx
args:
- "-y"
- "@mnemoverse/mcp-memory-server@latest"
env:
MNEMOVERSE_API_KEY: "mk_live_YOUR_KEY"
MNEMOVERSE_API_URL: "https://core.mnemoverse.com/api/v1"Why
@latest? Barenpx @mnemoverse/mcp-memory-serveris cached indefinitely by npm and stops re-checking the registry. The@latestsuffix forces a metadata lookup on every Claude Code / Cursor / VS Code session start (~100-300ms), so you always pick up new releases.
⚠️ Restart your AI client after editing the config. MCP servers are only picked up on client startup.
3. Try it — 30 seconds to verify it works
Paste this in your AI chat:
"Remember that my favourite TypeScript framework is Hono, and please call
memory_writeto save it."
Your agent should call memory_write and confirm the memory was stored.
Then open a new chat / new session (this is the whole point — memory survives restarts), and ask:
"What's my favourite TypeScript framework?"
Your agent should call memory_read, find the entry, and answer "Hono". If it does — you're wired up. Write whatever you want next.
If it doesn't remember: check that the client was fully restarted and the config has your real mk_live_... key, not the placeholder.
⭐ If the second session remembered, star the repo. It helps other builders find it.
Tools
Tool | What it does |
| Store a memory — insight, preference, lesson learned |
| Search memories by natural language query (optional recency ordering, time bounds, author exclusion) |
| List newest memories first — no query; |
| Rate memories as helpful or not (improves future recall) |
| Check how many memories stored, which domains exist |
| Create a shared memory room; its address works as a |
| Mint an invite (code + link) for a room you own; single-use unless |
| Join a shared room with an invite code ( |
| List rooms you own or joined, with each room's address to use as |
| Read the association edges around given concepts — weight, outcome valence, co-activation count |
| List Vault secrets by alias and purpose — the secret value is never returned |
Prompts
Four named prompts for clients that show MCP prompts as commands (Claude Code as /mcp__mnemoverse__<name>). None of them calls the API itself: three ask the model to use the tools above, and setup_memory hands you rules for your own agent.
Prompt | Arguments | What it asks for |
|
| Search memory for a topic with |
|
| Store an insight with |
|
| A briefing from |
| optional | Memory rules for CLAUDE.md, AGENTS.md, Cursor rules or your chat preferences, and where they go, so your assistant checks and saves memory without being reminded |
Resources
memory://item/{memory_id} opens one saved memory by its id (the id: line of a memory_read result) for clients that attach MCP resources. It returns the memory's memory_id, content and domain as JSON. It reads your own store only: a memory read from a shared room cannot be opened by id.
Tool surface stability
tools/list is frozen per released version, so a client can save the list it
saw and diff it against what the server serves today, by version.
Within a PATCH (x.y.Z): tool names, argument schemas and the
annotationsobject of every tool (title,readOnlyHint,destructiveHint,idempotentHint,openWorldHint) do not change. Only text may: descriptions and what a tool returns, as the CHANGELOG rules state.Within a MINOR (x.Y.0): tools and annotation fields may be added, never removed or renamed, and no declared annotation field disappears or flips silently. Every addition has a line in the CHANGELOG under that version. A MINOR may also add an output schema (
outputSchema, withstructuredContentreturned alongside the same text) to a tool that did not have one; once declared, that schema's fields are add-only under this same rule. Where this server's output schema deliberately differs from the hosted connector's, the CHANGELOG entry says so; today that ismemory_idin every output schema, a plain string here and a GUID-validated string there (this package's ids are opaque);memory_list_recent'snext_cursor, optional here (absent when the service sent a continuation token this client will not pass on) and required there;memory_stats, which carries five optional fields (episodes,prototypes,hebbian_edges,avg_valence,avg_importance) the connector's schema does not declare; the room tools (memory_create_room,memory_invite_to_room,memory_join_room,memory_list_rooms), where several fields the connector marks required are optional here (name,scope,already_member, and the invite'scode,scope,room_addressandexpires_at), because a value core did not send is an honest outcome here rather than a placeholder; andmemory_list_roomsandvault_list, which drop a row with no usable identity (room_id,address,role;alias,context) from the data, reported once on stderr, instead of emitting empty strings into required fields.Removing or renaming a tool or a tool's input parameter, or dropping or renaming a declared annotation field, is announced one MINOR ahead: the tool (or parameter) stays, its description says
deprecated since x.y, removed in x.z, and the change lands only in the announced version, with its CHANGELOG line. A renamed parameter is accepted under both names until then (0.11 renamedmemory_feedback'satom_idstomemory_ids; the old name was removed in 0.13, as announced after 0.12 shipped sooner than the first announcement assumed). A rename is announced by naming both the old and the new name; the version pair alone does not say what a client should look for. Because a MINOR may add a field but not remove one, a renamed annotation field is declared under both names until the announced version.Any difference between two servers of the same version is a bug. Report it with both
tools/listoutputs. One exception, by configuration: a server built on the/sharedentry point may ask for its own noun in the three descriptions that name the server (wording.serverNoun, below), which changes those three description strings and nothing else; tool names, input and output schemas and annotations never vary by configuration.
The list above is the current surface: eleven tools, each declaring all four hints.
The hosted connector at mcp.mnemoverse.com/mcp serves the same surface, registered
from this package at the version it pins. The list itself is published as
tools.json, generated from the built server (name, title,
description and annotations per tool); the test suite and the release workflow
fail when it does not list what the server registers, and the .mcpb manifest's
tool list is derived from it.
If the hosted connector stops answering in a session. A client can keep showing the connector as connected while every call in that session fails with "not connected". Reconnecting it on claude.ai does not revive a session that is already stuck; reconnect from inside the session instead (in Claude Code, /mcp, then sign in again). Meanwhile this local server, set up with an API key from the same account as in the Quick Start, reaches the same memory and does not depend on that session's sign-in.
Building a second MCP server on this package
@mnemoverse/mcp-memory-server/shared is the entry point another server registers these same tools from, instead of keeping its own copy (ADR-025, mnemoverse-core). It exports registerMemoryTools/registerMemoryPrompts/registerMemoryResources, the three typed error classes (ApiError, NetworkError, UnreadableBodyError), MAX_RESULT_CHARS/capResult, and two optional dependencies a hosted deployment injects to speak in its own voice: wording (its own server noun and error vocabulary, including an OAuth mode under which no 401 or 403 explanation names an API key) and writeAuthor (vouching for the end user behind a write). See docs/shared.md for the full contract.
Use cases
The pattern that pays off first is cross-tool continuity: a decision made while pairing in Claude Code is there when you open Cursor an hour later, and the preference you stated in VS Code holds in a ChatGPT session that evening. Teams use shared rooms the same way — one place where an agent's lessons about a codebase accumulate instead of being re-taught per seat. And because recall re-ranks from feedback, the memories that keep proving useful surface first, which matters once a store grows past what anyone curates by hand.
Concrete things worth writing:
User preferences: "I use dark mode", "I prefer Tailwind over CSS modules"
Project context: "This project uses PostgreSQL + Prisma", "Deploy to Railway"
Lessons learned: "Always run tests before push on this repo"
Decisions made: "We chose REST over GraphQL because of caching simplicity"
People & roles: "Alice is the designer, Bob owns the API"
Past mistakes: "Don't deploy on Fridays — learned this the hard way"
Universal Memory
The same API key works across all tools. Write a memory in Claude Code — read it in Cursor. Learn something in VS Code — your GPT Custom Action knows it too.
┌── Claude Code (this MCP server)
├── Cursor (this MCP server)
Mnemoverse API ──├── VS Code (this MCP server)
(one memory) ├── GPT (Custom Actions)
├── Python SDK (pip install mnemoverse)
└── REST API (curl)Configuration
Env Variable | Required | Default |
| For every tool call — the server starts and lists its tools without one | — |
| No |
|
Research behind it
The retrieval model is published: arXiv:2603.08965, accepted at the GRAAI workshop at IEEE WCCI 2026 — it establishes the abstraction-discovery method the memory model builds on. No benchmark figures appear in this README, ours or anyone's: numbers will come with a reproducible run to stand behind, not before.
Links
Setup and reference
Background reading
Memory MCP servers compared — thirteen shipping options, with pricing and registry presence
How to choose a memory MCP server — the five questions that narrow the field
What AI agent memory is — the category explained
Is this a vector database? — what makes a memory layer different
Shared memory for multi-agent systems — how Rooms work and when to use them
Other ways to install it
The same memory, packaged for hosts that prefer a plugin or an extension over an MCP config block. How each one connects and authenticates differs, so the line below says which is which rather than claiming one flow for all of them.
Claude Code plugin — remote endpoint over MCP with an OAuth sign-in, no key to paste. Bundles the
agent-memory-disciplineskillclaude plugin marketplace add mnemoverse/claude-plugin claude plugin install mnemoverse@mnemoverseCursor plugin — same remote endpoint, same sign-in
Gemini CLI extension — same remote endpoint.
gemini extensions install https://github.com/mnemoverse/gemini-extensionVS Code extension (VS Code Marketplace, Open VSX, source) — signs in through the browser, with pasting a key kept as a fallback command
Desktop extension:
manifest.jsonin this repository is an MCPB manifest. This one is different from the four above: it runs the server as a localnodeprocess and readsMNEMOVERSE_API_KEYfrom the extension settings rather than calling the hosted endpoint. The packaged.mcpbships with each release
Standing rules, separate from this server
agent-memory-discipline — when an agent should recall before acting and save afterward. CC0, backend-neutral, works against any memory store rather than this one. It carries its own marketplace manifest under
.claude-plugin/.awesome-agent-memory — a curated index of the category, CC0, including the servers this one competes with
Project
Privacy Policy
This server sends to the Mnemoverse API (core.mnemoverse.com), authenticated with your API key, what a tool call carries — and nothing else it can see. It does not read your AI client's conversation history, your local files, or anything you don't pass to a memory_* / vault_* tool. Stored memories live under your account; Mnemoverse never sells them and never shares them on its own. The one sharing path is the one you create yourself: inviting someone to a shared room grants their assistant access to that room's memories, bounded by the invite's scope.
What each tool sends:
Tool | Data sent |
| the |
| the |
| the feed filters: |
| the |
| the room |
| the |
| the invite |
| the |
| no request body — authenticated GETs |
One thing goes out that you did not explicitly request: since 0.8.1, when a search or feed comes back empty, the server sends one or two authenticated read-only GET probes (/memory/rooms and/or /memory/stats) so the empty answer can say what it did not cover. The probes carry your API key and nothing else, change no stored state, and are disclosed in the CHANGELOG.
Privacy Policy | |
Retention & deletion | correct a wrong or stale memory by writing a fresh one; deletion is an administrative operation on the REST API, not exposed through this MCP server |
Contact |
License
MIT © Mnemoverse
Available Tools
11 toolsmemory_create_roomAInspect
Create a SHARED memory room — a space OTHER people's assistants can read, and write too when their invite granted read_write (the default scope), across Claude/ChatGPT/Cursor. Use when the user wants to share context or collaborate with someone else (e.g. 'make a room for me and my teammate'). Returns the room's address; pass that address as the domain on memory_write/memory_read to use it, and on memory_list_recent to catch up on what others added. People join through an invite minted with memory_invite_to_room.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Room name, unique within your account (e.g. 'launch-team'). | |
| description | No | Optional description of the room. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The room name as stored. |
| address | Yes | Domain address (xroom:<id>); pass as `domain` on read/write. |
| room_id | Yes | The room's id (room_...); pass to memory_invite_to_room. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false). The description adds the substantive traits: the room is shared/cross-vendor (Claude/ChatGPT/Cursor), the default invite scope is read_write, and it returns an address to be reused as the `domain` argument elsewhere. It does not address name-collision behavior for a non-idempotent create, which leaves one gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the definition of the room before the usage trigger and the follow-on tools. It is a long sentence chain but each clause carries distinct information (scope, cross-platform reach, default invite scope, return value, next steps); minor tightening is possible but nothing is fat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so line-by-line return documentation is unnecessary, yet the description still tells the agent what the address is for. Combined with the invite/read/write follow-on pointers, an agent has enough to create and then use a room; only edge cases (duplicate names, permissions to create) are unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 `name` (unique within account) and the optional `description`; the baseline is 3. The description adds no additional meaning about the two parameters themselves (the uniqueness rule it references is already in the schema).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Create a SHARED memory room') and immediately distinguishes it from siblings by defining what a room is (a space other people's assistants can read/write). An agent can tell it apart from memory_list_rooms, memory_join_room, and memory_invite_to_room without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger condition and a concrete user-utterance example ('make a room for me and my teammate'), plus points to memory_invite_to_room as the way people join. It stops short of stating when NOT to create a room or how it differs for solo use, so it is clear context rather than full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_feedbackAInspect
Report whether memories returned by memory_read were actually helpful. This is a learning signal, not a log: positive feedback raises a memory's ranking so it surfaces faster next time (across all of the user's tools), negative feedback lowers it so other memories out-rank it — nothing is erased and nothing decays with time. Use it after an answer that relied on or rejected memories from memory_read: pass the ids of those memories as memory_ids, with outcome 1 when they helped and -1 when they were wrong or stale. For memories read from a shared room, also pass that room's address as domain; your own memories need no domain. A read-only room member cannot rate the room's memories.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Only for memories read from a shared room: that room's address (xroom:...), exactly as you read it. Omit it for your own memories, which are rated by id alone. | |
| outcome | Yes | How helpful was this? 1.0 = very helpful, 0 = neutral, -1.0 = harmful/wrong | |
| memory_ids | Yes | IDs of the memories to rate, the `id:` line of each memory_read result. |
Output Schema
| Name | Required | Description |
|---|---|---|
| avg_valence | No | Average valence of the rated memories after the update. Reported as 0 in an asynchronous acknowledgement, where the real value is computed later — a 0 here is therefore not evidence of a neutral outcome. |
| updated_count | Yes | How many memories the service reports it applied the rating to. Processed synchronously this is the real count of memories that existed and were updated; processed asynchronously it is a best-effort ACCEPTED-count estimate — the number of IDs submitted — and the authoritative number is not known until the background worker runs. Zero means no submitted ID matched in the service's resolved request scope. |
| coactivation_edges | No | Number of links between query concepts and result concepts that this rating changed. This server does not send query_concepts, so live calls through this tool report 0; asynchronous acknowledgements also report 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=false and destructiveHint=false; the description goes well beyond them by explaining the actual effect (positive raises ranking across all the user's tools, negative lowers it so other memories out-rank it), the non-destructive boundary ('nothing is erased and nothing decays with time'), and the permission limitation. No statement conflicts with the annotation set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct load: purpose, effect model, and invocation rules. The purpose and ranking consequence are front-loaded before the edge cases, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 no explanation. The description covers the mutation effect, the value convention, the conditional domain argument, and the permission edge case, leaving nothing an agent needs in order to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all three parameters; the baseline would be 3. The description adds situational meaning by tying memory_ids to 'the ids of those memories' just consumed and restricting domain to shared-room addresses read as xroom, which helps the agent supply them correctly in context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Report whether memories returned by memory_read were actually helpful') and immediately frames the tool's role as a learning signal rather than a log, which cleanly separates it from siblings like memory_read and memory_write. An agent can identify this as the ranking-feedback tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use conditions ('after an answer that relied on or rejected memories from memory_read'), the exact value convention for outcome (1 helpful, -1 wrong/stale), and a conditional rule for domain (shared-room reads only). It even names an exclusion: a read-only room member cannot rate the room's memories.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_graphARead-onlyIdempotentInspect
Reads the association edges around given concepts: which concepts the memory has linked together, with each link's weight, outcome valence and co-activation count. Use to inspect what a memory store has learned or to explain why a read expanded to a concept. Reads your own graph, or a shared room's when its address is passed as domain; any other domain value has no effect. At depth 2 or 3 the engine drops edges below weight 0.05 unless min_weight is set. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Hops to expand from the seeds (1-3, default 1). At depth 2 or 3, if min_weight is omitted the engine floors edge weight at 0.05 at EVERY hop — including the first — so a hub concept cannot fan out across the whole store before limit applies; pass min_weight explicitly (0 included) to see every edge anyway. | |
| limit | No | Max edges to return (1-500, default 100 — mirrors memory_read's top_k bounds). | |
| seeds | Yes | Concepts to center the graph on (1-20, each ≤200 chars, non-blank) — e.g. ['deploy', 'staging']. An unrecognised concept simply contributes no edges; it is not an error. | |
| domain | No | Read a shared room's graph instead of your own: pass that room's address (e.g. 'xroom:room_01ABC'). Find room addresses with memory_list_rooms. Unlike memory_read, any OTHER value has no effect here — the association store has no domain column, so a plain domain name behaves exactly like omitting this field. | |
| min_weight | No | Only include edges at or above this weight (≥ 0). Omit for no floor at depth 1; at depth 2/3 the engine applies its own 0.05 floor when this is omitted (see depth) — pass 0 to see every edge at every depth. |
Output Schema
| Name | Required | Description |
|---|---|---|
| edges | Yes | Association edges found within the requested depth. |
| nodes | Yes | Concepts touched by edges below. A seed with no surviving edge (unrecognised concept, or every edge fell below the weight floor) is not listed. |
| truncated | Yes | True when a per-hop server cap or limit cut the walk short — the store may hold more edges than are reported here. |
| min_weight_applied | Yes | The weight floor actually used at every hop: your min_weight when you set one (0 included); otherwise 0.05 from depth 2, or 0 at depth 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description reinforces 'Read-only.' Beyond that it discloses genuinely non-obvious behavior: the depth 2/3 weight floor of 0.05 applied at every hop, and the fact that a non-room domain value silently has no effect. It stops short of describing result ordering or truncation semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then scope, then caveats, in roughly four dense sentences with no filler. It is information-rich but borders on restating schema detail, slightly reducing economy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return shape need not be explained, and annotations cover the safety profile. The description fills the remaining gaps an agent needs: the shared-room domain exception, the cross-hop weight floor, and the non-error handling of unrecognized seeds.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters are already documented in the schema, including the depth/min_weight interaction and the domain address format. The description restates this at a high level rather than adding syntax or semantics the schema lacks, which is the expected baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Reads the association edges around given concepts') and enumerates what each edge carries (weight, outcome valence, co-activation count). It is distinguishable from the closer sibling memory_read, which is referenced by role ('explain why a read expanded to a concept').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives two concrete use cases — inspecting what the store learned and explaining an expansion — which implicitly contrasts with memory_read. However, it never states when NOT to use this tool, e.g. when a flat top_k read is sufficient, so the routing is clear but incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_invite_to_roomAInspect
Mint an invite for a room you own and get a ready-to-forward message. An invite is single-use by default; pass max_uses to let several people join with the same one. The user sends that message to the person they want to add (any messenger); the recipient opens the link or tells THEIR assistant the code to join. Use when the user asks to invite someone to a room they own, including one just created with memory_create_room.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | Role the invitee gets — 'read' or 'read_write' (default read_write). | |
| room_id | Yes | The room's id (room_...), from memory_create_room. | |
| max_uses | No | How many people may join with this invite (default 1, single-use). | |
| expires_in_days | No | Days until the invite expires (default 7). |
Output Schema
| Name | Required | Description |
|---|---|---|
| code | No | The invite code (mnvr_...). Single-use by default, with a configurable use limit. Shown once. |
| scope | No | Role the invitee will get. |
| join_url | No | Landing URL the invitee can open to join. |
| expires_at | No | ISO 8601 expiry, or null. |
| room_address | No | The room's domain address (xroom:<id>). |
| share_message | Yes | Ready-to-forward invite text. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only carry the generic mutation profile (readOnlyHint=false, idempotentHint=false), so the description must add the real behavior — and it does: invites are single-use by default, max_uses lets one invite admit several people, and it explains the out-of-band delivery flow (user forwards the message, recipient either opens the link or dictates the code to their own assistant). That is exactly the kind of non-obvious semantics 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action is front-loaded in the first sentence, followed by invite lifetime semantics and then the routing condition. Four sentences, each carrying distinct information, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a small mutation tool with an output schema (so return shape needn't be described) and full schema coverage, the description supplies the missing pieces: the invite artifact, its default single-use behavior, and the human-in-the-loop forwarding step. Nothing an agent needs to invoke it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all four parameters, setting a baseline of 3. The description still adds meaning about max_uses by framing the default as 'single-use' and the override as letting 'several people join with the same one,' which clarifies intent rather than restating the field. scope and expires_in_days are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Mint an invite for a room you own') plus the concrete deliverable ('ready-to-forward message'), which separates it cleanly from memory_join_room and memory_create_room. An agent can pick this tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger condition ('Use when the user asks to invite someone to a room they own') and connects it to memory_create_room for the just-created-room case. It does not state when not to use it, e.g. that the recipient side belongs to memory_join_room, so it stops short of a full when/when-not/alternatives treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_join_roomAIdempotentInspect
Join a shared memory room using an invite code (starts with 'mnvr_'). Use when the user pastes an invite code or says something like 'join room with code ...'. The result gives the room's address, which is the domain for reading the shared room with memory_read, and tells you what you may do with it: memory_write to that address is only allowed when your membership scope is read_write; a read-only membership has that write refused; and when the server does not report a scope, whether memory_write would succeed is stated as unknown rather than promised either way.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | The invite code (mnvr_...). |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The room name. |
| scope | No | Your role in the room ('read' | 'read_write'). |
| address | Yes | Domain address (xroom:<id>); pass as `domain` on read/write. |
| room_id | Yes | The room's id (room_...). |
| next_steps | Yes | How to use the room now. |
| already_member | No | True if you were already a member (no-op join). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only carry readOnlyHint/idempotent/destructive flags; the description adds real behavioral context beyond them: the result yields the room's address used as `domain`, and it explains that memory_write succeeds only with read_write scope, is refused for read-only membership, and is reported as unknown when the server gives no scope. This is honest, non-contradictory disclosure that an agent could not infer from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and trigger are front-loaded, and every sentence carries information. The final scope sentence is long and clause-heavy, but its content (write permission semantics) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate return fields, yet it still explains the key returned address and its role as the `domain` for memory_read/memory_write, plus the membership-scope outcomes. Nothing needed to invoke or chain this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is documented there, including the 'mnvr_...' format. The description repeats the same prefix hint but adds no syntax or validation detail beyond 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Join a shared memory room') plus the required credential ('invite code, starts with mnvr_'), which cleanly separates it from siblings like memory_create_room and memory_invite_to_room.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger conditions ('use when the user pastes an invite code or says join room with code ...') and names the downstream tools (memory_read, memory_write) this enables. It stops short of naming an alternative tool or an explicit when-not-to-use case, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_list_recentARead-onlyIdempotentInspect
List the NEWEST memories first — no search query needed. Semantic search answers 'what do I know about X'; this answers 'what happened lately': resuming work after a break, catching up on a shared room ('any new messages?'), or reviewing what was saved recently. Pass since (your last-seen time) to get only what's new, and page through older entries with the returned cursor. Complete by construction WITHIN ONE SCOPE — nothing is skipped there, unlike a semantic search. A page is also bounded by SIZE, so a page of long entries comes back shorter than limit and hands you a cursor for the rest — nothing is dropped, and following the cursor is how you get it. To catch up on a shared room you MUST pass its address as domain: rooms are separate stores and an unscoped call never covers them.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Most entries per page (default: 20). Newest first. ⚠️ A CEILING, not a promise: the page is ALSO bounded by size, so a page of long entries stops early and returns a cursor for the rest. In rooms whose entries run long, ask for 5–10 — a large `limit` there buys nothing the size budget will not take back, and costs round trips. | |
| since | No | Only entries created at/after this ISO-8601 instant (naive = UTC) — your novelty watermark. | |
| until | No | Only entries created at/before this ISO-8601 instant (inclusive). Pair with `since` to read a closed window — 'what happened on Monday' — instead of paging back from now. | |
| cursor | No | Opaque cursor from a previous page's 'More older entries exist' line — continues the listing without skips or duplicates. | |
| domain | No | Restrict to one domain. REQUIRED to read a shared room — pass its address ('xroom:room_01ABC'), because rooms are separate stores that an unscoped feed does NOT cover. Omit only when you mean your own domains. Room addresses come from memory_list_rooms. Room entries are often long — a room feed usually reaches its size budget after a handful of them, so expect to page (see `limit`). | |
| exclude_author | No | Drop entries written by this author PRINCIPAL. ⚠️ NOT USABLE FROM HERE YET — the principal is never shown in these results, so there is no value you can get through this tool; a guess like 'me' filters nothing, silently. Same caveat as on memory_read. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | Entries newest-first (creation time descending). |
| next_cursor | No | Pass back as cursor for the next (older) page; null = listing complete. Absent when the service sent a continuation token this client will not pass on; the text then says the token could not be displayed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and idempotent, and the description adds genuinely useful behavioral context: pages are complete within a scope, size-bounded pages can return fewer than `limit`, cursors are required to avoid dropped entries, and rooms are separate stores. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded: the core action appears in the first sentence, and every caveat earns its place by either explaining a consequence or a required condition. Warnings such as size budgeting and room separation are actionable rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers everything needed to invoke correctly: when to use it, when to scope by domain, how paging works, and where room addresses come from memory_list_rooms. Since an output schema exists, the lack of return-format explanation is not a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even with 100% schema coverage, the description adds meaning beyond the schema: `since` is framed as a novelty watermark, cursors continue listings without skips/duplicates, `limit` is a ceiling affected by page size, and `domain` unlocks shared rooms. The schema already documents syntax well, and the description reinforces behavior around it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the exact behavior—lists the newest memories first—and immediately distinguishes itself from semantic search by contrasting 'what do I know about X' with 'what happened lately.' This also cleanly separates it from sibling tools like memory_read and memory_list_rooms.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit use cases (resuming work, catching up on a shared room, reviewing recent activity), tells when to pass `since`, and when `domain` is mandatory. It even specifies the exclusion condition: an unscoped call never covers rooms, so an agent knows exactly when to supply the room address.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_list_roomsARead-onlyIdempotentInspect
List the shared memory rooms you can use — the ones you OWN plus the ones you've JOINED — each with the address to pass as domain on memory_read, and on memory_write too where your membership scope is read_write; a read-only membership has that write refused. Use this to RE-FIND a room in a new session (e.g. 'what rooms do I have?', 'resume the room with my teammate') instead of having to create or re-join it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| rooms | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds genuinely new behavior: which rooms are returned, that the returned address feeds the `domain` argument on memory_read/memory_write, and that read-only membership causes writes to be refused. Return value shaping isn't described, but the key membership caveat is.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense sentence that front-loads the core scope (owned + joined) and then the usage rationale. Every clause earns its place, though the em-dash interjection about read_write scope makes it slightly heavy for a list tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-format explanation is not required, yet the description still conveys the practically important bit of the output (the address for use as `domain`). For a zero-param, read-only list tool, nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description's mention of the `domain` address is output-to-other-tools mapping rather than input semantics, but it adds useful cross-tool meaning without overloading the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (list shared memory rooms) and immediately scopes it to the two membership sources (OWNED + JOINED). Clearly differentiates from siblings like memory_create_room and memory_join_room by framing this as the discovery operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('RE-FIND a room in a new session') and when not to (instead of having to create or re-join it), giving concrete trigger phrasings. The alternative tools are implied by name and purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_readARead-onlyIdempotentInspect
Search long-term memory for user preferences, past decisions, project setup, people, or earlier context. The memory persists across sessions and across every AI tool the user has connected (Claude, ChatGPT, Cursor, VS Code). It applies when an answer may depend on something from an earlier session or another tool; it is not needed for general world knowledge. Returns matches ranked by relevance (or newest-first with order_by: 'recency'); each result carries an id; after the answer, memory_feedback takes these ids to record which memories helped. A wrong or stale memory is corrected by writing a fresh one with memory_write, not by deleting it.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural-language description of what you're looking for, e.g. 'database choice for the API' or 'user's preferred testing framework'. | |
| since | No | Only memories created at/after this ISO-8601 instant (naive = UTC) — e.g. your last-seen watermark in a shared room. | |
| top_k | No | Requested number of results (default: 5, what this server asks for when you omit it; the engine's own default of 10 never applies, because the field is always sent). ⚠️ Not a hard cap: association expansion can return MORE than this, and the relevance floor can return fewer — raising it does not reliably widen the result set. For a complete, exactly-bounded listing use memory_list_recent instead. | |
| until | No | Only memories created at/before this ISO-8601 instant. | |
| domain | No | Restrict the search to one domain namespace (e.g. 'project:acme'). Omitting it searches your OWN domains — it does NOT include shared rooms, which are separate stores: to search a room, pass its address here (e.g. 'xroom:room_01ABC'). Find room addresses with memory_list_rooms. | |
| order_by | No | 'relevance' (default) = ranking order. 'recency' = the matched set re-sorted newest-first. For a complete newest-first feed with no search at all, use memory_list_recent instead. | |
| exclude_author | No | Drop memories written by this author PRINCIPAL — the server-side identity. ⚠️ NOT USABLE FROM HERE YET: the principal is not shown in these results, so there is no value you can obtain through this tool, and a guess like 'me' silently matches nothing and filters nothing. Only pass it if your system knows the exact principal from elsewhere (e.g. the REST API). |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | Matching memories, ordered per order_by. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), yet the description adds substantive behavior: cross-session/cross-tool persistence, relevance ranking with a recency re-sort option, per-result ids, and the fact that feedback and correction flow through memory_feedback and memory_write rather than deletion. That is real context beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then when-to-use, then return shape, then follow-up tools — a sensible ordering with no filler. It is on the long side for a single paragraph, but nearly every clause carries decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter search tool with full schema coverage, an output schema, and safety annotations, nothing an agent needs to invoke it correctly is missing. The description also covers the read-then-feedback lifecycle that spans several sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 query, since, top_k, domain, order_by and the unusable exclude_author. The description restates order_by recency and the relevance ranking but adds no syntax or format meaning beyond 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search long-term memory') and enumerates the content types it covers (preferences, decisions, project setup, people, earlier context). The scope 'persists across sessions and every connected AI tool' makes it trivially distinguishable from siblings like memory_list_recent or memory_graph.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives the triggering condition ('an answer may depend on something from an earlier session or another tool') and an exclusion ('not needed for general world knowledge'). It also routes two adjacent workflows to alternatives: memory_list_recent for complete bounded listings and memory_write for correcting a stale memory.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsARead-onlyIdempotentInspect
Get an overview of the stored memory: total count, the number of learned concept associations, the list of domains, and average quality scores. This memory is shared across all AI tools the user has connected to Mnemoverse. Use it to orient yourself, to confirm the exact domain name before writing to it, or when the user asks what you remember. Read-only — changes nothing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| domains | Yes | User-defined memory domains. |
| episodes | No | Number of individual memories (not merged into a summary). |
| prototypes | No | Number of summary memories merged from several individual ones. Consolidation is not running on the hosted service, so this count does not currently grow. |
| avg_valence | No | Average valence of stored memories: how well recalls turned out, on a scale from -1 to 1. |
| memory_count | Yes | Number of saved memories. |
| hebbian_edges | No | Number of learned concept-to-concept associations; memory_graph reads them. |
| avg_importance | No | Average importance of stored memories, on a scale from 0 to 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and idempotentHint=true, so 'Read-only — changes nothing' is reinforcement rather than new information. However, the claim that the memory is shared across all connected AI tools is a genuinely useful scope disclosure not present in any structured field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then scope, then usage, then safety — a sensible order. Three sentences with little waste, though the closing 'Read-only — changes nothing' repeats what the annotations already certify.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema and full annotation coverage, the description supplies everything an agent needs: what the call returns, whose data it reflects, and when it is worth calling. No gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. The description correctly adds background on what the shared store is, which is the only meaningful 'parameter-like' context available for a no-arg call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get an overview of the stored memory') and enumerates exactly what the overview contains: total count, concept associations, domains, average quality scores. It is unambiguous within the sibling set, though it never names a sibling like memory_read or memory_list_recent to draw the boundary explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives three concrete triggers: orienting yourself, confirming the exact domain name before writing, and answering 'what do you remember'. That is clear when-to-use guidance, but it offers no exclusion or explicit alternative (e.g. use memory_read when you need the raw contents).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_writeAInspect
Store a long-term memory that persists across sessions and across every AI tool the user has connected to Mnemoverse (Claude, ChatGPT, Cursor, VS Code). Suited to durable information: a stated preference, a decision, a fact about people, roles or project setup, a lesson learned; transient chatter that only matters this turn does not belong here. Never store passwords, API keys, payment data, MFA codes, government IDs, or health records. Behavior: an importance gate may filter low-value writes, so the result tells you whether the memory was stored or filtered. Write content as a self-contained statement that still makes sense when recalled out of context.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme'). Matched byte-for-byte — a leading space, a different case, or an invisible character opens a SEPARATE, permanent store, so reuse an exact name from memory_stats rather than retyping one. To write into a shared room, pass its address here instead (e.g. 'xroom:room_01ABC'). Find room addresses with memory_list_rooms. | |
| content | Yes | The memory to store as a self-contained statement, e.g. 'User prefers TypeScript strict mode' or 'Decided to deploy the API on Cloudflare Workers (2026-06)'. | |
| concepts | No | Key concepts for linking related memories (e.g. ['deploy', 'friday', 'staging']) |
Output Schema
| Name | Required | Description |
|---|---|---|
| reason | No | The memory service's own explanation of this outcome, quoted as sent — when stored is false this is the ONLY statement of WHY, e.g. "Below importance threshold (0.047 < 0.1)". Ordinary text is preserved exactly; only control, bidi, zero-width, and repeated-whitespace characters are normalized before display, and the value is capped at 400 characters. Absent when the service sent no explanation, or when nothing remains after that normalization. |
| stored | Yes | Whether the memory passed the novelty gate and was stored. |
| memory_id | Yes | Identifier of the stored memory, or null when it was not stored. |
| importance | No | Novelty score for this write (0-1): how much it adds over the nearest memories already saved in the same domain. Outside shared rooms, a write that scores below the service's importance threshold is not stored, and `reason` says why when the service sends one. The score is approximate and can read lower for non-English text. It is not a verdict on whether the memory was worth keeping. Absent when the service sent no score. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly=false, destructive=false, idempotent=false. The description adds meaningful behavior beyond that: an importance gate may silently filter low-value writes and the response reports stored vs filtered, plus a hard prohibition list (passwords, keys, payment, MFA, IDs, health records). This is exactly the context an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: purpose first, then suitability, then prohibitions, then behavior. Every sentence earns its place, though the multi-clause structure is heavier than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so returns need not be described, yet the description still flags that the result signals stored-or-filtered. Combined with privacy constraints and content-quality guidance, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 for `content` — it must be a self-contained statement that survives recall out of context — which the schema does not state. Domain/concepts semantics are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (store) and resource (long-term memory) plus scope: persistence across sessions and across every connected AI tool. This clearly separates it from read/list/stats siblings like memory_read and memory_list_recent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit inclusion criteria (stated preference, decision, fact, lesson learned) and an exclusion (transient chatter that only matters this turn). It does not name an alternative tool, but no sibling offers competing write semantics, so routing guidance is effectively complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_listARead-onlyIdempotentInspect
List the secrets stored in your Mnemoverse Vault — by ALIAS and purpose only; the secret VALUE is never returned or shown to you, and no tool on this server returns it. Use this to check WHICH secrets the user has stored and under what alias (e.g. the user says 'do I have a GitHub token saved?'). Only YOUR account's secrets are listed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| secrets | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, destructiveHint), the description adds a critical behavioral guarantee: 'the secret VALUE is never returned or shown to you, and no tool on this server returns it' and 'Only YOUR account's secrets are listed'. These privacy and scoping constraints are not derivable from annotations and are essential for correct use, making this a strong behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, immediately followed by the most critical constraint (value never returned), then a practical use case and account scoping. Every sentence serves a distinct purpose; even the seemingly repetitive privacy clauses add nuance (not returned, not shown, not available from any tool). It is efficient and highly informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters, an output schema exists, and the annotations cover safety properties, the description provides everything an agent needs: what the tool lists, privacy guarantees, and account scope. There is no missing information that would affect correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema fully covers parameter semantics (100% coverage trivially). The baseline for 0 parameters is 4; the description adds no parameter-specific info, but none is needed, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool 'List the secrets stored in your Mnemoverse Vault' with a specific verb and resource, and specifies the output is limited to 'ALIAS and purpose only'. It differentiates from the sibling memory_* tools by explicitly scoping to the vault and secrecy domain, so an agent can instantly recognize its function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit when-to-use case: 'Use this to check WHICH secrets the user has stored and under what alias' with a concrete example. It does not mention when not to use or alternative tools, but since the sibling tools are all in a different domain, the guidance is sufficient for the context.
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.
5 tool updates
v0.14.2- Changed
memory_create_room1 field changed- changed
Input schema / properties / name / descriptionPrevious value: -"Room name, unique within your account (e.g. 'me-and-olya')."New value: +"Room name, unique within your account (e.g. 'launch-team')."
- Changed
memory_feedback1 field changed- changed
Output schema / properties / coactivation_edges / descriptionPrevious value: -"Number of feedback-driven query/result concept co-activation edges changed by the service. This is separate from ordinary Hebbian strengthening among a memory's own concepts. This server does not send query_concepts, so live calls through this tool report 0; asynchronous acknowledgements also report 0."New value: +"Number of links between query concepts and result concepts that this rating changed. This server does not send query_concepts, so live calls through this tool report 0; asynchronous acknowledgements also report 0."
- Changed
memory_read1 field changed- changed
Input schema / properties / exclude_author / descriptionPrevious value: -"Drop memories written by this author PRINCIPAL — the server-side identity. ⚠️ NOT USABLE FROM HERE YET: the principal is not shown in these results, so there is no value you can obtain through this tool, and a guess like 'me' silently matches nothing and filters nothing. Only pass it if your system knows the exact principal from elsewhere (e.g. the REST API). A self-exclusion shortcut is planned."New value: +"Drop memories written by this author PRINCIPAL — the server-side identity. ⚠️ NOT USABLE FROM HERE YET: the principal is not shown in these results, so there is no value you can obtain through this tool, and a guess like 'me' silently matches nothing and filters nothing. Only pass it if your system knows the exact principal from elsewhere (e.g. the REST API)."
- Changed
memory_stats3 fields changed- changed
Output schema / properties / episodes / descriptionPrevious value: -"Number of episodic (not yet consolidated) memories."New value: +"Number of individual memories (not merged into a summary)." - changed
Output schema / properties / hebbian_edges / descriptionPrevious value: -"Number of Hebbian concept-to-concept links, learned from concepts that occur together as memories are stored and used."New value: +"Number of learned concept-to-concept associations; memory_graph reads them." - changed
Output schema / properties / prototypes / descriptionPrevious value: -"Number of consolidated prototype memories."New value: +"Number of summary memories merged from several individual ones. Consolidation is not running on the hosted service, so this count does not currently grow."
- Changed
memory_write1 field changed- changed
Output schema / properties / importance / descriptionPrevious value: -"Novelty score for this write (0-1): how much it adds over the nearest memories already saved in the same domain. A first-generation metric UNDER ACTIVE DEVELOPMENT and known to be unreliable — the same content has measured ~0.08 in Russian against ~0.55 in English, so it under-reads non-English text. It is not a verdict on whether the memory was worth keeping. Absent when the service sent no score."New value: +"Novelty score for this write (0-1): how much it adds over the nearest memories already saved in the same domain. Outside shared rooms, a write that scores below the service's importance threshold is not stored, and `reason` says why when the service sends one. The score is approximate and can read lower for non-English text. It is not a verdict on whether the memory was worth keeping. Absent when the service sent no score."
1 tool update
v0.13.0- Changed
memory_feedback3 fields changed- removed
Input schema / properties / atom_idsRemoved value: -{ - "description": "Deprecated since 0.11, removed in 0.13: atom_ids is the old name of memory_ids, still accepted on its own until then. Pass memory_ids instead.", - "items": { - "type": "string" - }, - "minItems": 1, - "type": "array" -} - changed
Input schema / properties / memory_ids / descriptionPrevious value: -"Required: IDs of the memories to rate, the `id:` line of each memory_read result. (Optional in this schema only while the deprecated atom_ids is still accepted in its place.)"New value: +"IDs of the memories to rate, the `id:` line of each memory_read result." - changed
Input schema / requiredPrevious value: -[ - "outcome" -]New value: +[ + "memory_ids", + "outcome" +]
4 tool updates
v0.12.1- Changed
memory_feedback1 field changed- changed
Input schema / properties / atom_ids / descriptionPrevious value: -"Deprecated since 0.11, removed in 0.12: atom_ids is the old name of memory_ids, still accepted on its own until then. Pass memory_ids instead."New value: +"Deprecated since 0.11, removed in 0.13: atom_ids is the old name of memory_ids, still accepted on its own until then. Pass memory_ids instead."
- Added
memory_graph - Changed
memory_list_rooms1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "rooms": { + "items": { + "additionalProperties": false, + "properties": { + "address": { + "description": "Domain address (xroom:<id>); pass as `domain` on read/write.", + "type": "string" + }, + "archived": { + "description": "True if archived (owned rooms only).", + "type": "boolean" + }, + "name": { + "description": "The room name.", + "type": "string" + }, + "role": { + "description": "'owner' or 'member'.", + "type": "string" + }, + "room_id": { + "description": "The room's id (room_...).", + "type": "string" + }, + "scope": { + "description": "'read' or 'read_write'.", + "type": "string" + } + }, + "required": [ + "room_id", + "address", + "role", + "archived" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "rooms" + ], + "type": "object" +}
- Changed
vault_list1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "secrets": { + "items": { + "additionalProperties": false, + "properties": { + "alias": { + "description": "The secret's alias — the reference you use, never the value.", + "type": "string" + }, + "concepts": { + "description": "Concept tags.", + "items": { + "type": "string" + }, + "type": "array" + }, + "context": { + "description": "The secret's purpose/context — never the value.", + "type": "string" + } + }, + "required": [ + "alias", + "context", + "concepts" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "secrets" + ], + "type": "object" +}
8 tool updates
v0.11.0- Changed
memory_create_room1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "address": { + "description": "Domain address (xroom:<id>); pass as `domain` on read/write.", + "type": "string" + }, + "name": { + "description": "The room name as stored.", + "type": "string" + }, + "room_id": { + "description": "The room's id (room_...); pass to memory_invite_to_room.", + "type": "string" + } + }, + "required": [ + "room_id", + "address" + ], + "type": "object" +}
- Changed
memory_feedback1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "avg_valence": { + "description": "Average valence of the rated memories after the update. Reported as 0 in an asynchronous acknowledgement, where the real value is computed later — a 0 here is therefore not evidence of a neutral outcome.", + "type": "number" + }, + "coactivation_edges": { + "description": "Number of feedback-driven query/result concept co-activation edges changed by the service. This is separate from ordinary Hebbian strengthening among a memory's own concepts. This server does not send query_concepts, so live calls through this tool report 0; asynchronous acknowledgements also report 0.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "updated_count": { + "description": "How many memories the service reports it applied the rating to. Processed synchronously this is the real count of memories that existed and were updated; processed asynchronously it is a best-effort ACCEPTED-count estimate — the number of IDs submitted — and the authoritative number is not known until the background worker runs. Zero means no submitted ID matched in the service's resolved request scope.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "updated_count" + ], + "type": "object" +}
- Changed
memory_invite_to_room2 fields changed- changed
Input schema / properties / max_uses / maximumPrevious value: -9007199254740991New value: +1000 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "code": { + "description": "The invite code (mnvr_...). Single-use by default, with a configurable use limit. Shown once.", + "type": "string" + }, + "expires_at": { + "description": "ISO 8601 expiry, or null.", + "type": [ + "string", + "null" + ] + }, + "join_url": { + "description": "Landing URL the invitee can open to join.", + "type": "string" + }, + "room_address": { + "description": "The room's domain address (xroom:<id>).", + "type": "string" + }, + "scope": { + "description": "Role the invitee will get.", + "type": "string" + }, + "share_message": { + "description": "Ready-to-forward invite text.", + "type": "string" + } + }, + "required": [ + "share_message" + ], + "type": "object" +}
- Changed
memory_join_room1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "address": { + "description": "Domain address (xroom:<id>); pass as `domain` on read/write.", + "type": "string" + }, + "already_member": { + "description": "True if you were already a member (no-op join).", + "type": "boolean" + }, + "name": { + "description": "The room name.", + "type": "string" + }, + "next_steps": { + "description": "How to use the room now.", + "type": "string" + }, + "room_id": { + "description": "The room's id (room_...).", + "type": "string" + }, + "scope": { + "description": "Your role in the room ('read' | 'read_write').", + "type": "string" + } + }, + "required": [ + "room_id", + "address", + "next_steps" + ], + "type": "object" +}
- Changed
memory_list_recent1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "items": { + "description": "Entries newest-first (creation time descending).", + "items": { + "additionalProperties": false, + "properties": { + "author": { + "description": "Sanitized AGENT identity of the writer (never the human principal) — attribution in shared rooms.", + "type": "string" + }, + "content": { + "description": "Stored memory content.", + "type": "string" + }, + "created_at": { + "description": "UTC creation instant, ISO-8601; absent on legacy memories without a timestamp.", + "type": "string" + }, + "domain": { + "description": "User-defined memory namespace or domain.", + "type": "string" + }, + "memory_id": { + "description": "Identifier needed to rate or manage this saved memory.", + "type": "string" + } + }, + "required": [ + "memory_id", + "content", + "domain" + ], + "type": "object" + }, + "type": "array" + }, + "next_cursor": { + "description": "Pass back as cursor for the next (older) page; null = listing complete. Absent when the service sent a continuation token this client will not pass on; the text then says the token could not be displayed.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "items" + ], + "type": "object" +}
- Changed
memory_read3 fields changed- changed
Input schema / properties / top_k / descriptionPrevious value: -"Requested number of results (default: 5). ⚠️ Not a hard cap: association expansion can return MORE than this, and the relevance floor can return fewer — raising it does not reliably widen the result set. For a complete, exactly-bounded listing use memory_list_recent instead."New value: +"Requested number of results (default: 5, what this server asks for when you omit it; the engine's own default of 10 never applies, because the field is always sent). ⚠️ Not a hard cap: association expansion can return MORE than this, and the relevance floor can return fewer — raising it does not reliably widen the result set. For a complete, exactly-bounded listing use memory_list_recent instead." - changed
Input schema / properties / top_k / maximumPrevious value: -50New value: +500 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "items": { + "description": "Matching memories, ordered per order_by.", + "items": { + "additionalProperties": false, + "properties": { + "author": { + "description": "Sanitized AGENT identity of the writer (never the human principal) — attribution in shared rooms.", + "type": "string" + }, + "content": { + "description": "Stored memory content.", + "type": "string" + }, + "created_at": { + "description": "UTC creation instant, ISO-8601; absent on legacy memories without a timestamp.", + "type": "string" + }, + "domain": { + "description": "User-defined memory namespace or domain.", + "type": "string" + }, + "memory_id": { + "description": "Identifier needed to rate or manage this saved memory.", + "type": "string" + } + }, + "required": [ + "memory_id", + "content", + "domain" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "items" + ], + "type": "object" +}
- Changed
memory_stats1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "avg_importance": { + "description": "Average importance of stored memories, on a scale from 0 to 1.", + "type": "number" + }, + "avg_valence": { + "description": "Average valence of stored memories: how well recalls turned out, on a scale from -1 to 1.", + "type": "number" + }, + "domains": { + "description": "User-defined memory domains.", + "items": { + "type": "string" + }, + "type": "array" + }, + "episodes": { + "description": "Number of episodic (not yet consolidated) memories.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "hebbian_edges": { + "description": "Number of Hebbian concept-to-concept links, learned from concepts that occur together as memories are stored and used.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "memory_count": { + "description": "Number of saved memories.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prototypes": { + "description": "Number of consolidated prototype memories.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "memory_count", + "domains" + ], + "type": "object" +}
- Changed
memory_write3 fields changed- added
Input schema / properties / concepts / maxItemsAdded value: +256 - added
Input schema / properties / domain / maxLengthAdded value: +100 - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "importance": { + "description": "Novelty score for this write (0-1): how much it adds over the nearest memories already saved in the same domain. A first-generation metric UNDER ACTIVE DEVELOPMENT and known to be unreliable — the same content has measured ~0.08 in Russian against ~0.55 in English, so it under-reads non-English text. It is not a verdict on whether the memory was worth keeping. Absent when the service sent no score.", + "type": "number" + }, + "memory_id": { + "description": "Identifier of the stored memory, or null when it was not stored.", + "type": [ + "string", + "null" + ] + }, + "reason": { + "description": "The memory service's own explanation of this outcome, quoted as sent — when stored is false this is the ONLY statement of WHY, e.g. \"Below importance threshold (0.047 < 0.1)\". Ordinary text is preserved exactly; only control, bidi, zero-width, and repeated-whitespace characters are normalized before display, and the value is capped at 400 characters. Absent when the service sent no explanation, or when nothing remains after that normalization.", + "type": "string" + }, + "stored": { + "description": "Whether the memory passed the novelty gate and was stored.", + "type": "boolean" + } + }, + "required": [ + "stored", + "memory_id" + ], + "type": "object" +}
2 tool updates
v0.10.2- Changed
memory_feedback4 fields changed- changed
Input schema / properties / atom_ids / descriptionPrevious value: -"IDs of memories to give feedback on (from memory_read results)"New value: +"Deprecated since 0.11, removed in 0.12: atom_ids is the old name of memory_ids, still accepted on its own until then. Pass memory_ids instead." - added
Input schema / properties / domainAdded value: +{ + "description": "Only for memories read from a shared room: that room's address (xroom:...), exactly as you read it. Omit it for your own memories, which are rated by id alone.", + "type": "string" +} - added
Input schema / properties / memory_idsAdded value: +{ + "description": "Required: IDs of the memories to rate, the `id:` line of each memory_read result. (Optional in this schema only while the deprecated atom_ids is still accepted in its place.)", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" +} - changed
Input schema / requiredPrevious value: -[ - "atom_ids", - "outcome" -]New value: +[ + "outcome" +]
- Changed
memory_invite_to_room1 field changed- added
Input schema / properties / max_usesAdded value: +{ + "description": "How many people may join with this invite (default 1, single-use).", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" +}
2 tool updates
v0.10.0- Changed
memory_list_recent2 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Restrict to one domain. REQUIRED to read a shared room — pass its address ('xroom:room_01ABC'), because rooms are separate stores that an unscoped feed does NOT cover. Omit only when you mean your own domains. Room addresses come from memory_list_rooms."New value: +"Restrict to one domain. REQUIRED to read a shared room — pass its address ('xroom:room_01ABC'), because rooms are separate stores that an unscoped feed does NOT cover. Omit only when you mean your own domains. Room addresses come from memory_list_rooms. Room entries are often long — a room feed usually reaches its size budget after a handful of them, so expect to page (see `limit`)." - changed
Input schema / properties / limit / descriptionPrevious value: -"Page size (default: 20). Newest first."New value: +"Most entries per page (default: 20). Newest first. ⚠️ A CEILING, not a promise: the page is ALSO bounded by size, so a page of long entries stops early and returns a cursor for the rest. In rooms whose entries run long, ask for 5–10 — a large `limit` there buys nothing the size budget will not take back, and costs round trips."
- Changed
memory_write1 field changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme')"New value: +"Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme'). Matched byte-for-byte — a leading space, a different case, or an invisible character opens a SEPARATE, permanent store, so reuse an exact name from memory_stats rather than retyping one. To write into a shared room, pass its address here instead (e.g. 'xroom:room_01ABC'). Find room addresses with memory_list_rooms."
2 tool updates
v0.9.0- Removed
memory_delete - Removed
memory_delete_domain
2 tool updates
v0.8.1- Changed
memory_list_recent3 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Restrict to one domain (e.g. a shared room address 'xroom:...'); omit for all your domains."New value: +"Restrict to one domain. REQUIRED to read a shared room — pass its address ('xroom:room_01ABC'), because rooms are separate stores that an unscoped feed does NOT cover. Omit only when you mean your own domains. Room addresses come from memory_list_rooms." - added
Input schema / properties / exclude_authorAdded value: +{ + "description": "Drop entries written by this author PRINCIPAL. ⚠️ NOT USABLE FROM HERE YET — the principal is never shown in these results, so there is no value you can get through this tool; a guess like 'me' filters nothing, silently. Same caveat as on memory_read.", + "maxLength": 200, + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "Only entries created at/before this ISO-8601 instant (inclusive). Pair with `since` to read a closed window — 'what happened on Monday' — instead of paging back from now.", + "type": "string" +}
- Changed
memory_read3 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Restrict the search to one domain namespace (e.g. 'project:acme'); omit to search across all domains."New value: +"Restrict the search to one domain namespace (e.g. 'project:acme'). Omitting it searches your OWN domains — it does NOT include shared rooms, which are separate stores: to search a room, pass its address here (e.g. 'xroom:room_01ABC'). Find room addresses with memory_list_rooms." - changed
Input schema / properties / exclude_author / descriptionPrevious value: -"Drop memories written by this author PRINCIPAL (the server-side identity, not shown in these results). Useful when your system knows principals (e.g. via the REST API); a self-exclusion shortcut is planned server-side."New value: +"Drop memories written by this author PRINCIPAL — the server-side identity. ⚠️ NOT USABLE FROM HERE YET: the principal is not shown in these results, so there is no value you can obtain through this tool, and a guess like 'me' silently matches nothing and filters nothing. Only pass it if your system knows the exact principal from elsewhere (e.g. the REST API). A self-exclusion shortcut is planned." - changed
Input schema / properties / top_k / descriptionPrevious value: -"Max results to return (default: 5)"New value: +"Requested number of results (default: 5). ⚠️ Not a hard cap: association expansion can return MORE than this, and the relevance floor can return fewer — raising it does not reliably widen the result set. For a complete, exactly-bounded listing use memory_list_recent instead."
4 tool updates
v0.7.0- Added
memory_list_recent - Added
memory_list_rooms - Changed
memory_read4 fields changed- added
Input schema / properties / exclude_authorAdded value: +{ + "description": "Drop memories written by this author PRINCIPAL (the server-side identity, not shown in these results). Useful when your system knows principals (e.g. via the REST API); a self-exclusion shortcut is planned server-side.", + "maxLength": 200, + "type": "string" +} - added
Input schema / properties / order_byAdded value: +{ + "description": "'relevance' (default) = ranking order. 'recency' = the matched set re-sorted newest-first. For a complete newest-first feed with no search at all, use memory_list_recent instead.", + "enum": [ + "relevance", + "recency" + ], + "type": "string" +} - added
Input schema / properties / sinceAdded value: +{ + "description": "Only memories created at/after this ISO-8601 instant (naive = UTC) — e.g. your last-seen watermark in a shared room.", + "maxLength": 40, + "type": "string" +} - added
Input schema / properties / untilAdded value: +{ + "description": "Only memories created at/before this ISO-8601 instant.", + "maxLength": 40, + "type": "string" +}
- Added
vault_list
3 tool updates
v0.5.0- Added
memory_create_room - Added
memory_invite_to_room - Added
memory_join_room
TDQS
Scored across 11 tools
Each tool has a clearly distinct purpose: write, read, feedback, stats, room management (create/invite/join/list), graph inspection, recent listing, and vault listing. The only potential overlap—memory_read vs memory_list_recent—is explicitly resolved by their descriptions (semantic search vs chronological listing), and stats vs graph are differentiated as summary vs detailed edges.
All tools use lowercase snake_case, and 10 of 11 share the memory_ prefix; vault_list is a minor deviation. The internal pattern mixes verbs (write, read, create_room) and nouns (feedback, stats, graph), but remains readable and predictable enough for consistent use.
11 tools is well-scoped for a memory server with shared rooms, feedback, graph, and vault functionality. Each tool earns its place, and the count avoids both bloat and thinness.
The surface covers the full memory lifecycle (write, read, feedback, stats, graph, recent) and core room management (create, invite, join, list). Minor gaps exist: no way to leave or delete a room, and the vault supports only listing (likely by design), but these do not block typical agent workflows.
Maintenance
Related MCP Connectors
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Persistent memory for AI agents. Search, store, and recall across sessions.
Persistent memory for AI agents. Semantic search, memory graph, W3C DID identity.
Private persistent memory for Claude, ChatGPT & Gemini via MCP - semantic search, zero-code setup.
Related MCP Servers
- AlicenseAqualityDmaintenancePersistent memory API for AI agents — store, recall, and inject semantically-searchable context across sessions. EU-hosted, GDPR-compliant. Supports Claude, Cursor, Cline, and any MCP-compatible client.42MIT
- AlicenseBqualityDmaintenanceA shared memory layer for AI agents — one memory.md synced across Claude Desktop, Cursor, Claude Code, OpenAI Codex, and any MCP client.42MIT
- AlicenseNot gradedqualityBmaintenancePersistent memory for AI coding agents that stores and recalls preferences, decisions, and conventions via semantic similarity, with zero cloud dependencies and plug-and-play MCP integration for Claude Code.Apache 2.0
- AlicenseBqualityAmaintenancePersistent, local memory for AI coding agents that learns how you work, not just what you said. Supports Claude Code, Codex CLI, Cursor, and any MCP client.7771MIT