Skip to main content
Glama

Aelios

A long memory for your AI. Switch windows, switch clients, switch models — the memory follows you.

English | 简体中文 · QQ group: 1091783659

Aelios is a memory gateway that runs on Cloudflare. Your Chatbox / Claude Code / Codex connects to Aelios first; Aelios forwards the request to the model. Every conversation is kept, and the relevant parts come back automatically next time.

your client  →  Aelios (identify, remember, recall)  →  the model

Let an AI set it up

With an AI that can run commands (Claude Code, Codex and the like), send it this:

Install and set up Aelios (my AI memory gateway) for me. Read https://raw.githubusercontent.com/wusaki0723/Aelios/main/docs/setup-with-ai.md first and follow it. When I need to click something in the browser or enter a key myself, stop and tell me where.

It works from scratch: it forks and deploys Aelios, creates the Cloudflare token, configures the assistant and imports your old memories. At the end it hands you a base URL, an API key and the model name to pick, ready for your chat app. You need a Cloudflare account (the free plan is enough) and a key for your model. All you do yourself is click "Allow" in the browser (twice for a new install) and store the model key in the Cloudflare dashboard (it tells you where). The guide is written in Chinese; the AI will talk to you in your language.

The recommended setup is API mode plus the MCP connector: chats go through Aelios, so every turn is remembered and recalled automatically, and with MCP the assistant can also look things up and save them on its own. Only if you have a Claude subscription and no API access, use MCP alone.

To do it by hand, follow the three steps below.

Related MCP server: second-brain-cloudflare

Quick start — three steps

1. Deploy

Fork this repo first, then deploy your fork. That way every later update is one click (see Updating).

  1. Click Fork at the top of this page.

  2. In the Cloudflare dashboard, go to Workers & Pages → Create → Import a repository, connect GitHub and pick your fork. Keep the project name companion-memory-proxy, set the build command to npm ci and the deploy command to npm run deploy. The deploy command creates the D1 database, the Vectorize index and the queue for you.

  3. Once it's deployed, open the Worker's Settings → Variables and Secrets and add the secret CHATBOX_API_KEY: make up a password, e.g. sk-my-aelios. It's the only one you need; the optional ones are in SECRETS.md.

You'll get an address like:

https://companion-memory-proxy.<your-subdomain>.workers.dev

Don't run a bare wrangler deploy — it won't create the databases.

Not recommended: the one-click button. Deploy to Cloudflare

It works, but Cloudflare copies this repo into a new repository in your account instead of forking it. GitHub has no Sync fork for a copy, so every update has to be pulled in by hand. If you use it anyway: the only required field is CHATBOX_API_KEY; for the Vectorize index use Dimensions 1024, Metric cosine; build command npm ci, deploy command npm run deploy. Already deployed this way? See Deployed with the button.

2. Add an assistant

Open:

https://<your Worker address>/admin

Enter your Worker address and the key from step 1, then go to Settings.

  1. Upstream: your Cloudflare account ID (32 characters). For full chat forwarding, also add a CLOUDFLARE_API_TOKEN Worker secret.

  2. Assistant: click Add assistant, for example:

    Field

    What it means

    Example

    Name

    The segment in the URL, lowercase English

    coder

    Primary model

    Only these models remember and recall

    anthropic/claude-opus-4-5

    Keys

    Who may use this assistant

    check the primary key

  3. Click Save.

One assistant, one address. Name it coder and the address is:

https://<your Worker address>/coder/v1

Only registered primary models get memory. Unregistered models (like the small utility models inside Claude Code) just pass through — nothing is recorded or recalled for them.

3. Point your client at it

Use CHATBOX_API_KEY as the API key everywhere. Write model names as vendor/model, e.g. anthropic/claude-opus-4-5.

Client

Address to use

Chatbox, Cherry Studio, …

https://<Worker address>/coder/v1

Claude Code

ANTHROPIC_BASE_URL=https://<Worker address>/coder

Codex

base_url = https://<Worker address>/coder/v1, with wire_api = "responses"

A bare /v1 without an assistant name routes to the first assistant of that key.

Try it: say "Please remember: my test code phrase is apple-star-0428." Wait a bit, then ask "What is my test code phrase?" If it answers, you're wired up.

Updating to the latest version

GitHub doesn't update forks by itself. When a new version is out:

  1. Open your fork on GitHub and click Sync fork → Update branch.

  2. Cloudflare picks up the new commit, builds and deploys it on its own. You can follow it under the Worker's Deployments.

Memories, settings, assistants and keys live in your Cloudflare account, not in the repo, so syncing keeps all of them. Change settings in /admin rather than by editing files in your fork, and Sync fork stays a one-click update with no conflicts.

Want it automatic? The Pull app syncs a fork on a schedule. Every new version then goes live without you looking at it first, database migrations included, and by default Pull hard-resets your fork to this repo, dropping any commits of your own. Syncing by hand is the recommended way.

Deployed with the button

A button deploy is a copy, not a fork, so it has no Sync fork. Move your Worker onto a fork instead; your memories and settings stay where they are, in Cloudflare.

  1. Fork this repo.

  2. If you renamed the D1 database or the Vectorize index on the button's setup page, open the Worker's Settings → Build → Build Variables and Secrets and add CMP_D1_NAME and CMP_VECTORIZE_NAME with those names. Otherwise the build creates new, empty ones and your memories look gone (they're still in the old database).

  3. In Settings → Build, click Disconnect, then Connect and pick your fork, with build command npm ci and deploy command npm run deploy.

  4. If Cloudflare opens a pull request on your fork to fix the Worker name, merge it.

From then on, Cloudflare builds from your fork whenever it changes, so your next Sync fork brings you up to date. Until then the Worker keeps running the version it has.

Day-to-day: the admin panel

Open /admin. The bottom tabs:

Tab

What it's for

Today

What you talked about today

Diary

One diary entry a day, plus weekly entries. If one came out empty, press "用原文重写这篇" (rewrite from the chat)

Dream

What the nightly consolidation (Dream) did each night and what it produced; you can also re-run a day by hand, see below

Review queue

Candidate memories consolidated overnight. Cloudflare's clef reviews them every night by default; the week's decisions are listed here with an undo. With clef switched off they wait here, or the assistant reviews them itself over MCP. Anything imported from elsewhere sits in its own "Imported" tab and waits for you alone

Important memories

Browse, search, edit, delete; a memory rewritten in place keeps its earlier versions under "Old versions", where you can restore one

Star map

Your memories drawn as a 3D star map (a separate page)

More

Precious originals, glossary, notebook, import / export, maintenance tools

Settings

Upstream, assistants, environment parameters

Want the AI to remember, forget, or fix something? It's all point-and-click.

Re-running Dream for one day

When a night's consolidation failed, or you want a day processed now:

  1. Open Dream and check the space selected at the top right.

  2. Under "现在做梦" (Dream now), pick the date and untick "预演 dry_run" (ticked by default; ticked only previews and writes nothing). Usually leave force off.

  3. Press "现在做梦". Once it says it is queued you can close the page; the job runs in the background, and a refresh shows the result.

  4. Each press handles one batch (DREAM_MAX_MESSAGES messages, 40 by default). For a busy day press again until it says the night is already done. When the day's last batch finishes, that day's diary is written automatically.

  • Button greyed out and the task marked as possibly interrupted: check the Worker logs that it really stopped, press "核查后标记为已中断" (mark as interrupted), then press again.

  • A diary entry that only says what was tidied up: that is Dream's draft. Open the Diary tab and press "用原文重写这篇" (rewrite from the chat). Chat is kept for 7 days; after that it can't be rewritten.

  • The detailed execution rules, API and limits are under For maintainers → Dream execution and failure status.

Moving memories: export and import

Under "More → Import / export", each one works on the space you have selected:

  • Export: md or jsonl. The md has one memory per line (date, text, #tags, the key in backticks); open it, edit it, and import it back as is. A line with the same key rewrites that memory, and the old version is kept.

  • Import tidied entries: one per line, - 2025-12-15 [preference] text #tag; date, type and tags are optional, and a plain md list or paragraphs work too. The page has a ready prompt to paste into the AI you used before so it lists what it remembers in this format. Entries can go straight in (exact duplicates are skipped, near-duplicates go to review) or all go to review first.

  • Import a chat history: ChatGPT and Claude conversations.json, SillyTavern .jsonl, and plain "Name: text" transcripts. The file is read in the page and cut by day; each day goes through the same model the nightly consolidation uses (DREAM_MODEL), and what it finds only lands in the review page's "Imported" tab, where nothing counts until you approve it. Progress and token use are shown as it runs. Only the lines a candidate quotes are kept, outside the chat table, so the 7-day cleanup never removes them and the nightly run never re-reads them. Close the page and pick the same file later to carry on.

How it actually works

  • Every time you speak, relevant old memories are tucked onto the end of the current conversation.

  • Raw conversations are stored first; overnight, Aelios consolidates them into long-term memory (the Dream pass). Each assistant decides what it keeps using the model it chats with, and you can undo any of its calls.

  • Memory lives in your own Cloudflare account (D1 + Vectorize) — never tied to a chat window, never on someone else's server.

One assistant can write to one space and read from several. A fresh conversation can write coder while also reading the old vault coder-old and a shared shared-docs. Leave the recall spaces empty and it only reads its own.

Optional features

Full chat gateway — let Aelios forward to every vendor's models, billed against your own keys:

  1. Cloudflare → AI → AI Gateway: create a gateway and store each vendor's key under it.

  2. Add the CLOUDFLARE_API_TOKEN Worker secret.

  3. In /admin Settings, put your 32-character account ID as the upstream and add assistants.

Skip all of that and memory recall + the overnight Dream still work (via Workers AI). An AI can do these three steps for you: see Let an AI set it up.

Choose which models your app lists — AI Gateway has thousands of models, and a chat app that only lets you pick from the list gets all of them. In /admin Settings → Providers → Model list, pick the ones you use from the upstream catalog (the + button) and type in any name the catalog does not have (custom providers, dynamic routes, suffixes such as :floor). The link button beside a listed model sends it one tiny real request, the way a chat client would, and turns into a green dot when it answers; the − button takes it off the list. GET /v1/models then answers with exactly that list, in the order you added the models. It only changes what is shown: a model that is not on the list can still be called by name, as before. Leave it empty and nothing changes (the whole catalog is shown). With a list saved, the chatgpt/… models are shown only if you picked them; the picker lists them first.

Use your ChatGPT plan — on a ChatGPT Plus or Pro plan, let your assistant run on the plan instead of an API key (OpenAI's "Sign in with ChatGPT"):

  1. /admin → Settings → Providers → ChatGPT plan → Continue with ChatGPT. Sign in and approve.

  2. Your browser then lands on a 127.0.0.1 page that fails to load. That is expected: copy the whole address from the address bar, paste it into the box in /admin and press Finish sign-in.

  3. Use models named chatgpt/<model>. The Test button lists what your account can use. To give one memory, add chatgpt/* to the assistant's primary models.

Good to know: it connects your own account and nothing else, so don't hand this route to other people. Usage counts against your plan's limits (ChatGPT settings → Usage). Clients speaking chat/completions, Anthropic messages or responses all work (the first two are translated to Responses and back, thinking blocks included), and OpenAI's plan route rejects hosted tools such as image generation, file search, code interpreter and MCP; function tools and web search work. No new secret is needed: the tokens sit encrypted in D1 under a key derived from CHATBOX_API_KEY, so changing that key means signing in again. npm run deploy applies the new migration. The overnight jobs can use the plan too: put chatgpt/<model> in Settings → Dream model (and the diary model if you like). They send several requests a night, all counted against the plan; on a night the plan is out, those jobs fail like any other model error and the memory stays put.

MCP memory for the Claude app (web and mobile), Claude Code and Codex:

https://<Worker address>/mcp?token=<CHATBOX_API_KEY>
  • Claude app: add a custom connector on the connectors page (claude.ai/customize/connectors) with the address above. Once it is added on the web it shows up in the mobile app too. Under tool permissions, set the read-only group to "Always allow", or every recall asks first.

  • The Claude app does not read the usage notes an MCP server sends. To make it remember to use the memory, paste this into your personal preferences or project instructions:

You have the Aelios memory connector: it is your long-term memory of me. In every new conversation, call wake_up before you reply. Before answering anything about my past or the people in my life, or before guessing something about me, call recall. When I tell you something new, change my mind or make a promise, call remember right away. When the conversation winds down, call log_conversation.
  • Conversations in the Claude app do not pass through Aelios, so the nightly diary and candidates only see what the assistant hands over with log_conversation. Clients that go through the gateway don't need it.

  • Only the ten everyday tools are listed by default. For maintenance tools such as memory_get and memory_export, add &tools=all to the address.

If you only have a Claude subscription and cannot use API mode, get automatic per-message recall and batch write-back in Claude Code with the Hook in this repo: integrations/claude-code/.

Seeing images (guide-dog): add the GUIDE_DOG_API_KEY secret, then point your client at https://<Worker address>/v1/guide-dog with model companion. The guide-dog only describes images — it writes no memory.

A companion that lives on Cloudflare: Aelios-resident — a separate Worker (one Durable Object, built on Cloudflare's Think) that you talk to on Telegram and on its own web page, both one conversation. With Aelios connected, its chat goes through your assistant's /v1 endpoint like any other client, so Aelios does the recalling and the remembering; it also uses the memory tools, and what lasts from its web searches is saved as world knowledge. On top of that it writes itself a handoff letter when you go quiet, checks in on a schedule, searches and reads the web, connects other MCP servers, and lets you change the model, persona and settings on its web page. It runs on the Workers Free plan. To connect it, fill in this Aelios's address, a key and the assistant to chat as on its settings page (the model you pick has to be one of that assistant's primary models); deployment is in its README.

Common pitfalls

  • Deploy with npm run deploy, never a bare wrangler deploy.

  • Assistant names are part of the URL: use coder-style English, no spaces.

  • Model names need the vendor prefix: anthropic/claude-opus-4-5, not claude-opus-4-5.

  • Only registered primary models get memory. Keep small utility models out.

  • Never hand-delete the Vectorize index (memo-kb, 1024-dim cosine).

  • Manual Dream on the Dream tab has "预演 dry_run" (preview) ticked by default, which writes nothing; untick it for a real run.

Digging deeper


For maintainers

A memory gateway on Cloudflare Workers. When helping a user deploy, always link the user's own fork; all secrets live in the user's own account.

Resource

Value

Worker

companion-memory-proxy

D1

companion_memory_proxy

Vectorize

memo-kb (1024-dim, cosine)

Queue

companion-memory

Embedding

workers-ai/@cf/baai/bge-m3

Entry points: /<assistant>/v1/chat/completions, /<assistant>/v1/messages, /<assistant>/v1/responses. A bare /v1/... uses the first assistant of that key.

Upstreams: chat goes through compat (all vendors, BYOK); messages / responses hit each vendor's native endpoint. Model names pass through untouched — if the vendor doesn't recognize one, the upstream error says so. Custom OpenAI-compatible base URLs are forwarded as-is.

Configuration has three layers, all under /admin Settings: upstream, assistants, environment parameters. Precedence: panel-saved > GATEWAY_CONFIG > empty config.

Common endpoints

Method

Path

Notes

GET

/health

Health check

GET

/admin

Admin panel

GET

/v1/models

Model list (the upstream catalog, or your saved model list)

POST

/<assistant>/v1/chat/completions

OpenAI-compatible chat

POST

/<assistant>/v1/messages

Anthropic messages

POST

/<assistant>/v1/responses

OpenAI responses

GET

/api/gateway/models

Model picker for /admin (owner key): every upstream model id, your ChatGPT models, the saved list

POST

/api/gateway/models/test

Connectivity test for one model (owner key): {"model": "…"} → one tiny chat request, {ok, status, latency_ms, error?}; nothing is recorded

GET / POST

/api/gateway/chatgpt/*

ChatGPT plan sign-in (owner key): status, login, callback, test, welcome, logout

GET / POST

/mcp

MCP memory tools

GET / POST

/v1/memories

List / create memories

POST

/v1/memory/recall

Dynamic recall (preferred by hooks)

POST

/v1/search/memories

Raw search (unmetered)

POST

/v1/ingest/messages

Ingest raw chats

GET

/v1/memory_boot

Cold-start pack

GET

/v1/diary, /v1/diary/recent

Diary

POST

/admin/diary-rewrite

Rewrite one diary entry from that day's chat: {"date":"YYYY-MM-DD"}

GET

/v1/dream/status

Dream runs from the last 7 days, the active task, cursors

POST

/v1/dream/run

Run Dream by hand: date, force, dry_run; add "background":true to queue it (202 with a run_id)

POST

/v1/dream/resolve

Mark a task unconfirmed for over 20 minutes as interrupted: {"run_id":"…"}

GET / POST / DELETE

/v1/precious, /v1/glossary

Precious originals / glossary

GET / POST / PATCH / DELETE

/v1/notebook

Notebook pages; /:id opens, edits or deletes one, DELETE ?confirm=all clears the space's notebook

GET / POST

/v1/candidates

Review queue; ?scope=daily for the nightly ones only, /decisions?days=7 lists automatic decisions, /:id/undo reverses one, /:id/sources shows the quoted lines

GET

/v1/memories/export?format=md|jsonl

Export the space's memories and precious lines (memory:read is enough)

GET

/v1/memories/:id/revisions

Earlier versions of a memory rewritten in place

GET / POST

/v1/import/*

Import: info, entries/preview, entries, batches, chat/chunk, candidates

Everything except /health and /admin requires Authorization: Bearer <key>. The gateway authorizes by assistant key; memory APIs by memory:read / memory:write scopes.

MCP tools

wake_up recall remember keep_moment forget learn_word read_diary log_conversation list_memories notebook

notebook keeps named pages the assistants read and rewrite themselves, such as progress on a long task. Pages are never recalled automatically, changed overnight or expired; you can edit, delete or clear them under "More → Notebook".

With the clef review switched off, memory_candidates and memory_review are listed too; &tools=all on the address adds memory_get and memory_export. The old names (memory_boot, memory_recall, memory_search, memory_upsert, memory_supersede, memory_archive, memory_delete, memory_ingest, memory_pin, glossary_set, diary_get, memory_list) are no longer listed but still work when called.

How memory flows

Writes: assistants write directly via remember; a nightly cron (10 20 * * *) extracts facts from the day's conversations → each candidate is judged remember-or-let-go by Cloudflare's clef decision model (CLEF_AUTO_REVIEW, on by default; switched off, candidates wait for you, or the assistant reviews them itself with the MCP tools memory_candidates and memory_review), and writes diary / weekly / monthly entries. It consolidates "yesterday" in DREAM_TIME_ZONE, in batches of DREAM_MAX_MESSAGES, at most DREAM_MAX_RUNS batches a night; a day left unfinished gets one more batch on each of the next few nights (3-day lookback), or you can finish it by hand on the Dream tab. A day's diary is written once its last batch is done.

Recall: your latest message → vector search + lexical match → batch rerank of original passages + rules → the clean original text is tucked onto the end of the current message. No generative LLM by default: at most one memory on a normal turn, two when answering about the past; low scores are never padded in. Rerank failures fall back to lexical. Scores and trade-offs are visible in /admin → Settings. Transport envelopes, hashes, and message IDs never enter the daily prompt; two adjacent messages within 90 seconds in one session are merged. Active search still returns full records and IDs. Diaries are not auto-injected.

Cleanup: messages live ~7 days; a memory not rewritten, recalled or seen again for 180 days is flagged expired (pinned, identity and persona never are), and expired records are hard-deleted 30 days later.

Dream execution and failure status

The admin Dream console submits non-dry manual Dream runs to the existing durable MEMORY_QUEUE. Acceptance returns a run ID immediately; after acceptance, closing the browser does not cancel the queued work. The panel polls status every five seconds and can find the task again after a reload. Queue batches contain one message so several expensive Dream jobs do not share one invocation's execution budget.

API clients opt in with POST /v1/dream/run and {"background":true} (plus the usual optional namespace, date and force). A successful enqueue returns HTTP 202 with data.run_id and data.status="queued"; use GET /v1/dream/status to follow it. As with the legacy endpoint, each manual job handles one batch, not necessarily the whole date; use the cursor to check whether more batches remain. Missing queues and failed acceptance return 503. Without background:true, the old synchronous contract remains; dry-runs also stay synchronous.

  • A queued/running task blocks another background admission in the same space; force does not bypass it. This is not a global lease covering cron and legacy synchronous callers.

  • A single digest/extraction call has a 120-second deadline, including its response body. The two-stage extraction phase has an eight-minute budget and at most three batch reductions. Invalid JSON/schema causes both stages to restart on the same smaller prefix; the suffix remains for a later batch. Empty valid candidates differ from malformed output. A single unusable entry inside an otherwise valid answer (blank, over-long or wrong-typed) is dropped and counted in the logs instead of failing the batch; a wrong container type, a missing candidate list, or a non-empty list in which nothing is usable still counts as malformed. The extraction call has the same output budget as the digest (DREAM_MAX_TOKENS, up to 8000). Model/format failure does not advance the cursor or actively delete that batch's raw messages; the separate retention policy still applies.

  • Records older than 20 minutes without confirmed completion are labelled possibly interrupted / unconfirmed, not endlessly presented as healthy work. This is a read-only hint, not proof that execution stopped. Old unresolved records require log inspection and explicit operator reconciliation; they are not silently cleared to permit another run. Once you have checked the logs, the panel's Mark as interrupted button (or POST /v1/dream/resolve with {"run_id":"…"}, same memory:write scope) closes a queued/running record older than 20 minutes; anything newer or already finished is refused. The record then shows as an error and stops blocking a new task. Whatever it had already written is not rolled back.

  • Each Dream batch leaves a housekeeping draft on that date's diary entry; the real diary replaces it once the date's last batch is done. The nightly cron only writes yesterday's diary, so a manual job, the manual backfill endpoint and the cron backfill now write the diary themselves after a date's last batch (nothing happens until that batch is done, and a diary failure does not undo the Dream). On the Diary page, Rewrite from the chat (POST /admin/diary-rewrite with {"date":"YYYY-MM-DD"}) redoes any day whose chat is still within retention and replaces its current text; it is refused once that week has been rolled up into a weekly entry.

  • A conditional claim prevents duplicate delivery of one job from re-executing its pipeline. This is not exactly-once completion or automatic crash recovery: after a claim, ambiguous or partial writes are not automatically replayed. Inspect the run before retrying. The manual follow-up candidate review is retained; its failure does not undo an already completed Dream.

Local verification

npm install
npm run verify

Tests need Node.js 22+.

Lint is blocking in CI: npm run lint must be zero-error to merge. There are still some noNonNullAssertion warnings; the rule is demoted to warning in biome.json and doesn't affect the exit code — clean them up if you're touching that line, and never bulk-fix with Biome's autofix: it rewrites x!.y into x?.y, turning "crash loudly" into "silently return undefined".

License

AGPL-3.0

Free to use and modify; if you run a modified version as a network service, you must open-source your modifications under the same license.

The final v1 point is tag v1-final (MIT at the time).

Community

QQ group: 1091783659

Available Tools

14 tools
diary_getA
Read-only

Read daily_log diary entries. These are impressions, not verified facts. Omit date for today+yesterday (recent). Use week (e.g. 2026-W29) for weekly_log. Rolled-up daily dates fall back to weekly_log. Fetch explicitly when needed; do not treat diary as ground truth.

NameRequiredDescriptionDefault
dateNoYYYY-MM-DD; omit for recent (today+yesterday)
weekNoISO week label, e.g. 2026-W29
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real context beyond that: entries are impressions rather than verified facts, and rolled-up dates silently fall back to weekly_log, which is a non-obvious behavioral trait. It stops short of describing output shape or pagination.

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

Conciseness4/5

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

Five short clauses, none of which waste words, and the core semantics (recent default, weekly label) are front-loaded. The telegraphic style is dense but readable and earns its length.

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

Completeness4/5

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

For a read-only tool with no output schema and a fully documented 3-param schema, the description supplies the missing domain framing (what a diary entry is, its reliability) and the date/week fallback rule. Return format is undescribed, but no output schema exists, so the remaining gap is minor.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by explaining how date and week interact (the weekly_log fallback for rolled-up dates) and when to omit each. That is genuine semantics the schema does not carry.

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

Purpose4/5

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

States a specific verb+resource ('Read daily_log diary entries') and characterises the content ('impressions, not verified facts'), which separates it from the memory_* siblings that return authoritative memories. It does not explicitly name a sibling alternative, so it stops short of a 5.

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

Usage Guidelines4/5

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

Gives concrete selection guidance: omit date for today+yesterday, use week for weekly_log, and dates rolled up into weekly_log fall back there. 'Fetch explicitly when needed; do not treat diary as ground truth' sets a usage posture. It lacks explicit when-not/alternative routing to the memory_* tools.

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

glossary_setA
DestructiveIdempotent

Add or update a glossary term: private vocabulary such as nicknames, in-jokes or project names. Terms are matched literally (not by vector) during memory_recall and are all included in memory_boot. Upserts by term: an existing term gets the new definition, and aliases/examples are replaced by what you pass (omitting them clears them). Returns { data: glossary row }.

NameRequiredDescriptionDefault
termYesThe word or phrase exactly as it is used.
aliasesNoOther spellings or names that should match this term. Replaces any existing aliases.
examplesNoExample sentences using the term. Replaces any existing examples.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
definitionYesWhat the term means.

TDQS

A4.5/5.0
Behavior5/5

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

The annotations declare destructiveHint=true and idempotentHint=true, and the description explains exactly why: upsert-by-term semantics, plus the non-obvious fact that aliases/examples are replaced by what you pass and omitting them clears them. It also discloses literal (non-vector) matching and returns '{ data: glossary row }', adding real behavioral context beyond the annotations.

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

Conciseness5/5

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

Three dense sentences with no filler: purpose first, then matching/usage context, then mutation semantics and return shape. Each sentence earns its place and the key constraint (clearing aliases) is stated in the same breath as the upsert behavior.

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

Completeness5/5

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

Despite no output schema, the description gives the return shape, covers matching behavior, mutation/upsert semantics, and namespace handling is covered by the schema. Nothing an agent needs to invoke this correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so every parameter is already documented, including the 'Replaces any existing aliases/examples' semantics. The description's upsert sentence mostly restates what the schema says, so the baseline 3 applies.

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

Purpose5/5

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

The description states a precise verb+resource ('Add or update a glossary term') and immediately scopes the resource ('private vocabulary such as nicknames, in-jokes or project names'), which clearly separates it from the memory_* siblings. An agent can identify the tool's job 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.

Usage Guidelines4/5

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

It explains where glossary terms surface ('matched literally during memory_recall', 'all included in memory_boot'), which gives useful context on why to set one. However, it never explicitly states when to prefer glossary_set over a sibling like memory_upsert, nor any exclusions or prerequisites, so it stops short of full routing guidance.

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

memory_archiveA
DestructiveIdempotent

Soft-archive a memory: sets status='archived' and removes it from search and recall, but keeps the record in storage (memory_list with status='archived' still shows it). There is no MCP tool to un-archive. Does not touch the supersede chain. Prefer this over memory_delete when the memory might be needed later. Returns { data: { id, archived: true } }, or an error result 'Memory not found'.

NameRequiredDescriptionDefault
idYesMemory id (e.g. from memory_search, memory_recall or memory_list).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only declare destructiveHint=true/idempotentHint=true; the description goes well beyond by specifying exactly what is and isn't affected (removed from search/recall, retained in storage and visible via memory_list with status='archived', supersede chain untouched), that un-archiving is impossible, and the exact success and error return shapes. This is unusually rich 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.

Conciseness5/5

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

Front-loaded with the core action and its effect, then consequence, then alternative-tool guidance, then return shape. Every sentence carries distinct, decision-relevant information with no filler.

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

Completeness5/5

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

For a 2-param mutation tool with no output schema, the description covers effect, irreversibility, persistence behavior, alternative selection, and return/error values. Nothing needed to invoke it correctly is missing.

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

Parameters3/5

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

Schema coverage is 100% and both parameters (id, namespace) are already documented with examples and defaults in the schema, so the description adds no parameter-level meaning. Baseline 3 applies since the schema does the heavy lifting.

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

Purpose5/5

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

States a specific verb+resource ('Soft-archive a memory') and immediately defines the semantics: status becomes 'archived', it disappears from search/recall, but the record persists. It also explicitly contrasts itself with the sibling memory_delete, so an agent can differentiate without opening schemas.

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

Usage Guidelines5/5

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

Gives explicit routing guidance: 'Prefer this over memory_delete when the memory might be needed later,' and notes there is no MCP tool to un-archive, which is a decisive constraint for choosing this tool. Both the when-to-use and the irreversible consequence are stated.

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

memory_bootA

Cold-start context package for a new session: yesterday's diary log, the latest weekly and monthly summaries, the 20 most recent precious entries (from memory_pin), every glossary term and any spontaneous perception items, as { data: {...} }. Output is stable and deterministically ordered so the client can cache it. Call once at session start, not every turn; for per-question lookups use memory_recall. Never changes memory content; it only records that the returned precious entries were shown.

NameRequiredDescriptionDefault
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations mark this readOnlyHint=false and idempotentHint=false, and the description correctly explains why: it 'never changes memory content' but 'records that the returned precious entries were shown.' That reconciles the non-read-only flag with a content-preserving side effect, and adds useful caching context ('stable and deterministically ordered so the client can cache it'). It stops short of describing cost, latency, or failure behavior.

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

Conciseness4/5

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

Front-loaded with the payload contents, then usage rules, then the side-effect caveat — a logical order with no filler. The first sentence is a long enumeration, but each item listed is genuinely informative rather than padding.

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

Completeness5/5

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

With no output schema, the description carries the return contract itself (the { data: {...} } shape, its constituent sections, and its deterministic ordering). Combined with the usage rule and side-effect disclosure, an agent has everything needed to invoke this correctly once per session.

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

Parameters3/5

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

There is a single optional parameter (namespace) and schema description coverage is 100%, including the default and the fixed-namespace override case. The description adds nothing about it, which is the expected baseline when the schema fully documents the parameter.

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

Purpose5/5

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

The description names a specific operation (cold-start context package) and enumerates exactly what it bundles: yesterday's diary log, weekly/monthly summaries, 20 most recent precious entries, glossary terms, and perception items. It is clearly distinguishable from siblings like memory_recall and memory_search, which it explicitly routes around.

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

Usage Guidelines5/5

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

It states the when ('call once at session start, not every turn') and names the alternative for the opposite case ('for per-question lookups use memory_recall'). Both the trigger and the explicit exclusion are present, so routing is unambiguous.

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

memory_deleteA
DestructiveIdempotent

Permanently delete one memory by id, removing it from storage and from the search index. This cannot be undone. To hide a memory but keep the record, use memory_archive; to replace an outdated fact while keeping its history, use memory_supersede. Returns { data: { id, deleted: true } }, or an error result if the id is not found or the memory could not be removed from the search index (the record is then kept).

NameRequiredDescriptionDefault
idYesMemory id (e.g. from memory_search, memory_recall or memory_list).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds real context beyond them: irreversibility ('cannot be undone'), the dual removal from storage AND the search index, and failure semantics where an index-removal failure keeps the record. That is the exact behavioral detail an agent needs before a destructive call.

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

Conciseness5/5

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

Three tight sentences, front-loaded with the destructive action and its irreversibility, followed by routing alternatives and return shape. No filler.

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

Completeness5/5

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

There is no output schema, so the description supplies the return shape ({ data: { id, deleted: true } }) plus the error case, and covers the destructive semantics, alternatives, and parameters. Nothing an agent needs to call this correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100% and both parameters are documented there, including the namespace fallback rule. The description adds essentially no parameter detail beyond 'by id', so the schema carries the full load and baseline 3 applies.

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

Purpose5/5

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

The description states a precise verb+resource+scope: 'Permanently delete one memory by id, removing it from storage and from the search index.' It also names the two adjacent siblings (memory_archive, memory_supersede), letting an agent distinguish it 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.

Usage Guidelines5/5

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

It gives explicit when-not alternatives with the selecting condition for each: use memory_archive to hide while keeping the record, use memory_supersede to replace an outdated fact while keeping history. No inference is required.

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

memory_exportA
Read-only

Export the namespace's active memories (content plus metadata) as one JSON payload, for backup or migration. Archived and superseded memories are not included. The result can be large; use memory_list to page or memory_search to look things up. Read-only.

NameRequiredDescriptionDefault
typeNoOnly export one memory type (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all.
formatNoOutput format. Only json is supported (default).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, and the description reinforces this with 'Read-only' while adding real behavioral context: archived/superseded memories are filtered out and the payload can be large. It goes beyond the annotations, though it says nothing about size limits, auth requirements, or truncation risk.

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

Conciseness5/5

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

Three short sentences, front-loaded with the core action and scope, then the exclusion rule, then the alternative routing. Every sentence carries distinct information with no repetition.

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

Completeness5/5

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

With no output schema, the description carries the burden of describing the return ('one JSON payload' of content plus metadata) and does so, while also covering filtering behavior and where to go for smaller/paged reads. Nothing essential for correct invocation is missing.

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

Parameters3/5

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

Schema description coverage is 100%, with the type enum, format enum, and namespace fallback behavior all documented in the schema. The description adds no parameter-level detail beyond what the schema already provides, so the baseline 3 applies.

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

Purpose5/5

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

States a precise verb+resource ('Export the namespace's active memories ... as one JSON payload') and immediately bounds scope by excluding archived and superseded memories. An agent can distinguish this bulk dump from memory_list/memory_get without opening a schema.

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

Usage Guidelines4/5

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

Gives a use context ('for backup or migration') and names alternatives with an explicit condition: 'The result can be large; use memory_list to page or memory_search to look things up.' It lacks an explicit when-not clause (e.g., don't use for single-record retrieval), but the routing intent is clear.

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

memory_getA
Read-only

Fetch one memory by id with its full record and lifecycle fields (fact_key, version status, superseded_by). Returns { data: record }, or an error result 'Memory not found' if the id does not exist in this namespace. Use it after memory_search, memory_recall or memory_list when you need the complete record before editing. Read-only.

NameRequiredDescriptionDefault
idYesMemory id (e.g. from memory_search, memory_recall or memory_list).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered; the 'Read-only.' trailer is largely redundant. The description still adds real behavioral context beyond annotations: the exact return shape { data: record } and the 'Memory not found' error outcome for a missing id in the namespace.

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

Conciseness4/5

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

Three tight, front-loaded sentences: return value first, then error case, then usage guidance. 'Read-only.' duplicates the readOnlyHint annotation and is the one sentence that does not fully earn its place.

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

Completeness4/5

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

With no output schema, the description correctly compensates by naming the return envelope and the not-found error. Usage ordering and read-only status are also covered, leaving only minor things (e.g. behavior when the namespace is fixed by the API key) to the schema.

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

Parameters3/5

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

Schema description coverage is 100%, so both id and namespace are already documented in the schema (including the fixed-namespace behavior). The description adds meaning for 'id' only indirectly ('in this namespace'), so baseline 3 is appropriate.

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

Purpose5/5

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

States a specific verb and resource ('Fetch one memory by id') plus the payload it returns (full record with lifecycle fields fact_key, version status, superseded_by). The singular 'one memory' contrasts cleanly with the list/search siblings, so an agent can distinguish it without opening a schema.

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

Usage Guidelines5/5

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

Explicitly specifies when to call it: 'after memory_search, memory_recall or memory_list when you need the complete record before editing.' It names the sibling alternatives and the condition that selects this tool, leaving no inference required.

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

memory_ingestA

Store raw chat messages as conversation history. Memories are not extracted immediately: the nightly background pipeline (dream) reads stored messages and distills them into long-term memories later. To save a fact right away, use memory_upsert. Returns { data: { conversation_id, message_ids } }; message_ids can be passed to memory_pin as context.

NameRequiredDescriptionDefault
sourceNoLabel for where the messages came from. Defaults to 'mcp'.
messagesYesMessages in chronological order.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
auto_extractNoAccepted for compatibility only; it is not stored and does not change processing.
conversation_idNoConversation to append to. Defaults to the namespace's shared default conversation.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations mark this as a non-read-only, non-idempotent write but say nothing about timing. The description discloses the crucial asynchronous behavior (nightly 'dream' pipeline distills messages later) and the return shape, which is well beyond what the annotations convey.

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

Conciseness5/5

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

Three tight sentences: purpose first, deferred-processing caveat second, alternative and return value last. Every sentence earns its place with no filler.

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

Completeness5/5

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

Though there is no output schema, the description supplies the return shape ({ conversation_id, message_ids }) and how to use message_ids downstream. The deferred-processing model is explained, so an agent has everything needed to call and reason about the result.

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

Parameters3/5

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

Schema coverage is 100%, so parameters (source, messages, namespace, auto_extract, conversation_id) are fully documented by the schema. The description adds no per-parameter meaning, so the baseline 3 applies; the schema does the heavy lifting.

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

Purpose5/5

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

States a specific verb and resource: 'Store raw chat messages as conversation history.' It also clarifies the deferred nature of the operation and explicitly names memory_upsert as the immediate-save alternative, letting an agent distinguish it from siblings like memory_upsert or memory_search without opening schemas.

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

Usage Guidelines5/5

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

Explicitly routes the agent: 'To save a fact right away, use memory_upsert,' which gives both the when-to-use and the alternative. It also points to memory_pin as the downstream consumer of message_ids, so the usage flow is fully specified.

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

memory_listA
Read-only

Page through stored memories without a query, pinned first, then by importance, then most recently updated; optionally filtered by type or status. Returns { data, paging: { limit, has_more, next_offset } }; pass next_offset back as offset for the next page. Use memory_search or memory_recall to find memories by meaning. Read-only.

NameRequiredDescriptionDefault
typeNoOnly list one memory type (fact, event, preference, relationship, boundary, habit, decision, note).
limitNoPage size. Defaults to 100.
cursorNoLegacy paging cursor; only used when the lifecycle store is disabled. Prefer offset.
offsetNoNumber of records to skip. Use paging.next_offset from the previous page.
statusNoOnly list memories with this status: active (default), archived or superseded.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
include_idsNoLegacy mode only: also return the bare id list.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the 'Read-only' clause adds little. The real added value is behavioral: the deterministic ordering (pinned, then importance, then most recently updated) and the paging contract including next_offset round-tripping, neither of which is derivable from annotations.

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

Conciseness4/5

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

Front-loaded with the core behavior and ordering, then paging mechanics, then the alternative-tool pointer. Dense but every clause carries information; the only near-redundancy is the trailing 'Read-only', already implied by annotations.

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

Completeness4/5

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

With no output schema, the description compensates by disclosing the return shape ({ data, paging: { limit, has_more, next_offset } }) and the offset round-trip, which is what an agent needs to page. Ordering and alternative routing are covered; minor gaps like default page size or namespace binding effects are left to the schema.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents type, status, offset, cursor, namespace, limit and include_ids in detail. The description only restates type/status filtering and the offset-for-next-page pattern, adding no format or edge-case detail beyond the schema, so baseline 3 is correct.

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

Purpose5/5

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

States a specific verb and resource ('Page through stored memories') and adds the exact ordering semantics (pinned, importance, recency) plus optional type/status filtering. It also names sibling tools (memory_search, memory_recall) as the meaning-based alternatives, so an agent can route correctly without opening another schema.

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

Usage Guidelines4/5

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

Explicitly tells the agent to use memory_search or memory_recall to find memories by meaning, which cleanly carves out this tool's niche as unfiltered enumeration. It stops short of covering the other read siblings (memory_get, memory_export) or stating when-not to use this tool, so it is clear but not exhaustive.

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

memory_pinA

Save a moment as a precious entry: pinned, offered through memory_boot (which shows the 20 most recent), and never deduplicated, decayed or deleted by the automatic pipeline. Each call creates a new entry. Write the content so it still makes sense on its own later, and attach the surrounding messages via context_message_ids. For ordinary facts use memory_upsert. Returns { data: precious record }.

NameRequiredDescriptionDefault
contentYesThe moment to keep, self-contained and readable on its own.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
context_message_idsNoIds of stored messages (e.g. message_ids from memory_ingest) to keep as surrounding context.

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations: pinned, surfaced through memory_boot (20 most recent), never deduplicated/decayed/deleted by the automatic pipeline, and each call creates a new entry. This discloses durability and lifecycle behavior that annotations (which only say not read-only, not idempotent) do not convey.

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

Conciseness5/5

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

Three dense sentences, front-loaded with the core behavior, then usage guidance, then the alternative tool, then return shape. Every clause carries information; no filler.

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

Completeness5/5

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

For a 3-parameter write tool with no output schema, it covers lifecycle (durable, pinned), discoverability (memory_boot), non-idempotency (new entry each call), and return shape. Nothing essential is missing.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3. The description adds meaning beyond the schema by explaining the purpose of context_message_ids (attach surrounding messages) and the self-contained writing requirement for content, though it doesn't expand namespace semantics beyond the schema.

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

Purpose5/5

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

States a specific verb (Save/pin) and resource (a moment/precious entry) and distinguishes itself from siblings by naming memory_upsert as the tool for ordinary facts. An agent can tell this apart from memory_upsert or memory_ingest without opening schemas.

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

Usage Guidelines5/5

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

Explicitly says when to use it vs the alternative: 'For ordinary facts use memory_upsert.' It also gives a usage instruction for the content ('write so it still makes sense on its own later') and the routing via context_message_ids.

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

memory_recallA

Answer-oriented recall: matches glossary terms literally, runs hybrid search over active memories, reranks the hits and drops anything below min_score. Returns { data: { hits, glossary_hits, week_blocks, meta } }, each hit with id, score and source so you can cite or edit it. Precious entries are not searched here (they come from memory_boot). Prefer this over memory_search when you want only the relevant memories for the current question. Never changes memory content, but marks the returned memories as recently injected, which briefly lowers their rank in later automatic recall.

NameRequiredDescriptionDefault
kNoMaximum number of memory hits. Defaults to 20.
queryYesThe question or topic to recall memories for.
typesNoOnly recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types.
min_scoreNoRelevance floor applied after reranking. Defaults to the server setting (0.15).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
include_historyNoWhen true, include superseded memory versions (status/version_status=superseded). Default false.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations declare readOnlyHint=false and non-idempotent, which is surprising for a 'recall' tool; the description resolves this by explaining it 'marks the returned memories as recently injected, which briefly lowers their rank in later automatic recall' — a genuine side effect beyond structured data. It also states the return shape and that precious entries aren't searched. It does not mention auth namespace binding edge cases, but the side-effect disclosure is the key non-obvious behavior.

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

Conciseness4/5

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

Four dense sentences front-load the core mechanism and return shape, then handle routing and side effects. No wasted words, though the return-shape enumeration and side-effect clause make it slightly long; every sentence carries distinct information.

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

Completeness4/5

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

Covers mechanism, return structure, sibling routing, exclusion of precious entries, and the rank-injection side effect — comprehensive for a 6-param tool with no output schema. Minor gap: it doesn't explain namespace versus API-key binding interplay, but that is adequately handled by the schema description.

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

Parameters3/5

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

Schema coverage is 100%, so every parameter including k, types, min_score, namespace, and include_history is already documented in the schema with defaults and constraints. The description adds the pipeline context (min_score applied after reranking) but no syntax or format details the schema lacks. Baseline 3 is correct.

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

Purpose5/5

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

Names a specific verb+resource ('recall memories') and details the exact pipeline: literal glossary matching, hybrid search over active memories, reranking, and min_score filtering. This is far more specific than siblings like memory_search, and the explicit 'Prefer this over memory_search when...' clause makes the distinction operational.

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

Usage Guidelines5/5

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

Explicitly states when to use it ('when you want only the relevant memories for the current question') and names the alternative (memory_search). It also carves out the precious-entry exclusion and notes memory_boot as their source, so the agent knows not to expect them here.

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

memory_supersedeA
Destructive

Replace an outdated memory while keeping history: marks old_id as superseded (kept, and visible via memory_recall with include_history) and inserts a new active memory linked to it. The new entry inherits the old fact_key unless new_fact_key is given. If old_id does not exist, the new memory is still created and oldStatus is 'missing'. Use it when a fact changed over time; to fix a mistake in place use memory_upsert, and to remove a memory use memory_archive or memory_delete. Returns { data: { oldStatus, newId } }.

NameRequiredDescriptionDefault
old_idYesId of the memory being replaced.
reasonNoShort note on why the old memory is outdated; stored with the chain.
new_typeNoOne of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
authored_byNoE-axis signature for the new entry (hand sources only)
new_contentYesThe up-to-date memory text.
valid_as_ofNoWhen the new fact became true (ISO date or datetime).
new_fact_keyNofact_key for the new entry. Defaults to the old entry's fact_key.
response_tendencyNoE-axis: how to respond when the new memory fires

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the destructiveHint annotation by disclosing the exact mutation mechanics: the old entry is kept and remains visible via memory_recall with include_history, a new active memory is linked to it, and the fact_key is inherited unless overridden. It also documents the edge case that a missing old_id still creates the new memory with oldStatus 'missing'.

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

Conciseness4/5

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

Front-loads the core behavior and return shape in a compact sequence of sentences with no filler. Slightly dense at five sentences, but each one carries distinct information (mechanism, edge case, alternatives, return).

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

Completeness5/5

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

For a 9-parameter destructive mutation tool, the description covers the operation, its side effects on history, the edge case, sibling routing, and the return shape. Nothing an agent needs to invoke it correctly is missing, even without an output schema.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds genuine meaning: new_fact_key defaults to the old entry's fact_key, and old_id's non-existence yields a 'missing' status rather than failure. These behavioral notes exceed what the schema documents.

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

Purpose5/5

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

States a specific verb+resource ('Replace an outdated memory while keeping history') and immediately contrasts it with the sibling tools memory_upsert, memory_archive, and memory_delete. An agent can distinguish it from all siblings without opening a schema.

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

Usage Guidelines5/5

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

Explicitly states when to use it ('when a fact changed over time') and names the alternatives for adjacent scenarios ('to fix a mistake in place use memory_upsert, and to remove a memory use memory_archive or memory_delete'). No inference required.

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

memory_upsertA
Destructive

Write a refined memory immediately (no waiting for the nightly dream), keyed by fact_key. If an active memory with the same fact_key exists, its content and fields are overwritten in place and the old text is not kept; otherwise a new memory is created. To keep the old version as history, use memory_supersede. Pass authored_by (with the default source) to mark the memory as hand-authored: it ranks above distilled memories and the automatic pipeline cannot overwrite it. Returns { data: { id, created } }.

NameRequiredDescriptionDefault
tagsNoFree-form labels.
typeNoOne of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default).
sourceNoWho is writing. Leave unset (defaults to 'mcp'). authored_by is only stored when source is mcp, manual, api or remember_now.
contentYesThe memory text, one self-contained statement.
fact_keyYesStable key for this fact, e.g. 'user:favorite_coffee'. Reusing a key updates that memory. Facts about the outside world rather than the user use the prefix 'world_fact:'.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
confidenceNo0 to 1, how sure you are it is true. Defaults to 0.8.
importanceNo0 to 1, how much this matters. Defaults to 0.6.
authored_byNoE-axis signature; only honored on hand sources (mcp/manual/api/remember_now)
valid_as_ofNoWhen the fact became true (ISO date or datetime). Used as the event date in recall.
response_tendencyNoE-axis: how to respond when this memory fires

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the destructiveHint annotation by stating exactly what is lost ('the old text is not kept'), that matching fact_key overwrites fields in place, and that hand-authored memories outrank distilled ones and resist pipeline overwrites. It even discloses the return shape.

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

Conciseness4/5

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

Front-loaded with the core action and the key consequence, and each subsequent sentence carries distinct information (supersede alternative, authored_by behavior, return value). The '(no waiting for the nightly dream)' aside is slightly informal but still informative.

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

Completeness5/5

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

For an 11-parameter mutation tool with no output schema, the description covers the destructive semantics, the key alternative, the special-parameter behavior, and the response shape. Nothing essential for correct invocation is missing.

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

Parameters4/5

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

Schema description coverage is already 100%, so baseline is 3, but the description adds real meaning for authored_by (ranking behavior, pipeline protection) and clarifies the fact_key overwrite contract that the schema only hints at.

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

Purpose5/5

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

States a specific verb+resource ('Write a refined memory'), its keying mechanism (fact_key), and its timing semantics versus the nightly distillation pipeline. It is clearly distinguishable from siblings like memory_supersede and memory_ingest.

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

Usage Guidelines4/5

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

Explicitly routes the agent: 'To keep the old version as history, use memory_supersede,' and explains the authored_by path for hand-authored memories. It gives a clear context and one named alternative, though it doesn't contrast against memory_ingest or spell out when not to write at all.

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

Tool Schema Changelog

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

  1. 14 tool updatesv0.1.2
    • Changeddiary_get1 field changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedglossary_set5 fields changed
      • addedInput schema / properties / aliases / description
        Added value: +"Other spellings or names that should match this term. Replaces any existing aliases."
      • addedInput schema / properties / definition / description
        Added value: +"What the term means."
      • addedInput schema / properties / examples / description
        Added value: +"Example sentences using the term. Replaces any existing examples."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / term / description
        Added value: +"The word or phrase exactly as it is used."
    • Changedmemory_archive2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_boot1 field changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_delete2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace
        Added value: +{
        +  "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.",
        +  "type": "string"
        +}
    • Changedmemory_export3 fields changed
      • addedInput schema / properties / format / description
        Added value: +"Output format. Only json is supported (default)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / type / description
        Added value: +"Only export one memory type (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all."
    • Changedmemory_get2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace
        Added value: +{
        +  "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.",
        +  "type": "string"
        +}
    • Changedmemory_ingest7 fields changed
      • addedInput schema / properties / auto_extract / description
        Added value: +"Accepted for compatibility only; it is not stored and does not change processing."
      • addedInput schema / properties / conversation_id / description
        Added value: +"Conversation to append to. Defaults to the namespace's shared default conversation."
      • addedInput schema / properties / messages / description
        Added value: +"Messages in chronological order."
      • addedInput schema / properties / messages / items / properties / content / description
        Added value: +"Message text, or an OpenAI-style content parts array."
      • addedInput schema / properties / messages / items / properties / role / description
        Added value: +"One of user, assistant, system, tool. Other roles are dropped."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / source / description
        Added value: +"Label for where the messages came from. Defaults to 'mcp'."
    • Changedmemory_list7 fields changed
      • addedInput schema / properties / cursor / description
        Added value: +"Legacy paging cursor; only used when the lifecycle store is disabled. Prefer offset."
      • addedInput schema / properties / include_ids / description
        Added value: +"Legacy mode only: also return the bare id list."
      • addedInput schema / properties / limit / description
        Added value: +"Page size. Defaults to 100."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / offset / description
        Added value: +"Number of records to skip. Use paging.next_offset from the previous page."
      • addedInput schema / properties / status / description
        Added value: +"Only list memories with this status: active (default), archived or superseded."
      • addedInput schema / properties / type / description
        Added value: +"Only list one memory type (fact, event, preference, relationship, boundary, habit, decision, note)."
    • Changedmemory_pin3 fields changed
      • addedInput schema / properties / content / description
        Added value: +"The moment to keep, self-contained and readable on its own."
      • addedInput schema / properties / context_message_ids / description
        Added value: +"Ids of stored messages (e.g. message_ids from memory_ingest) to keep as surrounding context."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_recall5 fields changed
      • addedInput schema / properties / k / description
        Added value: +"Maximum number of memory hits. Defaults to 20."
      • addedInput schema / properties / min_score / description
        Added value: +"Relevance floor applied after reranking. Defaults to the server setting (0.15)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / query / description
        Added value: +"The question or topic to recall memories for."
      • addedInput schema / properties / types / description
        Added value: +"Only recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
    • Changedmemory_search4 fields changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / query / description
        Added value: +"What to look for, in natural language or keywords."
      • addedInput schema / properties / top_k / description
        Added value: +"Maximum number of records to return. Defaults to the server setting (50)."
      • addedInput schema / properties / types / description
        Added value: +"Only return these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
    • Changedmemory_supersede8 fields changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / new_content / description
        Added value: +"The up-to-date memory text."
      • addedInput schema / properties / new_fact_key / description
        Added value: +"fact_key for the new entry. Defaults to the old entry's fact_key."
      • addedInput schema / properties / new_type / description
        Added value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)."
      • addedInput schema / properties / old_id / description
        Added value: +"Id of the memory being replaced."
      • addedInput schema / properties / reason / description
        Added value: +"Short note on why the old memory is outdated; stored with the chain."
      • addedInput schema / properties / response_tendency / description
        Added value: +"E-axis: how to respond when the new memory fires"
      • addedInput schema / properties / valid_as_of / description
        Added value: +"When the new fact became true (ISO date or datetime)."
    • Changedmemory_upsert10 fields changed
      • changedInput schema / properties / authored_by / description
        Previous value: -"E-axis signature; only honored on hand sources (mcp/manual/api)"New value: +"E-axis signature; only honored on hand sources (mcp/manual/api/remember_now)"
      • addedInput schema / properties / confidence / description
        Added value: +"0 to 1, how sure you are it is true. Defaults to 0.8."
      • addedInput schema / properties / content / description
        Added value: +"The memory text, one self-contained statement."
      • addedInput schema / properties / fact_key / description
        Added value: +"Stable key for this fact, e.g. 'user:favorite_coffee'. Reusing a key updates that memory. Facts about the outside world rather than the user use the prefix 'world_fact:'."
      • addedInput schema / properties / importance / description
        Added value: +"0 to 1, how much this matters. Defaults to 0.6."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / source / description
        Added value: +"Who is writing. Leave unset (defaults to 'mcp'). authored_by is only stored when source is mcp, manual, api or remember_now."
      • addedInput schema / properties / tags / description
        Added value: +"Free-form labels."
      • addedInput schema / properties / type / description
        Added value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)."
      • addedInput schema / properties / valid_as_of / description
        Added value: +"When the fact became true (ISO date or datetime). Used as the event date in recall."
  2. 14 tool updatesv0.1.0
    • First observeddiary_get
    • First observedglossary_set
    • First observedmemory_archive
    • First observedmemory_boot
    • First observedmemory_delete
    • First observedmemory_export
    • First observedmemory_get
    • First observedmemory_ingest
    • First observedmemory_list
    • First observedmemory_pin
    • First observedmemory_recall
    • First observedmemory_search
    • First observedmemory_supersede
    • First observedmemory_upsert

TDQS

A4.4/5.0

Scored across 14 tools

Disambiguation4/5

The retrieval trio (memory_search, memory_recall, memory_list) overlaps at a glance, but the descriptions explicitly cross-reference each other and clarify when to use which, and the write tools (upsert, supersede, archive, delete) are carefully distinguished. memory_ingest vs memory_upsert is also well delineated. Only the subtle search/recall split keeps it from a perfect score.

Naming Consistency5/5

Every tool follows a consistent noun_verb pattern (memory_search, memory_upsert, glossary_set, diary_get). The memory_/glossary_/diary_ prefixes correspond cleanly to distinct resources rather than mixing arbitrary conventions.

Tool Count5/5

14 tools sit comfortably in the well-scoped range for a memory system, and each tool has a distinct lifecycle role (search, recall, ingest, boot, pin, upsert, supersede, archive, delete, export, glossary, diary) without obvious redundancy.

Completeness4/5

The memory lifecycle is thoroughly covered from ingest through search, edit, supersede, archive and delete, plus glossary and diary reads. Minor gaps remain: no un-archive operation (explicitly noted) and no glossary deletion or diary write tool.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides cross-device access to a persistent knowledge graph via Cloudflare Workers, enabling memory storage and retrieval through both MCP protocol and REST API with full-text search capabilities.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Self-hosted semantic memory layer for Claude and MCP-compatible AI clients. Store notes, search by meaning not keywords, and recall relevant context automatically across sessions. Runs free on Cloudflare Workers, D1, Vectorize, and Workers AI
    0
    822
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Self-hosted semantic memory for AI agents. Save worklogs, decisions, and notes via MCP, then recall them across sessions by meaning rather than keyword. Backed by Postgres + pgvector with local embeddings (multilingual-e5-base).
    1
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    A self-hosted AI memory service that shares durable project context between MCP-compatible clients such as Claude Code and Devin, via a REST API and a Streamable HTTP MCP server with tools to remember, recall, list, and forget memories.
    -