basic-memory
Basic Memory MCP server lets an AI client manage a Markdown-based knowledge base and projects.
Create, update, read, view, edit, move, and delete Markdown notes.
Read raw file content and list directory contents with depth/glob filters.
Search notes/content with pagination, type filters, dates, and search types; use compatibility
search/fetchtools.Build contextual knowledge-graph views from
memory://URIs and inspect recent activity.List, create, and delete Basic Memory projects.
Generate Obsidian canvas files to visualize nodes and connections.
Uses Markdown as the primary file format for storing knowledge, with specific patterns for semantic structure.
Works seamlessly with Obsidian for knowledge management, visualization, and editing of the Basic Memory knowledge base files.
Provides import capability for ChatGPT conversation history into the Basic Memory knowledge base.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@basic-memorycreate a note about coffee brewing methods I've been exploring"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Skip the install — try Basic Memory in the cloud
Claude, Codex, or Cursor connected in 30 seconds. No Python, no JSON, no
terminal. $15.00/mo locked in for life (12.50/mo yearly pricing). 7-day free
trial — cancel any time before day 7 if it's not for you. Beta pricing —
sign up now and your rate never goes up. OSS users: code BMFOSS takes
another 20% off for 3 months.
Basic Memory Teams is now available!
Give your team a single, shared cloud workspace. Knowledge isn't confined to one person — anything a teammate writes is immediately available to everyone else and to their AI assistants. Edit a note together in real time, hand work off between humans and agents, and build one connected knowledge base instead of scattered copies. Same pricing - start with one user and add more as needed.
Basic Memory
Your AI never forgets again.
Pick up right where you left off — in Claude, Codex, Cursor, ChatGPT, or anything that speaks MCP. Your knowledge lives as Markdown files that both you and your AI can read, write, and search.
Local-first. Plain text on your disk. Forever.
Two-way. AI and humans write to the same files; sync keeps them in step.
A real knowledge graph. Observations and wikilinks compound into context.
Semantic search. Find notes by meaning, not just keywords, with optional cross-encoder reranking for higher-quality vector and hybrid results.
MCP-native. Works with every major AI client and IDE.
Progressive tool discovery. Every tool is tagged with behavior hints (read-only, destructive, idempotent) so agents pick the right tool on demand — no wasted context trying things to see what they do.
Cloud, optional. Sync across devices when you want — never required.
Related MCP server: memora
Get started
Pick the path that fits you. Both run the same product on the same Markdown.
30 seconds. Sign up, connect your AI client, done.
Works in any browser
Mobile, web, desktop
Cross-device sync built in
We handle hosting, backups, snapshots
$15.00/mo locked for life · 7-day free trial · cancel any time
2 minutes. Install, configure your AI client, run.
Free forever (AGPL-3.0)
All data on your disk
Air-gapped friendly
Requires Python via
uv
uv tool install basic-memory --prerelease=allow--prerelease=allow is required: Basic Memory 0.23 depends on a FastMCP 4
pre-release, and uv only accepts pre-releases of transitive dependencies when
told to — without the flag it silently installs an older release. The same flag
goes on every uvx / uv tool upgrade command below.
For Postgres deployments that store semantic vectors in Milvus, install the first-party optional extra instead:
uv tool install "basic-memory[milvus]" --prerelease=allowWhat people are saying
Basic Memory changed my whole relationship with LLMs. I switched from GPT and Gemini to exclusively Claude and Claude Code because of this integration and am completely revamping all our company's processes around a Basic Memory workflow.
— Alex, TrainerDay
Basic Memory is the missing 'wow' factor in AI chatbots. Now I can't imagine Claude or Claude Code without it.
— Caleb, Caleb Picker Consulting
I don't code without Basic Memory anymore. It's such a time saver to be able to refer to projects I don't currently have active and keep a running log of all my learnings and ProTips.
— @groksrc, Developer
More on basicmemory.com.
Basic Memory Cloud
The hosted version of Basic Memory. Same product, same Markdown files, same MCP tools — we just host the database, run the sync, and put it on your phone.
What you get
Every device, same brain. Your knowledge graph on web, mobile, and desktop. No copy-paste between machines.
Connect any MCP client. Claude Desktop, Claude Code, Codex, Cursor, ChatGPT (Custom GPTs), VS Code — one-click connect from the web app.
Bidirectional sync to local. Edit on your phone, see it in Obsidian on your laptop. rclone-powered with conflict resolution.
Snapshots and backups. Point-in-time restore. Browse history. Never lose a note.
No lock-in. Your notes are plain Markdown. Export to local Markdown any time — same files, same format, same wikilinks. Cancel anytime, your data stays yours.
Built on WorkOS AuthKit, Neon Postgres, and Tigris S3.
Pricing
$15.00/mo, locked in for the life of your subscription (regular price $19). Sign up during beta and the rate never goes up — as long as you stay subscribed, you keep the price. One plan, no tiers, no surprise upgrades. Unlimited notes, unlimited projects, every feature.
7-day free trial. Cancel any time before day 7 if it's not for you.
Cancel anytime after that too — export your notes whenever you want.
OSS users: code
BMFOSSfor another 20% off for 3 months (~$11.40/mo).
Cloud vs. local
Cloud | Local | |
Setup time | 30 seconds | 2 minutes (requires Python) |
Cost | $15.00/mo, locked for life (7-day trial) | Free |
Storage | We host (Tigris S3) | Your disk |
Cross-device sync | Built in | Manual (Git, Syncthing, etc.) |
Mobile access | Yes (web + app) | No |
Air-gapped | No | Yes |
Your data stays yours | Yes — export anytime | Yes — already there |
Source code | AGPL-3.0 | AGPL-3.0 |
Snapshots & backups | Built in | Roll your own |
Both paths use the same OSS engine and the same Markdown files. There's no lock-in either way — flip between them when your needs change.
Works with the tools you already use
Client | Transport | Notes |
Cloud web app | https | Sign in at basicmemory.com — no install |
stdio/https | macOS / Windows / Linux | |
stdio/https |
| |
stdio/https | OpenAI's coding agent | |
stdio/https |
| |
stdio/https | Native MCP support | |
https | Custom GPT actions ( | |
— | Reads/writes the same Markdown directly | |
Anything MCP | stdio/https | If it speaks MCP, it works |
Official agent packages
This repository is also the canonical home for Basic Memory's host-native agent packages. The core Python package, Claude Code plugin, shared skills, Hermes plugin, and OpenClaw plugin all ship from the same source tree.
Maintainers can verify the whole consolidated surface from the repo root:
just package-checkPackage-local justfiles are also available when working inside one host:
just package-check-claude-code
just package-check-skills
just package-check-hermes
just package-check-openclawClaude Code plugin
The Claude Code plugin is the bridge between Claude's working memory and Basic
Memory — session-start briefings, pre-compaction checkpoints, an opt-in capture
output style, and /basic-memory:bm-setup · :remember · :share · :status.
Connect the Basic Memory MCP server first — see Connect your AI client. The plugin's hooks and skills call it, so it's a hard prerequisite. Then install the plugin:
bm install claude-codeThat registers the marketplace and installs the plugin through Claude Code. Add
--scope project to declare both in the repository's settings for a team, or
--dry-run to see the underlying claude plugin commands without running them.
Source: plugins/claude-code.
Shared skills
Framework-agnostic SKILL.md files live in skills/. If your
Skills CLI supports repository subdirectory sources:
npx skills add basicmachines-co/basic-memory/skills -gFor Claude and ChatGPT, upload basic-memory.zip or basic-memory-chatgpt.zip
from the skills-latest
release; see skills/README.md.
If your installed Skills CLI cannot load that source, update the CLI or copy
the memory-* directories from skills/ into your agent's skills directory.
Hermes
Hermes keeps its native plugin shape under integrations/hermes:
hermes plugins install basicmachines-co/basic-memory/integrations/hermesHermes does not install a plugin's Python dependencies, so also add the mcp
package to the Hermes venv — see the plugin README
for that step and the supported Hermes releases.
OpenClaw
OpenClaw stays package-native and publishes from
integrations/openclaw:
openclaw plugins install @basicmemory/openclaw-basic-memoryPick up where you left off
https://github.com/user-attachments/assets/a55d8238-8dd0-454a-be4c-8860dbbd0ddc
Connect your AI client
If you went the Cloud route, the web app walks you through client connect. The snippets below are for local installs.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"basic-memory": {
"command": "uvx",
"args": ["--prerelease=allow", "basic-memory", "mcp"]
}
}
}Restart Claude Desktop. Notes live in ~/basic-memory by default.
Claude Code
claude mcp add basic-memory -- uvx --prerelease=allow basic-memory mcpFor the full memory bridge — session briefings, pre-compaction checkpoints, and
the /basic-memory:* commands — also install the Claude Code
plugin on top of this.
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.basic-memory]
command = "uvx"
args = ["--prerelease=allow", "basic-memory", "mcp"]Codex can keep its default MCP approval behavior, or you can pre-approve eligible Basic Memory tools by adding this server-scoped setting to the same table:
[mcp_servers.basic-memory]
command = "uvx"
args = ["--prerelease=allow", "basic-memory", "mcp"]
default_tools_approval_mode = "approve"This does not disable Codex approvals globally or expand which Basic Memory projects the server can access. Codex still requires approval for tools that advertise a destructive annotation, including Basic Memory's writes, edits, and deletes. If you installed the Basic Memory Codex plugin, use its plugin-scoped configuration instead.
Cursor
Add to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):
{
"mcpServers": {
"basic-memory": {
"command": "uvx",
"args": ["--prerelease=allow", "basic-memory", "mcp"]
}
}
}VS Code
Add to your User Settings (JSON):
{
"mcp": {
"servers": {
"basic-memory": {
"command": "uvx",
"args": ["--prerelease=allow", "basic-memory", "mcp"]
}
}
}
}ChatGPT
Basic Memory exposes OpenAI-compatible search and fetch tools for Custom
GPT actions. See the ChatGPT integration
guide.
Obsidian
No setup. Point Obsidian at ~/basic-memory (or your project folder) and the
same wikilinks, frontmatter, and Markdown your AI writes appear in your graph
view. Edit either side — sync handles the rest.
Try a prompt:
"Create a note about our project architecture decisions."
"Find information about JWT auth in my notes."
"What have I been working on this week?"What's New
Automatic updates. Basic Memory keeps itself up to date for
uv tooland Homebrew installs;bm updatetriggers a manual check.Semantic vector search. Find notes by meaning, not just keywords. Hybrid full-text + vector ranking with FastEmbed embeddings, on SQLite or Postgres.
Optional search reranking. Rescore the strongest vector and hybrid candidates with a local FastEmbed cross-encoder or a LiteLLM-backed provider.
Schema system. Infer, validate, and diff the structure of your knowledge base with
schema_infer,schema_validate,schema_diff.Per-project cloud routing. Route individual projects through the cloud while others stay local, via API key (
bm project set-cloud).Smarter editing.
edit_noteappend/prepend auto-creates notes when missing;write_noteguards against accidental overwrites.Richer search results. Matched chunk text is included so the LLM gets context, not just hits.
FastMCP 3.0 + tool annotations. Every tool ships with MCP behavior hints (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint) so agents can discover capabilities progressively at runtime instead of guessing or burning tokens.CLI overhaul.
--jsonoutput for scripting, workspace-aware commands, and an htop-inspired project dashboard.
Full CHANGELOG for v0.18 → v0.20.
Optional cross-encoder reranking
Reranking adds a second relevance pass after vector or hybrid retrieval. It is disabled by default because it adds inference latency and, for the local provider, a first-run model download. Text, title, and permalink searches keep their existing ranking.
Enable the default local FastEmbed reranker:
export BASIC_MEMORY_RERANKER_ENABLED=trueThe default model is jinaai/jina-reranker-v1-tiny-en. To use a hosted
reranker through LiteLLM instead:
export BASIC_MEMORY_RERANKER_ENABLED=true
export BASIC_MEMORY_RERANKER_PROVIDER=litellm
export BASIC_MEMORY_RERANKER_MODEL=cohere/rerank-v3.5
export COHERE_API_KEY=...The feature fails fast on invalid configuration and does not silently fall back to retrieval order when an enabled provider fails. See the semantic search guide for provider setup, all settings, tuning, pagination, and failure behavior.
Why Basic Memory
Most LLM conversations are ephemeral. You ask a question, get an answer, then everything is forgotten. Workarounds have limits:
Chat history captures conversations but isn't structured knowledge.
RAG lets the LLM query your documents but not write back to them.
Vector DBs need complex infra and usually live in someone else's cloud.
Knowledge graphs need specialized tooling to maintain.
Basic Memory takes a simpler path: structured Markdown files that humans and LLMs both read and write.
All knowledge stays in plain files you control.
Both sides read and write to the same files.
Familiar Markdown with semantic patterns — no new format to learn.
A traversable graph the LLM can follow link by link.
Works with the editors you already use (Obsidian, VS Code, anything).
Just files plus a local SQLite index. No servers required.
How it works
You're chatting normally about coffee:
I've been experimenting with brewing methods. Pour over gives more clarity than French press, water at 205°F seems best, and freshly ground beans make a huge difference.
Ask the LLM to capture it:
"Make a note on coffee brewing methods."
A Markdown file appears in your project directory in real time:
---
title: Coffee Brewing Methods
permalink: coffee-brewing-methods
tags: [coffee, brewing]
---
# Coffee Brewing Methods
## Observations
- [method] Pour over highlights subtle flavors over body
- [technique] Water at 205°F (96°C) extracts optimal compounds
- [principle] Freshly ground beans preserve aromatics
## Relations
- relates_to [[Coffee Bean Origins]]
- requires [[Proper Grinding Technique]]
- affects [[Flavor Extraction]]Next session, the LLM picks up the thread. It follows the relations to surface what you already know about Ethiopian beans and burr grinders, and builds on it instead of starting over. You see the same files in Obsidian or your editor. Edit them by hand — the AI sees your changes too.
Real two-way flow: humans edit Markdown, LLMs read/write through MCP, sync keeps everything consistent, and the source of truth is always your files.
The Markdown format
Each file is an Entity. Entities have Observations (facts about them) and
Relations (links to other entities). That's the whole grammar.
Frontmatter
---
title: <Entity title>
type: note
permalink: <uri-slug>
tags: [optional, list]
---Observations
Facts about the entity. Categories in [brackets], tags with #, optional
context in parens.
- [method] Pour over highlights subtle flavors
- [tip] Grind medium-fine for V60 #brewing
- [fact] Lighter roasts contain more caffeine than dark
- [resource] James Hoffmann's V60 technique on YouTube
- [question] How does temperature affect compound extraction?Relations
Wiki-style links that form the graph. Single-token relation types, or quote multi-word ones.
- pairs_well_with [[Chocolate Desserts]]
- grown_in [[Ethiopia]]
- requires [[Burr Grinder]]
- "pairs well with" [[Dark Chocolate]]Bare - [[Target]] and prose - Worth checking out [[Target]] index as
links_to. Full reference in the
docs.
MCP tools
Basic Memory exposes these tools to any MCP client. Every tool is annotated with MCP behavior hints (read-only, destructive, idempotent, open-world) so agents can pick the right one without trial-and-error:
Content:
write_note,read_note,edit_note,move_note,delete_note,read_content,view_noteSearch & discovery:
search_notes,recent_activity,list_directoryKnowledge graph:
build_context(navigatesmemory://URLs)Projects:
list_memory_projects,list_workspaces,create_memory_project,delete_projectSchema:
schema_infer,schema_validate,schema_diffCompatibility & diagnostics:
search,fetch,basic_memory_diagnostics
All MCP tools default to text output; pass output_format="json" for
structured responses. Full tool reference in the
docs.
CLI essentials
# Projects
basic-memory project list
basic-memory project add research ~/research
basic-memory project set-cloud research # route through cloud
basic-memory project set-local research # revert
# Config
basic-memory config list # all settings, effective values, env overrides
basic-memory config set cli_output_style plain # validated through the config model
basic-memory config unset cli_output_style # revert to default
# Health & maintenance
basic-memory status
basic-memory doctor # report project problems and the commands that fix them
basic-memory tool edit-note ... # CLI access to MCP tools
basic-memory update # check for and install updates
# Imports
basic-memory import claude conversations
basic-memory import chatgpt
basic-memory import memory-jsonRouting flags (--local / --cloud) force a target when you're in mixed
mode. Full CLI reference in the
docs.
Auto-updates
CLI installs check for updates every 24 hours by default and apply them silently (so the MCP server keeps responding).
Supported install sources:
uv tool, HomebrewSkipped for
uvx(ephemeral runtime managed by uv)Manual:
bm update(check + apply) orbm update --check(check only)
Disable in ~/.basic-memory/config.json:
{ "auto_update": false }Telemetry
Minimal, anonymous events to understand the CLI-to-cloud conversion funnel.
What we collect: cloud promo impressions, cloud login attempts and outcomes, promo opt-out events.
What we don't: file contents, note titles, knowledge base data, PII, IP addresses, per-command or per-tool tracking.
Events go to our Umami Cloud instance (open-source, privacy-focused) on a background thread — never blocks the CLI.
Opt out:
export BASIC_MEMORY_NO_PROMOS=1This disables promos and all telemetry.
Logging
Basic Memory uses Loguru. Defaults vary by entry point:
Entry point | Default | Why |
CLI commands | File only | Doesn't interfere with command output |
MCP server | File only | Stdout would corrupt JSON-RPC |
API server | File (local) or stdout (cloud) | Docker/cloud uses stdout |
Log file: ~/.basic-memory/basic-memory.log (10MB rotation, 10 days
retention).
Environment variables
Variable | Default | Description |
|
| DEBUG / INFO / WARNING / ERROR |
|
| API logs to stdout with structured context |
|
| Force local API routing |
|
| Force cloud API routing |
|
| Mark route selection as explicit |
|
| Set to |
|
| Disable cloud promos and telemetry |
|
| Max uploaded import size |
BASIC_MEMORY_LOG_LEVEL=DEBUG basic-memory reindex
tail -f ~/.basic-memory/basic-memory.logDevelopment
Basic Memory supports SQLite (default, fast, no Docker) and Postgres (via testcontainers — Docker required).
just install # Install with dev dependencies
just test-sqlite # All tests, SQLite
just test-postgres # All tests, Postgres (testcontainers)
just test # Both backends
just fast-check # fix/format/typecheck + impacted tests
just doctor # File <-> DB consistency check (temp config)
just package-check # Claude Code, skills, Hermes, OpenClaw package checks
just lint
just typecheck # Pyright (primary)
just typecheck-ty # ty (supplemental)
just format
just check # All quality checks
just migration "msg" # New Alembic migrationTests use pytest markers: windows, benchmark, smoke. See
justfile for the full list.
Contributions welcome — see CONTRIBUTING.md.
License
Built with ♥️ by Basic Machines
Available Tools
38 toolsbasic_memory_diagnosticsBasic Memory DiagnosticsARead-only
Return version, system, and configuration diagnostics for Basic Memory.
Provides:
Basic Memory package version
Python version and platform details
Config file path and its contents (secrets redacted)
BASIC_MEMORY_* environment variables that override the file at runtime
Useful for troubleshooting installations and gathering information for support requests. Read-only; never emits secrets or API keys.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=false, so the safety profile is covered. The description earns credit for details annotations cannot express: config file contents are returned with secrets redacted, and it never emits secrets or API keys — the key behavioral concern for a tool that dumps configuration. It slightly restates read-only, but the redaction guarantee is genuinely additive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence, then a scannable bullet list of what is returned, then a use-case line. Every element earns its place except the trailing 'Read-only', which merely echoes readOnlyHint=true already in the annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing returns and does so by enumerating the diagnostic sections. It stops short of indicating the response shape (structured object vs. formatted text) or approximate payload size, which is a minor gap for a config-dumping tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate. It correctly signals a no-argument invocation by omission, and 'additionalProperties: false' in the schema confirms no inputs are accepted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb-and-resource pairing: 'Return version, system, and configuration diagnostics for Basic Memory', followed by an explicit enumeration of the payload (package version, Python/platform, config path and contents, BASIC_MEMORY_* env vars). No sibling tool in the list is a diagnostics tool, so it is unambiguously distinguishable from the note/project/schema tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names a concrete use case — 'troubleshooting installations and gathering information for support requests' — which tells the agent when to reach for it. It does not state exclusions or name an alternative, but no sibling overlaps with this behavior, so the omission is low-risk.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_contextBuild contextARead-onlyIdempotent
Follow the Basic Memory knowledge graph from a note: the note, its observations, and the notes its relations reach, up to depth hops (1-5). identifier is a path, permalink, memory:// URL, or a pattern such as 'specs/*'. since limits related results to recent changes. compact returns the graph without note bodies; read chosen notes with bm_read.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number. | |
| depth | No | Relation hops to follow (1-5). | |
| since | No | How far back to look: '7d', '24h', '2 days ago', 'last week', or a date. Windows shorter than one day are widened to one day. | 7d |
| compact | No | Omit note bodies and observations; keep the graph shape. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| page_size | No | Primary results per page (1-50). | |
| identifier | Yes | Where to start: a note path, permalink, memory:// URL, or a pattern such as 'specs/*'. | |
| max_related | No | Most related results to return (0-100). | |
| output_format | No | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly, idempotent, non-destructive, closed-world behavior, so the bar is lower. The description still adds real value beyond them: what `compact` strips, that `depth` bounds traversal at 5 hops, and that `since` narrows related results. It does not discuss pagination behavior across primary vs related results, which is left to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences: traversal scope first, then the identifier contract, then the time filter, then the compact/read split. Every sentence carries operative information and none repeats the tool title back at the reader.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be described. Required input is a single identifier, which is fully specified, and the highest-leverage optional knobs (depth, since, compact) are explained. The remaining params are low-risk tuning values documented in the schema at 89% coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 89%, so the baseline is 3; the description goes further by enumerating the identifier formats (path, permalink, memory:// URL, glob pattern), clarifying that `since` applies to related results rather than the root note, and explaining the practical consequence of `compact`. Page, page_size, max_related and project are left to the schema, which is acceptable at this coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: follow the Basic Memory knowledge graph from a note, returning the note, its observations, and notes reached by relations up to `depth` hops. It also distinguishes itself from bm_read by naming that sibling as the way to read full note bodies, so an agent can tell the two apart 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for use (graph traversal from a starting note, with `compact` for a body-free view) and explicitly routes follow-up reading to bm_read. It does not state when NOT to use this versus search_notes or bm_search, so it falls short of a full when/when-not/alternative treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_deleteDelete noteADestructiveIdempotent
Delete a Basic Memory note (identifier) or a directory (path). A directory delete removes every file under it and needs recursive=true. Pass expected_checksum (from bm_read) to delete a note only if it is still the revision you read. A note that does not exist is an error. This cannot be undone.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | The directory to delete, with everything in it. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| recursive | No | Required true to delete a directory and everything under it. | |
| identifier | No | The note to delete: a path, permalink, memory:// URL or exact title. | |
| output_format | No | text | |
| expected_checksum | No | Delete the note only while it is still this revision (from bm_read). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the bar is lower, yet the description still adds real value: irreversibility, the cascading scope of a directory delete, and the error behavior for a missing note. It stops short of noting permission requirements or what the response reports after deletion.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, each carrying a distinct rule — target selection, recursive requirement, concurrency guard, error case, and irreversibility. No filler and the destructive warning lands at the end where it is read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the description covers both deletion modes, the safety precondition, and failure semantics. Only the project-scoping parameter and post-delete response behavior are left entirely to structured fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 83%, so the schema already documents most parameters. The description reinforces the identifier/path split and the checksum's provenance from bm_read, but says nothing about `project` or `output_format`, so it only marginally exceeds the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb plus two clearly delineated resources: a note via `identifier` or a directory via `path`. The description makes the two deletion modes and their parameter mapping explicit, which distinguishes it from read/edit siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete conditional rules: `recursive=true` is required for directories, and `expected_checksum` (sourced from bm_read) guards against concurrent modification. It does not name or rule out alternatives such as the sibling `delete_note`, so routing is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_editEdit noteADestructive
Change part of an existing Basic Memory note. command: append or prepend content; find_replace find_text with content (exact text, which must occur expected_replacements times, default 1); replace_section, insert_before_section or insert_after_section for a section heading ('Decisions', 'Auth/Decisions', 'Decisions[1]', as bm_read takes it); set_metadata to merge metadata into the frontmatter without touching the body. metadata also merges with any other command. Pass expected_checksum (from bm_read) to edit only the revision you read. A missing note is an error; create notes with bm_write.
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | The edit. | |
| content | No | The text to add or the replacement. Not used by set_metadata. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| section | No | The heading for section commands: "Decisions", "Auth/Decisions" for one under "Auth", or "Decisions[1]" for the second of two. | |
| metadata | No | Frontmatter fields to set; other fields are kept. | |
| find_text | No | For find_replace: the exact, case-sensitive text to replace. | |
| identifier | Yes | The note or file: a file path ('notes/plan.md'), permalink, memory:// URL, exact title, external id, or '<project>/path'. | |
| output_format | No | text | |
| expected_checksum | No | Edit only while the note is still this revision (from bm_read). | |
| replace_subsections | No | For replace_section: true replaces the section's subsections too; false stops at the first subsection heading. | |
| expected_replacements | No | For find_replace: how many times find_text must occur. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as destructive, non-read-only, and non-idempotent. The description adds useful behavior beyond those hints: optimistic concurrency via expected_checksum, exact replacement-count enforcement, missing-note errors, and metadata merging without touching the body. It does not call out that replace_section may remove subsections by default, though the schema documents that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded and appropriate for a seven-command editing tool. Every sentence adds operational detail, and the command mapping is organized efficiently despite the compact paragraph form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema, output schema, and annotations, the description covers the critical editing semantics and error behavior. Minor gaps remain around explicitly warning about replace_subsections' destructive default and fully differentiating from the edit_note sibling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is high, but the description adds cross-parameter meaning that is not obvious from individual field descriptions: how command selects content, find_text, section, metadata, and expected_checksum behavior, including that metadata merges with any command and expected_checksum comes from bm_read.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb, resource, and scope: changing part of an existing Basic Memory note. It also distinguishes creation by directing missing notes to bm_write, but it does not explicitly differentiate itself from the sibling edit_note tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states that missing notes are errors and should be created with bm_write, and it references bm_read for checksums and section syntax. It does not give an explicit when-not rule against using sibling tools such as edit_note.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_findFind filesARead-onlyIdempotent
Find files in a Basic Memory project, recursively. With name, match file names against a glob ('meeting'). With filters, match notes by frontmatter, e.g. {"status": "active"} or {"priority": {"$in": ["high"]}}, and with fields return just those frontmatter values per note. path limits the search to a folder. For ranked text or meaning search, use bm_search.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | File-name glob, e.g. '*.md'. Not with `filters`. | |
| page | No | Page number. | |
| path | No | A directory in the project, e.g. 'specs' or 'specs/active'. '/' is the project root; '<project>/path' addresses another project. | / |
| depth | No | Folder levels to search (1-10). | |
| fields | No | Frontmatter fields to return per note (dot paths allowed), e.g. ["title", "priority"]. Needs `filters`. | |
| filters | No | Frontmatter filters as {field: condition}. Nested fields use dot notation ("schema.confidence"). A condition is a value for equality ({"status": "draft"}), null for absent-or-null ({"owner": null}), a list for contains-all ({"tags": ["a", "b"]}), or an operator object with $gt, $gte, $lt, $lte, $in, $between, $contains or $exists, e.g. {"priority": {"$in": ["high"]}}. Several operators on one field AND together. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| page_size | No | Results per page (1-100). | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive, closed-world behavior. The description adds useful operational context: recursive search, path scoping, frontmatter filtering, and projecting selected fields, though it does not restate pagination behavior or the `fields`-requires-`filters` constraint that appears in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then efficiently covers the main modes and the alternative tool. Every sentence earns its place, with no filler or repeated annotation metadata.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a nine-parameter read-only search tool with a rich input schema, an output schema, and strong annotations, the description covers the essential selection and invocation context. It leaves pagination and some parameter interactions to the schema, which is acceptable given the 89% coverage but prevents a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 89%, so the schema already documents most parameters thoroughly, including the detailed `filters` operator grammar. The description reinforces `name`, `filters`, `fields`, and `path` with examples but does not add significant meaning beyond the schema, so the high-coverage baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: find files in a Basic Memory project, recursively. It clearly distinguishes its modes (`name` glob, `filters` frontmatter matching, `fields` projection) and explicitly routes ranked text/meaning search to `bm_search`, so an agent can tell it apart from that sibling without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage context for each major mode and names the alternative for ranked text or meaning search: use `bm_search`. It does not explicitly state the `name`/`filters` mutual exclusion in prose, although the schema does, so it falls short of fully explicit when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_listList folderARead-onlyIdempotent
List one folder of a Basic Memory project: its subfolders, then its files with title, date and id. bm_list('/') with no project lists the projects you can address; '/path' lists inside another project. Filter files with glob and order them with sort. For a recursive search by name or frontmatter, use bm_find.
| Name | Required | Description | Default |
|---|---|---|---|
| glob | No | File-name glob, e.g. '*.md' or '*meeting*'. | |
| page | No | Page number. | |
| path | No | A directory in the project, e.g. 'specs' or 'specs/active'. '/' is the project root; '<project>/path' addresses another project. | / |
| sort | No | File order. Folders always come first. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| page_size | No | Results per page (1-100). | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral detail beyond that: ordering guarantees ('subfolders, then its files'), the fields returned per file, and cross-project addressing. It does not mention pagination behavior, which is the one notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core behavior, then addressing rules, then the sibling redirect. No filler and no repetition of schema text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 7 optional parameters, rich annotations and an output schema, the description covers the essentials an agent needs to pick and call this tool. The only missing piece is that results are paginated (page/page_size defaults), which an agent could otherwise miss.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is high at 86%, so the baseline is 3. The description still adds real meaning: it clarifies the special '/' form and the '<project>/path' cross-project addressing convention, and explains that glob and sort apply to files (not folders).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List one folder of a Basic Memory project') and immediately specifies the return shape: subfolders first, then files with title, date and id. It also explicitly distinguishes itself from the sibling bm_find, which does recursive name/frontmatter search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage context: `bm_list('/')` with no project lists addressable projects, '<project>/path' lists inside another project. It names the alternative (bm_find) and the condition that selects it, plus notes where filtering (glob) and ordering (sort) belong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_manManualARead-onlyIdempotent
Read the Basic Memory manual. With no arguments, the index of every page. page reads one page: 'bm-search(3)' for an MCP tool, 'grep(1)' for a shell command; a tool name such as 'bm_search' works too. query lists the pages that mention every word given, like man -k.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | The page to read, e.g. 'bm-search(3)', 'grep(1)' or 'bm_search'. | |
| query | No | Words to find in the manual; lists the pages that mention them all. | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, closed-world behavior. The description adds useful mode behavior beyond that: no-argument invocation returns an index, `page` reads exactly one page, and `query` lists pages matching every word. It does not discuss output formatting or error behavior, but the annotations cover the safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action and then mode-specific details. There is no filler; every sentence adds usable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only manual tool with an output schema and strong annotations, the description covers all three invocation modes and enough examples to call it correctly. Minor gaps remain: no explicit sibling differentiation from `man`, and `output_format` is only inferable from the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%, and the schema already documents `page` with examples and `query` with AND-matching semantics. The description largely repeats those examples and adds the `man -k` analogy, but does not cover the undocumented `output_format` parameter. A baseline 3 is appropriate since the schema does most of the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read the Basic Memory manual.' It then distinguishes the three invocation modes (index, page, query), so an agent can tell this apart from note-reading or shell-manual siblings by resource scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains how the modes behave: no arguments returns the index, `page` reads one page, `query` searches pages by all given words. It gives examples such as 'bm-search(3)' and 'man -k', but does not explicitly say when to use this versus sibling tools like `bm_search` or `man`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_moveMove noteA
Move or rename a Basic Memory note (identifier) or a directory (path) within its project. destination is the new project-relative path; ending it with '/' moves into that folder under the current name ('archive/'). A note keeps its file extension ('.markdown' may become '.md'). Pass expected_checksum (from bm_read) to move a note only if it is still the revision you read. Moving into another project is refused: bm_read, bm_write there, then bm_delete.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | The directory to move, with everything in it, e.g. 'drafts/2025'. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| identifier | No | The note to move: a path, permalink, memory:// URL or exact title. | |
| destination | Yes | New path, e.g. 'archive/plan.md'. A trailing '/' ('archive/') moves the note or directory into that folder under its current name. | |
| output_format | No | text | |
| expected_checksum | No | Move the note only while it is still this revision (from bm_read). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-destructive, non-idempotent mutation but say nothing about mechanics; the description fills that gap with extension rewriting, trailing-slash semantics, and optimistic concurrency via `expected_checksum` gated on the revision from bm_read. It also discloses the cross-project refusal rule, which an agent would otherwise only learn from a failed call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences, each carrying distinct information: scope, destination semantics, extension rule, concurrency guard, and the cross-project exclusion. Front-loaded with the core action and no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter mutation tool with an output schema that covers return values, the description supplies everything an agent needs before calling: target selection, path formatting, concurrency safety, and the unsupported cross-project case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 83%, and the description adds real meaning on top: `destination` is project-relative, a trailing '/' changes its interpretation to a parent folder, and `expected_checksum` acts as a conditional guard rather than a plain value. `project` and `output_format` are left to the schema, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair (move/rename) and resource (a note or a directory), and binds each to its own parameter (`identifier` for notes, `path` for directories). An agent can tell what this does and which input shape applies without reading the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly rules out the cross-project case and prescribes the alternative workflow ('bm_read, bm_write there, then bm_delete'), which is genuine when-not guidance. It does not, however, differentiate itself from the sibling `move_note` tool, leaving a real ambiguity unresolved.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_projectProjectsA
Basic Memory projects. command: list (projects, grouped by workspace); create (name, path, optional set_default, workspace); recent (what changed lately: since, items, paging; project picks the project, else the default project, and with no default every project).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | For create: the new project's name. | |
| page | No | Page number. | |
| path | No | For create: the folder that holds the project's notes. | |
| items | No | What to return: notes, observations, relations, or a mix. Default: notes. | |
| since | No | How far back to look: '7d', '24h', '2 days ago', 'last week', or a date. Windows shorter than one day are widened to one day. | 7d |
| command | Yes | What to do. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| page_size | No | Results per page (1-100). | |
| workspace | No | In Cloud: the workspace slug, name or id that holds the project. | |
| set_default | No | For create: make the new project the default. | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false, so the safety profile is already carried by structured data. The description adds nothing about what `create` actually does to the filesystem — whether `path` must already exist, whether a directory is made, what happens on name collision, or whether creation can be undone. Since it is a non-destructive but non-read-only and non-idempotent tool, those omissions matter somewhat, but no contradiction exists with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Everything is packed into a single front-loaded block with the command enum stated first, and no sentence is filler. The heavy nested-parenthesis style is dense but still parseable, costing a small amount of readability rather than correctness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the 11-parameter surface is large but mostly routed by the description. What remains thin is the create path semantics and the difference from the sibling project tools; both are real but secondary gaps rather than blockers to a correct call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 91%, so the baseline is 3, and the description earns a step above it by mapping parameters to commands (name/path/set_default/workspace belong to create; since/items/paging/project to recent) and by spelling out the `project` resolution chain: explicit project, else default project, else all projects. That cross-parameter precedence is not visible in the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates the three multiplexed operations (list, create, recent) and the resource is unambiguous: projects, grouped by workspace. An agent can tell what each command does without opening the schema. However, it never distinguishes this tool from overlapping siblings like list_memory_projects, create_memory_project, or recent_activity, so the agent must guess which entry point is canonical.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through per-command parameter mapping (list groups by workspace; recent falls back to the default project, or every project if none is set). That last clause is the only real selection rule given. There is no explicit when-to-use-this-instead-of guidance despite three sibling tools that appear to cover the same three operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_readRead noteARead-onlyIdempotent
Read a Basic Memory note or file by path, permalink, memory:// URL or exact title. Slice a long note with section (a heading), start_line/end_line or max_tokens; line numbers count the whole file, frontmatter included. include_content=false returns only the metadata and the checksum that bm_write and bm_edit take as expected_checksum. Images come back as images and other binary files as documents. A missing note is an error: find notes with bm_search.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| section | No | A heading to read: "Decisions", "Auth/Decisions" for a heading under "Auth", or "Decisions[1]" for the second "Decisions" heading. | |
| end_line | No | ||
| identifier | Yes | The note or file: a file path ('notes/plan.md'), permalink, memory:// URL, exact title, external id, or '<project>/path'. | |
| max_tokens | No | Approximate token budget. Longer content is cut at a section or paragraph boundary, and the result says which line to continue from. | |
| start_line | No | ||
| output_format | No | text | |
| include_content | No | False returns only title, paths, checksum and updated_at. | |
| include_frontmatter | No | Include the YAML frontmatter in a whole-note read. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), yet the description still adds real behavioral facts: line numbers count the whole file including frontmatter, max_tokens cuts at a section/paragraph boundary and returns a continuation line, images return as images and binaries as documents, and a missing note raises an error.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the identity (what it reads, from what forms) before slicing options and the error/alternative note. Dense and largely waste-free, though the sentence about images/binaries sits slightly apart from the main reading flow.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter read tool with no output schema, the description covers input forms, slicing controls, truncation behavior, and metadata-only mode. Only the text/json output_format switch and include_frontmatter semantics are left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 67% schema coverage, the description goes beyond it by explaining that line counts include frontmatter (a semantics the schema omits), how max_tokens truncation behaves, and that include_content=false yields the checksum expected by bm_write/bm_edit. Minor gap: output_format and include_frontmatter are left entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Read) and resource (Basic Memory note or file) and enumerates the accepted identifier forms (path, permalink, memory:// URL, exact title), so an agent can match inputs to it immediately. It also distinguishes itself from the discovery sibling by routing missing notes to bm_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear condition for the alternative ('A missing note is an error: find notes with bm_search') and explains the include_content=false mode as the checksum-fetch path used by bm_write/bm_edit. It does not, however, disambiguate against lookalike siblings such as read_note, view_note, or read_content.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_schemaNote schemasARead-onlyIdempotent
Basic Memory note schemas (Picoschema). command: validate notes against their schema (one note_type, one note by identifier, or every type that has a schema); infer a schema from the notes of a note_type; diff a note_type's notes against its schema to find drift. A schema is a note with type: schema whose entity field names the note type it describes.
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | What to do. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| note_type | No | The frontmatter `type:` to check. Required for infer and diff. | |
| threshold | No | For infer: the share of notes a field must appear in to be suggested. | |
| identifier | No | For validate: one note, instead of a whole note type. | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuine domain context the annotations can't: that a schema is itself a note with type: schema whose `entity` field names the type it describes. Return values needn't be explained given an output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and a tight, per-command enumeration, then a definitional sentence. It is a dense run-on with some nested parentheticals, but every sentence carries useful information and nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter, mutation-free, multi-mode tool with an output schema and full annotation coverage, the description supplies the one thing structured fields can't: the Picoschema concept and the command-to-target mapping. Omission of `project` and `threshold` is acceptable since the schema documents them well.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (83%), so the schema already documents every parameter, including the enum values and threshold semantics. The description's mention of `note_type` and `identifier` largely restates what is in the schema, and it never touches `project` or `threshold`. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (Basic Memory note schemas / Picoschema) and states the three concrete operations (validate, infer, diff) with the object each acts on. An agent can tell what this tool does without opening the schema. It does not, however, distinguish itself from the sibling schema_validate / schema_infer / schema_diff tools, which cover the same operations individually.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Each of the three `command` values is given an explicit usage condition: validate covers one note_type, one note by identifier, or every type with a schema; infer derives a schema from a note_type's notes; diff finds drift against a note_type's schema. What's missing is any statement of when to prefer this multi-command tool over the per-command siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_searchSearch notesARead-onlyIdempotent
Search a Basic Memory project, ranked by relevance. query supports quoted phrases, AND/OR/NOT and tag:name. mode picks hybrid (the default when semantic search is available), text, semantic, title or permalink (globs with *). Narrow with filters (frontmatter), note_types, items (notes, observations, relations) and since. lines returns the matching lines of each hit with that many lines of context, like grep. path limits the search to a folder; identifier searches one note. Read full notes with bm_read.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Search mode. | |
| page | No | Page number. | |
| path | No | Search only this folder and its subfolders. | |
| items | No | What to return: notes, observations, relations, or a mix. Default: notes. | |
| lines | No | Return each hit's matching lines with this many lines of context (0-10), instead of a match excerpt. | |
| query | No | What to search for. Omit to search by filters alone. | |
| since | No | How far back to look: '7d', '24h', '2 days ago', 'last week', or a date. Windows shorter than one day are widened to one day. | |
| compact | No | Omit note bodies and excerpts; keep identifiers and scores. | |
| filters | No | Frontmatter filters as {field: condition}. Nested fields use dot notation ("schema.confidence"). A condition is a value for equality ({"status": "draft"}), null for absent-or-null ({"owner": null}), a list for contains-all ({"tags": ["a", "b"]}), or an operator object with $gt, $gte, $lt, $lte, $in, $between, $contains or $exists, e.g. {"priority": {"$in": ["high"]}}. Several operators on one field AND together. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| projects | No | Search these projects together. | |
| valid_at | No | Specialist: only facts whose authored valid time contains this date. | |
| page_size | No | Results per page (1-100). | |
| time_kind | No | Specialist: effective, valid, occurred, due or mentioned. | |
| categories | No | Observation categories to match exactly, e.g. ['decision']. | |
| identifier | No | Search only this note; returns its matching lines. | |
| note_types | No | Frontmatter `type` values, e.g. ['person', 'meeting']. | |
| max_matches | No | Matching lines shown per note with `lines`. | |
| all_projects | No | Search every project you can access. | |
| output_format | No | text | |
| min_similarity | No | Override the semantic similarity floor (0-1). | |
| valid_overlaps | No | Specialist: only facts whose valid range overlaps '[start,end)'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), so the description only needs to add operational context, which it does: results are ranked by relevance, the default mode is hybrid when semantic search is available, and `lines` produces grep-like line output instead of excerpts. Pagination behavior (page/page_size) is left entirely to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core search statement and ranking, then grouped by concern (query syntax, mode, narrowing, line output, scoping, alternative tool). Dense backtick-heavy phrasing for 22 parameters, but no sentence is redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, return values need no explanation, and the description covers the main decision points: mode selection, narrowing dimensions, and the handoff to bm_read. Only pagination and the specialist temporal/similarity parameters are unmentioned, and those are self-documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 95%, so the baseline is 3; the description exceeds it by explaining query syntax (quoted phrases, AND/OR/NOT, tag:name), the meaning of each mode including permalink globs, and the intent of filters/path/identifier/lines. Specialist parameters (valid_at, time_kind, valid_overlaps, min_similarity, compact, pagination) get no prose treatment, but they are documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Search a Basic Memory project, ranked by relevance') and immediately lists the dimensions that characterize the operation (modes, filters, line output). It routes to bm_read for full notes, so the agent can separate search from retrieval, though other similar siblings (search_notes, bm_find, grep) are never distinguished.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear when-to-use signals for each mode ('hybrid (the default when semantic search is available)', permalink 'globs with *'), says query can be omitted to search by filters alone, and points to bm_read for reading full notes. It stops short of any when-NOT-to-use guidance or comparison against the overlapping search_notes/bm_find siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bm_writeWrite noteADestructive
Create or replace a Basic Memory note. Give a file path as identifier ('notes/plan.md'), or title plus directory. With a path the file lands exactly there and the title comes from the content's frontmatter, then title, then the file name. An existing note is an error unless overwrite=true; pass expected_checksum (from bm_read) to replace only the revision you read. To change part of a note use bm_edit. Content may hold frontmatter, observations ('- [category] fact #tag') and relations ('- relation_type [[Other Note]]').
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Tags, as a list or 'a,b,c'. | |
| title | No | Note title. With `directory`, it also names the file. With `identifier`, it is used when the content has no frontmatter title. | |
| content | Yes | The note's Markdown. Saved as given; it may start with frontmatter. | |
| project | No | Project name, 'workspace/project', or project external id. Omit to use the default project. | |
| metadata | No | Extra frontmatter fields, merged into the note's frontmatter. | |
| directory | No | Folder for a note addressed by title, e.g. 'meetings'; '/' is the root. | |
| note_type | No | Frontmatter `type:`. A `type:` in the content wins. | note |
| overwrite | No | Replace a note that already exists. Default: the write_note_overwrite_default setting (false unless changed). | |
| identifier | No | File path for the note, e.g. 'notes/plan.md'; '.md' is added when missing. '<project>/path' writes into another project. Use instead of title + directory. | |
| output_format | No | text | |
| expected_checksum | No | Replace the note only while it is still this revision (the checksum from bm_read). Implies overwrite=true. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true and non-idempotent, but the description adds important behavior: an existing note is an error unless overwrite=true, and expected_checksum allows replacing only the revision read. It also explains title fallback behavior, which materially improves safe invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded, starting with the core create-or-replace behavior before addressing modes, overwrite rules, and content format. Every sentence contributes operational guidance without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter write tool with rich annotations, high schema coverage, and an output schema, the description supplies the critical missing behavioral context around addressing, conflict handling, and safe replacement. No essential invocation detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 91%, so the schema does most parameter documentation. The description still adds meaning beyond the schema by clarifying identifier path behavior, title precedence, overwrite defaults, and how expected_checksum relates to bm_read.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create or replace a Basic Memory note.' It also distinguishes the tool from bm_edit for partial changes and explains the two addressing modes, so an agent can identify its role without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states when to use identifier versus title plus directory, when overwrite is required, and that partial edits belong to bm_edit. It stops short of broader when-not guidance against other siblings, but the critical usage conditions are explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_contextBuild ContextARead-only
Build context from a memory:// URI to continue conversations naturally.
Use this to follow up on previous discussions or explore related topics.
Memory URL Format:
- Use paths like "folder/note" or "memory://folder/note"
- Pattern matching: "folder/*" matches all notes in folder
- Valid characters: letters, numbers, hyphens, underscores, forward slashes
- Avoid: double slashes (//), angle brackets (<>), quotes, pipes (|)
- Examples: "specs/search", "projects/basic-memory", "notes/*"
Timeframes support natural language like:
- "2 days ago", "last week", "today", "3 months ago"
- Or standard formats like "7d", "24h"
Format options:
- "json" (default): Structured JSON with internal fields excluded
- "text": Compact markdown text for LLM consumption
Queries the Basic Memory knowledge base API — see
https://docs.basicmemory.com/concepts/memory-urls
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | memory:// URI pointing to discussion content (e.g. memory://specs/search), or a bare permalink path. | |
| page | No | Page number of results to return (default: 1) | |
| depth | No | How many relation hops to traverse (1-3 recommended, maximum: 5) | |
| compact | No | Omit note bodies and entity observation lists for graph discovery; the server skips loading observations. Preserve identifiers, relation targets and pagination; use read_note for selected content. Not a guaranteed token budget. | |
| project | No | Project name to build context from. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| page_size | No | Number of primary results to return per page (default: 10, maximum: 50) | |
| timeframe | No | How far back to look. Supports natural language like "2 days ago", "last week" | 7d |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| max_related | No | Maximum total related results to return (default: 10, maximum: 100) | |
| output_format | No | Response format - "json" for structured JSON dict, "text" for compact markdown text | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered structurally. The description adds that 'json' excludes internal fields and 'text' is compact markdown, but says nothing about pagination limits, relation-traversal cost, or what 'context' actually contains beyond the output schema. Adequate, not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and primary usage are front-loaded, but the bulk of the text is a bulleted URL/timeframe/format reference that largely restates the 100%-covered schema. It is organized but padded; a third of the length would still carry the same information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 10 parameters, an output schema, and full annotations, the description covers the one high-risk input (URL syntax) and the timeframe format thoroughly. Remaining gaps — depth semantics and pagination interaction with max_related — are minor since the schema and output schema cover them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline would be 3; the description earns above baseline by documenting memory URL pattern matching ('folder/*'), allowed and forbidden characters, natural-language timeframes, and the json-versus-text output distinction in more concrete terms than the schema. It still does not explain 'depth' traversal semantics, which the schema only sketches.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Build context from a memory:// URI') with the intended outcome ('continue conversations naturally'). It does not, however, distinguish itself from siblings such as search_notes, read_note, or bm_context, so an agent must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use this to follow up on previous discussions or explore related topics' implies a scenario but never names an alternative tool or an exclusion condition (e.g., when to prefer search_notes or read_note instead). Usage is inferable but not routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
catCatBRead-only
Print a note's content. Accepts '/path' identifiers.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name. Optional - the server resolves the default. | |
| section | No | Heading to slice to: "Decisions", path form "Auth/Decisions" to disambiguate by parent, or bracket form "Heading[1]" for the second duplicate heading. Cannot combine with start_line/end_line; the response's start_line/end_line support follow-up range reads. | |
| end_line | No | Last line to include (inclusive). Defaults to the last line. | |
| identifier | Yes | Note title, permalink, memory:// URL, or '<project>/path' identifier (resolved exactly). | |
| max_tokens | No | Approximate token budget. Longer content is truncated at a section or paragraph boundary with an explicit ellipsis marker; the response carries truncated/continue_line for resuming. | |
| project_id | No | Project external_id (UUID); takes precedence over `project`. | |
| start_line | No | First line to include (1-indexed, inclusive). | |
| include_frontmatter | No | Include the YAML frontmatter block in `content`. Ignored for section/max_tokens reads — those slices never carry a frontmatter block. A start_line/end_line range combined with max_tokens addresses the full document (frontmatter included) and therefore requires include_frontmatter=True. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description itself adds little behavioral context beyond saying it prints content; it does not explain range reads, section slicing, truncation, or frontmatter handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences, front-loaded with the action and followed by the identifier form. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has rich schema coverage, an output schema, and clear annotations, so the short description is not required to explain return values or parameter details. Still, for a read tool with several close siblings, the description omits enough selection guidance to be only minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents identifier, section, start_line, end_line, max_tokens, include_frontmatter, project, and project_id. The description only reiterates the "<project>/path" identifier form, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Print a note's content." It also names the accepted identifier form. However, it does not distinguish this tool from overlapping siblings such as read_note, view_note, or read_content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives only the accepted identifier syntax, not when to use this tool versus alternatives. There is no guidance about when to prefer cat over read_note, view_note, read_content, or bm_read.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_memory_projectCreate Memory ProjectB
Create a new Basic Memory project.
Creates a new project with the specified name and path. The project directory will be created if it doesn't exist. Optionally sets the new project as default.
| Name | Required | Description | Default |
|---|---|---|---|
| workspace | No | Optional cloud workspace selector to create the project in. Slug is preferred for AI callers, but tenant_id and unique name are also accepted. When omitted, the connection's default workspace is used. Discover values via `list_workspaces`. A workspace selector implies cloud routing: without cloud credentials the call fails fast instead of silently creating a local project. | |
| set_default | No | Whether to set this project as the default (optional, defaults to False) | |
| project_name | Yes | Name for the new project (must be unique) | |
| project_path | Yes | File system path where the project will be stored | |
| output_format | No | "text" returns human-readable result text. "json" returns structured project creation metadata. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so the write/safety profile is covered. The description adds genuinely useful side-effect context that annotations do not carry: the project directory is created if missing, and the optional change to the global default project. It omits error behavior for duplicate names and the fail-fast cloud routing noted only in the workspace schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action, with no filler. The opening line partially duplicates the title and the second sentence repeats 'Creates a new project', a minor redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and annotations cover the safety profile, so return values and read/write nature need not be explained. The description covers the key filesystem and default-state side effects; what is missing is guidance on duplicate-name failure and cloud-vs-local routing for a 5-parameter creation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters are already documented in the schema, giving a baseline of 3. The description names project name, path and the optional default flag but adds no semantics beyond what the schema states (uniqueness, workspace routing and output_format are all schema-only).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('Create a new Basic Memory project') and restates it with the two required inputs (name, path). It is distinguishable from list_memory_projects/bm_project by the verb, but it never explicitly contrasts itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this versus list_memory_projects or bm_project, and no prerequisites such as the uniqueness constraint or that cloud credentials are needed when a workspace selector is supplied. The only usage hint is the incidental 'optionally sets the new project as default'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_noteDelete NoteADestructive
Delete a note or directory by title, permalink, or path. Deletion is permanent and removes the file. With is_directory=True every file under the path is deleted. A missing note returns false rather than an error.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name to delete from. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| identifier | Yes | For files: note title or permalink to delete. For directories: the directory path (e.g., "docs", "projects/2025"). Can be a title like "Meeting Notes" or permalink like "notes/meeting-notes" | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| is_directory | No | If True, deletes an entire directory and all its contents. When True, identifier should be a directory path (without file extensions). Defaults to False. | |
| output_format | No | "text" returns true/false for a single note (false if not found), a markdown summary for directories, or markdown guidance on error. "json" returns machine-readable deletion metadata. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the destructiveHint annotation by stating deletion is permanent, that files are removed from disk, that is_directory recursively deletes everything under the path, and that a missing note returns false instead of erroring. These are exactly the behavioral facts an agent needs before an irreversible call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action and scope, then the destructive consequence, then the recursive flag, then the not-found behavior. No sentence is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A mutation tool with an output schema still gets the salient return semantics (false on missing note) spelled out, and the recursive-deletion risk is explicit. Nothing needed to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so identifier, is_directory, project and output_format are already documented. The description restates the identifier forms and the is_directory branch but adds no syntax or edge-case detail beyond the schema, which puts it at baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (note or directory) plus the accepted identifier forms. It is clearly distinguishable from the sibling read/edit/move tools without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the key usage branch: pass is_directory=True to delete a whole tree, otherwise a single note is removed. It gives context but no explicit 'when not to use this vs edit_note/move_note' guidance or prerequisite checks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_noteEdit NoteADestructive
Edit a note in place. operation picks the edit: append or prepend content (prepend lands after frontmatter; both create the note if it does not exist); find_replace (replaces every exact, case-sensitive occurrence of find_text, and writes nothing unless the count equals expected_replacements, default 1); replace_section (replaces the content under the section heading, including its subsections unless replace_subsections=false); insert_before_section / insert_after_section (adds content beside the section heading). The heading must match exactly and appear once; a heading without leading # is treated as ##. A missing or duplicate heading, or missing find_text, fails without writing. identifier must resolve exactly; there is no fuzzy matching. Pass metadata to merge frontmatter fields in the same call. Pass expected_checksum to edit only if the note is still the revision you read.
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | The content to add or use for replacement | |
| project | No | Project name to edit in. Optional - server will resolve using hierarchy. Use "workspace/project" to route to a project in a specific cloud workspace. If unknown, use list_memory_projects() to discover available projects. | |
| section | No | Heading for replace_section, insert_before_section, and insert_after_section (e.g. "## Notes", "### Implementation"). Must match exactly. | |
| metadata | No | Optional dict of frontmatter fields to merge, independent of `operation`. Provided keys overwrite existing frontmatter values (or are added if new); unrelated frontmatter keys and the note body are left untouched. Can be combined with any operation in the same call. `title` and `permalink` are ignored since those have their own dedicated handling; `type` is applied like any other frontmatter field. Key deletion is not supported. | |
| find_text | No | For find_replace operation - the exact, case-sensitive text to replace | |
| operation | Yes | The editing operation to perform: - "append": Add content to the end of the note (creates the note if it doesn't exist) - "prepend": Add content to the beginning of the note (creates the note if it doesn't exist) - "find_replace": Replace occurrences of find_text with content (note must exist) - "replace_section": Replace a markdown section identified by its header (note and section must exist). The heading must match exactly, including trailing tags or text; a miss fails without writing. By default the section spans through the next heading of the same or higher level, so its subsections are replaced too; see replace_subsections. - "insert_before_section": Insert content before a section heading without consuming it (note must exist) - "insert_after_section": Insert content after a section heading without consuming it (note must exist) | |
| workspace | No | Workspace slug, name, or tenant_id. When provided with `project`, routes as `workspace/project`. Cannot be combined with `project_id`. | |
| identifier | Yes | The exact title, permalink, or memory:// URL of the note to edit. Must be an exact match - fuzzy matching is not supported for edit operations. Use search_notes() or read_note() first to find the correct identifier if uncertain. From the CLI this is a positional argument, not a flag. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | "text" returns a markdown summary of the edit and the note's resulting observations and relations. "json" returns machine-readable edit metadata. | text |
| expected_checksum | No | Optional revision precondition: the full `checksum` that read_note, write_note, or edit_note returned in JSON mode (the accepted revision's checksum; text output shows only its first 8 characters). When the note has changed since, the edit is refused with a revision conflict that names the current checksum, and nothing is written. A refused precondition never auto-creates the note. To refresh a stale checksum without reading the whole note, call read_note(identifier=..., include_content=False). | |
| replace_subsections | No | For replace_section operation. Default (true): the section spans everything through the next heading of the same or higher level in the original note, so replacing "## Section" also replaces its "###" subsections — the replacement content may freely introduce new headings. Set to false to replace only the immediate content under the header, stopping at the next heading of any level and preserving subsections. | |
| expected_replacements | No | For find_replace: required occurrence count of find_text (default 1). A mismatch fails without writing. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already flag destructiveHint=true, the description goes well beyond them: it says append/prepend auto-create the note, that a failed count/heading check 'writes nothing', that replace_section consumes subsections by default, and that a stale checksum refuses the edit and never auto-creates. That is exactly the write/destroy surface an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the verb and the operation switch, and every clause carries operational detail. The single dense paragraph with stacked parentheticals is harder to scan than a short bulleted operation list would be, but there is little true filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter, destructive, multi-mode tool with an output schema already covering return values, the description supplies the operation contract, failure semantics, atomicity guarantees, and concurrency precondition. Nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description still adds meaning the schema lacks — prepend landing after frontmatter, a heading lacking '#' being normalized to '##', and expected_replacements defaulting to 1. It does not touch project/workspace/project_id routing, but those are fully documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource ('Edit a note in place') and the rest enumerates the six supported operations with their distinct semantics. It does not name write_note or delete_note as alternatives, so sibling differentiation is left to the reader, which caps it below 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Selection among the six operations is spelled out (append/prepend create, find_replace requires existence and an exact count, section ops require an exact single heading). It also states when to pass expected_checksum. What is absent is guidance on when to choose edit_note at all versus write_note, which the description never mentions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetchFetch DocumentARead-only
OpenAI/ChatGPT connector fetch adapter. Takes an id from search results (permalink, title, or memory:// URL) and returns one text item holding JSON {id, title, text, url, metadata}. Other MCP clients receive an unsupported-client error; use read_note instead.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Document identifier (permalink, title, or memory URL) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already establish read-only, non-destructive, and closed-world behavior. The description adds valuable connector-specific behavior: unsupported MCP clients receive an error, and the return payload is a single text item containing JSON.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded: caller scope, input source, return shape, and fallback are all stated without wasted sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only fetch tool with annotations and an output schema, the description covers the necessary caller constraints, input expectations, return behavior, and the alternative tool. Nothing important is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the id parameter is already documented. The description adds useful context by saying the id should come from search results and that it may be a permalink, title, or memory:// URL.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it fetches one document by id and returns a text item containing JSON. It also distinguishes the tool from sibling read_note by explaining that other MCP clients should use read_note instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly identifies the intended caller (OpenAI/ChatGPT connector), the source of the id (search results), and the alternative for unsupported MCP clients (read_note). This gives clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
findFindARead-only
Recursively list files by name glob or metadata predicates (e.g. "status=active"). Paths accept '/path'.
| Name | Required | Description | Default |
|---|---|---|---|
| meta | No | Frontmatter metadata predicates, repeatable; every predicate must hold. One predicate per string, one predicate per key, at least one predicate; omit `meta` entirely for the directory listing. Forms: "status=active" equality "confidence>0.6" comparison: > >= < <= "priority in high,critical" any of the listed values "tags has security,oauth" array contains ALL listed values "score between 0.3,0.8" inclusive range "owner=null" key missing or explicitly null Values are JSON-scalar inferred ("true"/"false"/"null"/numbers become booleans/None/numbers); quote a token to force a literal string (e.g. 'status="true"'), including inside a list, where the quotes also protect a comma ('label in "a,b",c' matches "a,b" or "c") and a value that itself starts with an operator character ('range=">=5"'). Numbers must be finite, and null is only meaningful with "=" — the other operators compare against the value, and a comparison with null is never true. Keys accept dot-paths ("review.approved"); "note_type" aliases the frontmatter "type" key. String equality and "in" on either type spelling use normalized note-type matching ("LiteraryDevice" matches "literary_device"). Other metadata keys and operators retain their usual comparisons. Any other operator fails fast naming the supported set. | |
| name | No | File-name glob to match, e.g. "*.md". None matches everything. Cannot combine with `meta` — scope with `path` instead. | |
| page | No | Page number (1-indexed). | |
| path | No | Directory to start from (default: project root). '<project>/path' routes into that project. With `meta`, scopes the search to this subtree (matched on a directory boundary, so "specs" never admits "specs-archive/"). | / |
| depth | No | How many levels to recurse (1-10, default: 10). A non-default depth cannot combine with `meta` (the subtree scope is all-or-nothing). | |
| fields | No | Frontmatter fields to return per hit (dot-paths allowed), e.g. ["title", "priority"]. Requires `meta`. A field missing on a hit renders as null — rows are never dropped. Requesting fields also narrows each row to the note's identity plus those values: the projection replaces the note body rather than riding alongside it. | |
| project | No | Project name. Optional - qualified paths route themselves; unqualified paths refuse when several projects are addressable. | |
| page_size | No | Nodes per page. | |
| project_id | No | Project external_id (UUID); takes precedence over `project`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds the recursion trait and the project-qualified path form, which are genuine behavioral facts, but says nothing about pagination behavior, result caps or how the two modes interact (the non-combinability of name and meta lives only in the schema).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the primary capability leads, and the path-syntax caveat follows. Nothing is restated and every clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, full schema coverage and safety annotations, most structural burden is carried elsewhere, so the short description is defensible. What remains missing is disambiguation in a very crowded sibling set (ls, list_directory, search, search_notes, grep) — without that, an agent can call it but may pick the wrong tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all nine parameters in depth; the baseline of 3 applies. The description adds only the '<project>/path' routing convention on top of that, which is a marginal increment rather than compensating for any gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: recursively listing files, either by name glob or by metadata predicates, with the extra path-routing syntax. It is clearly distinguishable from the mutation siblings (edit_note, move_note), but it never contrasts itself with the closest read siblings (ls, list_directory, search_notes, grep), which is the only thing separating it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the two modes it names (glob for name matching, metadata predicates for frontmatter filtering) and by the note that paths accept '<project>/path'. There are no explicit when-to-use or when-not-to-use statements and no sibling is named as the alternative for, say, plain directory listing or full-text search, so the agent has to infer routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
grepGrepARead-only
Search note content in one project and return matching notes. Not a regex: pattern is matched as full-text keywords by default, and a pattern found in no note returns no results. semantic=True ranks by meaning instead (hybrid semantic plus full-text, when semantic search is enabled). Add context_lines to get case-insensitive matching lines with surrounding context and line numbers. Requires 'project' when several projects are addressable.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (1-indexed). | |
| pattern | Yes | Text to search for. | |
| project | No | Project name. Required when more than one project is addressable. | |
| semantic | No | Rank by meaning with hybrid semantic plus full-text retrieval instead of the default keyword matching. Cannot be combined with context_lines. | |
| page_size | No | Results per page (maximum 100 in line-scanning mode). | |
| project_id | No | Project external_id (UUID); takes precedence over `project`. | |
| max_matches | No | Maximum matching lines to show per candidate in line mode (1-100, default 10). Omitted matches carry next_match_line for a targeted read_note or cat read. Edits between calls can shift line positions. | |
| context_lines | No | Return compact literal match windows with 0-10 surrounding lines (not with semantic=True). Case-insensitive substrings, coordinates including frontmatter, overlapping windows merged. Scans current content of this indexed candidate page; pagination/totals count candidates, not exact matches. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint=false, so the safety bar is low. The description adds genuine behavioral context beyond annotations: empty-match returns no results, case-insensitive matching, and the reason to add context_lines. It doesn't discuss pagination behavior, but the added matching semantics are valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose and then layers mode details efficiently. Sentences each carry information, though the density around semantic/context_lines is slightly tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values needn't be explained, and annotations cover the safety profile. The description covers matching modes and the project prerequisite, leaving only minor gaps like pagination behavior for an 8-param tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds real meaning beyond the schema for `pattern` (full-text keywords, not regex) and reinforces the semantic vs context_lines tradeoff and the project requirement, which the schema alone states more tersely.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search note content in one project and return matching notes') and clarifies the matching mechanism ('Not a regex... full-text keywords by default'). It distinguishes itself from regex search by mechanism, though it doesn't name the competing sibling tools (search_notes, search) explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear conditions for the semantic mode ('semantic=True ranks by meaning instead') and for context_lines ('Add context_lines to get...'), plus the 'Requires project when several projects are addressable' prerequisite. It lacks explicit 'use X instead of grep' routing to siblings, so not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_directoryList DirectoryBRead-only
List directory contents with filtering and depth control.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | One-indexed result page (default: 1) | |
| sort | No | Optional file ordering: "title_asc", "title_desc", "updated_asc", or "updated_desc". Directories remain first. | |
| depth | No | Recursion depth (1-10, default: 1 for immediate children only) Higher values show subdirectory contents recursively | |
| project | No | Project name to list directory from. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| dir_name | No | Directory path to list (default: root "/") Examples: "/", "/projects", "/research/ml" | / |
| page_size | No | Number of nodes per page (default: 10, maximum: 200) | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | "text" for a readable listing or "json" for structured pagination data | text |
| file_name_glob | No | Optional glob pattern for filtering file names Examples: "*.md", "*meeting*", "project_*" |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is clear. The description adds only a brief note about filtering and depth control, without extra behavioral context such as pagination behavior or project resolution. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. It immediately states the operation and the two main capability areas.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The full schema, output schema, and annotations cover the mechanical details needed to invoke the tool. However, the description does not address project scoping or how this tool relates to sibling directory/listing tools, leaving some contextual gaps. It is minimally adequate given the rich structured metadata.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameter meanings are already documented in the schema. The description mentions filtering and depth control at a high level but does not add syntax or semantics beyond what the schema provides. This meets the baseline for fully documented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List directory contents.' It also mentions filtering and depth control, which clarifies scope. However, it does not distinguish this tool from sibling list-oriented tools such as ls, bm_list, list_workspaces, or list_memory_projects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit when-to-use or when-not-to-use guidance. With several sibling listing tools present, an agent is left to infer when list_directory is preferable to alternatives like ls or bm_list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_memory_projectsList Memory ProjectsARead-only
List all available projects with their status.
Shows projects from both local and cloud sources when cloud credentials are available, merging by permalink to give a unified view.
Each project entry includes an external_id (UUID). Pass that value as the
project_id parameter on other tools to address a specific project
unambiguously across cloud workspaces — useful when the same project name
exists in more than one workspace.
| Name | Required | Description | Default |
|---|---|---|---|
| output_format | No | "text" returns a human-readable project list. "json" returns structured project metadata. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly and non-destructive, so the safety profile is covered. The description adds meaningful behavior beyond that: cloud credentials gate whether cloud results appear, and results from both sources are deduplicated by permalink into a unified view — a non-obvious merging trait an agent should know about.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then scope, then the downstream identifier contract. Three short paragraphs, each adding distinct information with little repetition. Could be tightened slightly, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is not the description's job; it still usefully flags the credential prerequisite and the merge rule. Minor omissions remain (e.g. whether the list is exhaustive or paginated), but 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the sole output_format parameter is fully described with an enum and default, so the schema already carries the meaning. The description adds no format details of its own; its external_id guidance concerns return values, not input semantics. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List all available projects with their status') and immediately adds scope detail — local plus cloud sources merged by permalink. That merged-view behavior distinguishes it from sibling list tools like list_workspaces, so an agent can tell what it gets without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes downstream usage: take the returned external_id and pass it as project_id on other tools, and explains the condition where this matters (duplicate project names across workspaces). It stops short of naming a direct alternative or exclusion versus list_workspaces, but the use context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workspacesList WorkspacesBRead-only
List available cloud workspaces (tenant_id, type, role, and name).
| Name | Required | Description | Default |
|---|---|---|---|
| output_format | No | "text" returns human-readable workspace list. "json" returns structured workspace metadata. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered structurally. The description adds that the tool returns tenant_id/type/role/name, which is mildly useful, but that information is largely duplicated by the output schema and it says nothing about ordering, empty results, or pagination for what could be a multi-tenant listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence, front-loaded with the verb and resource and parenthetically listing the returned fields. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple, zero-required-parameter read tool with a full output schema and complete annotations, so the description need not explain return values or safety. It is nearly complete; the only gap is that it gives no hint about the workspace/tenant context an agent needs before calling workspace-scoped siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (output_format) exists and schema description coverage is 100%, including a full enum documentation for text vs json. The description says nothing about output_format, so it does not compensate or add meaning — but the schema already carries that burden, making baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('List available cloud workspaces') and even names the returned fields (tenant_id, type, role, name), so the agent knows exactly what it will get. It does not, however, distinguish this tool from the many other listing siblings (list_directory, bm_list, list_memory_projects) in terms of which resource domain it covers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this versus alternatives, no prerequisites (e.g. authentication or tenant context), and no exclusions. The agent must infer that this is the entry-point enumeration for workspaces before calling other workspace-scoped tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lsLsBRead-only
List one directory level. '/' lists projects; paths accept '/path'.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (1-indexed). | |
| path | No | Directory path to list. '/' (the default) with no project param lists the active projects as mount points; '<project>/path' routes into that project. | / |
| project | No | Project name. Optional - '/' lists projects; qualified paths route themselves; other unqualified paths refuse when several projects are addressable. | |
| page_size | No | Nodes per page. | |
| project_id | No | Project external_id (UUID); takes precedence over `project`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds the routing behavior ('/' lists projects, '<project>/path' routes into a project), which is genuine added value, but says nothing about pagination behavior or the 'refuses when several projects are addressable' condition that the schema mentions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly packed sentences with the core action front-loaded and the root-path special case attached directly. Nothing redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full schema coverage, the description need not explain returns or parameters. It covers the main conceptual hurdle (root vs project-qualified paths); only the sibling distinction and pagination expectations are absent, which are minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters including page, page_size and project precedence are already documented in structured fields. The description merely restates the path convention at a higher level, which is a baseline-level contribution.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List one directory level') and immediately clarifies the special root case. It does not, however, distinguish itself from the sibling list_directory / bm_list, which an agent could easily confuse with this tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to choose this over list_directory or bm_list, and no stated prerequisites or exclusions. Usage is only weakly implied by the path-shape hints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manManBRead-only
Look up a manual page or search the manual.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page reference, e.g. "search-notes(3)". Any common spelling works. | |
| query | No | Apropos search text. Mutually exclusive with `page`. | |
| project | No | Ignored; the manual is bundled with the package. | |
| project_id | No | Ignored; the manual is bundled with the package. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, closed-world, non-destructive operation. The description adds no behavioral context beyond that, such as what kind of search is performed or how lookup differs from search. It does not contradict the annotations, but it contributes little.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no filler or repetition. Every word supports the tool's core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple, read-only nature of the tool, a fully documented schema, and an output schema, the description is nearly complete for invocation. It could mention sibling tools like bm_man or clarify the page/search distinction, but those are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents `page`, `query`, and the ignored `project`/`project_id` parameters in detail. The description only gestures at page lookup and search without adding syntax or constraints, so it meets the baseline but does not enrich parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Look up', 'search') and resource ('manual page', 'the manual'), so the tool's function is immediately understandable. It does not distinguish itself from likely siblings such as bm_man, which prevents a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'or search the manual' implies the two usage modes, but it does not explicitly explain when to use `page` versus `query`, nor does it name alternatives. The schema notes mutual exclusivity, but the description itself gives only implied guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_noteMove NoteA
Move a note, or a whole directory with is_directory=true, to a new path within the same project; cross-project moves are refused. For a file, give either destination_path (project-relative, with the same file extension as the source, e.g. "archive/note.md"; .markdown may become .md) or destination_folder (keeps the filename). The file moves on disk and its index entry, observations, and relations move with it. The permalink stays the same unless the server's update_permalinks_on_move setting is on, so links that use it keep resolving; other notes' text is not rewritten.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name to move within. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| identifier | Yes | For files: exact entity identifier (title, permalink, or memory:// URL). For directories: the directory path (e.g., "docs", "projects/2025"). Must be an exact match - fuzzy matching is not supported for move operations. Use search_notes() or list_directory() first to find the correct path if uncertain. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| is_directory | No | If True, moves an entire directory and all its contents. When True, identifier and destination_path should be directory paths (without file extensions). Defaults to False. | |
| output_format | No | "text" returns a markdown success or failure message. "json" returns machine-readable move metadata, with an error code on failure. | text |
| destination_path | No | For files: new path relative to project root (e.g., "work/meetings/note.md") For directories: new directory path (e.g., "archive/docs") Mutually exclusive with destination_folder. | |
| destination_folder | No | Move the note into this folder, preserving the original filename. Mutually exclusive with destination_path. Only for single-file moves. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing side effects: the file moves on disk and its index entry, observations and relations travel with it; the permalink is preserved unless update_permalinks_on_move is set; other notes' text is not rewritten. That tells the agent exactly what breaks and what doesn't, which the bare destructiveHint=false cannot.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the cross-project constraint, then spends the remaining space on destination-mode rules and move side effects. Dense but every sentence carries information; the long second sentence could be split for scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema handling return values and annotations covering safety, the description supplies everything else an agent needs: scope limits, mode selection, extension rules, and post-move state of permalinks and links. Nothing material is missing for a 7-parameter mutation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: destination_path must keep the same file extension (with the .markdown→.md conversion rule), destination_folder preserves the original filename, and is_directory switches identifier/destination to directory-path interpretation. Only the project/project_id precedence and output_format are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Move a note, or a whole directory with is_directory=true') plus a hard scope constraint ('within the same project; cross-project moves are refused'). This clearly separates it from read/search/edit siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes between the two destination modes ('give either destination_path ... or destination_folder (keeps the filename)') and states the cross-project exclusion. It does not, however, contrast the tool with siblings like edit_note or write_note, so an agent must infer that moving is not the way to rename-edit content.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_contentRead ContentARead-only
Read a file's raw bytes by path, permalink, or memory:// URL, without knowledge-graph processing. Text and JSON come back as {"type": "text"}; images are re-encoded as JPEG and downscaled to about 350 KB; other binaries come back base64 as {"type": "document"} and are refused above 350 KB. Use read_note for markdown notes when you want note resolution and fallback search.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | The path or permalink to the file. Can be: - A regular file path (docs/example.md) - A memory URL (memory://docs/example) - A permalink (docs/example) | |
| project | No | Project name to read from. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond readOnlyHint=true by disclosing transformation behavior: images are re-encoded as JPEG and downscaled to ~350 KB, other binaries return base64 as {"type": "document"}, and binaries above 350 KB are refused. These are decision-relevant constraints an agent could not infer from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action and addressing modes, then the size/encoding caveats, then the routing rule. Every clause carries information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers addressing modes, size limits, encoding/transform behavior, and the sibling alternative; an output schema exists so return values need not be spelled out further. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so path, project, and project_id are already fully documented, including precedence of project_id. The description repeats the accepted path/permalink/memory:// forms but adds no syntax or resolution detail beyond the schema, making baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read a file's raw bytes') plus the accepted addressing forms, and explicitly scopes itself as 'without knowledge-graph processing', which separates it from read_note/search_notes. An agent can distinguish it from siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes markdown-note use cases to read_note when note resolution and fallback search are wanted, which is a concrete alternative-with-condition. It does not state any when-not-to-use case for this tool itself (e.g. preference among cat/read_note/view_note beyond that), but the primary fork is covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_noteRead NoteARead-only
Read a markdown note by title or permalink, optionally a numbered line range. If the identifier doesn't resolve directly, a note whose title matches it exactly (case-insensitive) is returned with full content; otherwise it returns related-note suggestions from text search instead of content. Pass include_content=false to get only the note's metadata and checksum.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page of fallback-search results to use when the identifier does not resolve to a note directly (default: 1). A direct or exact-title match returns the note content — page/page_size never chunk the note itself, and the title-match lookup pages through fixed-size pages of title results until an exact match is found or results are exhausted, regardless of page or page_size. Aliases: page_number. | |
| project | No | Project name to read from. Optional - when omitted, a project prefix on a memory:// URL or permalink identifier routes the read; otherwise the server uses the configured default project. If unknown, use list_memory_projects() to discover available projects. | |
| end_line | No | Last document line to read (inclusive); omitted means EOF. Out-of-file ranges return empty content; invalid/reversed ranges fail. With either bound, text output is numbered and JSON carries coordinates, has_more, and next_start_line/next_end_line. include_frontmatter does not strip an explicitly addressed range. Edits between calls may shift lines. | |
| page_size | No | Number of fallback-search results per page (default: 10). When no match is found, this caps how many related-note suggestions are listed. Aliases: limit, per_page. | |
| identifier | Yes | The title or permalink of the note to read. Can be a full memory:// URL, a permalink, a title, or search text. From the CLI this is a positional argument, not a flag. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| start_line | No | First document line to read (1-based, inclusive). Defaults to 1 when only end_line is given. Line scans count the full Markdown, including frontmatter, matching cat's default line coordinates. | |
| output_format | No | "text" returns markdown content or guidance text. "json" returns a structured object with title/permalink/file_path/content/frontmatter. Unresolved notes carry error="NOTE_NOT_FOUND" and a message, with related_results when suggestions are available. | text |
| include_content | No | Default true. Set to false to return only the note's metadata — title, permalink, file_path, the full accepted-revision checksum, and updated_at — without the body. Use it to refresh the checksum that edit_note/write_note take as expected_checksum without reading the whole note. Cannot be combined with start_line/end_line. | |
| include_frontmatter | No | For unsliced JSON reads, include opening YAML in content; parsed frontmatter is returned either way. Explicit line ranges are never stripped. CLI: --frontmatter (--include-frontmatter is a deprecated alias). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavior beyond that: the exact-title fallback, the fact that unresolved notes return suggestions instead of content, and the checksum-refresh use of include_content=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences that front-load the core read action and then layer the fallback and metadata-only mode. No wasted language, though it packs a lot into a single sentence block.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 10 params at 100% schema coverage, an output schema present, and annotations covering safety, the description supplies the remaining behavioral essentials (fallback path, checksum use case, error suggestion behavior). An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description still adds value by explaining the purpose behind include_content=false (refreshing the checksum for edit_note/write_note) and the page/page_size fallback semantics, going beyond restating parameter names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Read a markdown note by title or permalink, optionally a numbered line range') and describes the fallback path when the identifier doesn't resolve. An agent can distinguish this read operation from search-based siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The fallback behavior ('if the identifier doesn't resolve directly... returns related-note suggestions') and the include_content=false guidance give clear context for when to use this tool. However, it does not explicitly name a competing sibling like search_notes or view_note to route between them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recent_activityRecent ActivityARead-only
Get recent activity for one project.
With no project, this uses the configured default project. It lists activity
across all projects only when there is no default.
Timeframe supports natural language formats like:
- "2 days ago"
- "last week"
- "yesterday"
- "today"
- "3 weeks ago"
Or standard formats like "7d"
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (default 1) | |
| type | No | Filter by content type(s). Can be a string or list of strings. Valid options: - "entity" or ["entity"] for knowledge entities - "relation" or ["relation"] for connections between entities - "observation" or ["observation"] for notes and observations Multiple types can be combined: ["entity", "relation"] Case-insensitive: "ENTITY" and "entity" are treated the same. Default is entity-only. Specify other types explicitly to include observations and relations. | |
| depth | No | How many relation hops to traverse (1-3 recommended, maximum: 5) | |
| project | No | Project name to query. Optional - when omitted, the server uses the configured default project, and discovery mode across all projects applies only when there is no default. If unknown, use list_memory_projects() to discover available projects. | |
| page_size | No | Number of items per page (default 10, maximum: 100) | |
| timeframe | No | Time window to search. Supports natural language: - Relative: "2 days ago", "last week", "yesterday" - Points in time: "2024-01-01", "January 1st" - Standard format: "7d", "24h" Aliases: since, time_range, lookback. | 7d |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | "text" returns human-readable summary text. "json" returns a flat list of recent items. | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only, non-destructive, closed-world profile, so the description's job is to add operational nuance — which it does by disclosing the implicit project-resolution and cross-project discovery fallback that would otherwise surprise an agent. It doesn't mention pagination limits or result ordering, but the output schema carries 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The default-project behavior is usefully front-loaded, but the natural-language timeframe bullet list duplicates the schema's own timeframe examples verbatim in spirit, consuming roughly half the description with no new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a full output schema, and 100% parameter coverage, the description only needs to resolve ambiguity — and it does resolve the main one (project vs. no project resolution order). Minor omission: no note on how timeframe interacts with the type/depth filters or what 'recent' ordering means in the returned feed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter in detail. The timeframe bullet list largely restates examples already present in the timeframe schema description, adding little beyond the schema; the project-defaulting sentence is the only genuine semantic addition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource ('Get recent activity') and scopes it to a project. An agent knows it retrieves a recent-items feed, though what counts as 'activity' is only inferable from the type parameter in the schema rather than the description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the default-project fallback behavior ('with no project, this uses the configured default project... lists across all projects only when there is no default'), which is genuine usage context. However, it never names an alternative sibling (build_context, bm_search, search_notes) or states when this tool is the wrong choice over a search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schema_diffSchema DiffBRead-only
Detect drift between a schema definition and actual note usage. A schema is a note with type: schema whose entity field names the note type it describes.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name. Optional -- server will resolve. | |
| note_type | Yes | The note type to check for drift (e.g., "person"). | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds domain context by explaining that a schema is a note with type: schema whose entity field names the described note type, but it does not clarify what counts as drift or how results are reported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no waste. The purpose is front-loaded and the schema definition follows as necessary context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema and annotations cover return values and safety. The description explains the core schema concept needed to call the tool correctly. A minor gap remains around what specific drift conditions are detected, but the essential information is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the schema documents most parameters. The description adds meaning to note_type by explaining the schema-note relationship, but it does not mention project/project_id precedence or the output_format parameter beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: detect drift between a schema definition and actual note usage. It also defines what a schema note is, which makes the purpose concrete. It does not explicitly differentiate itself from sibling tools like schema_validate or schema_infer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is used for drift detection, but gives no explicit when-to-use guidance, no exclusions, and no comparison to relevant siblings such as schema_validate or schema_infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schema_inferInfer SchemaARead-only
Analyze existing notes of one type and suggest a Picoschema definition. A schema is a note with type: schema whose entity field names the note type it describes.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name. Optional -- server will resolve. | |
| note_type | Yes | The note type to analyze (e.g., "person", "meeting"). | |
| threshold | No | Minimum frequency (0-1) for a field to be suggested as optional. Default 0.25 (25%). Fields above 95% become required. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds conceptual context (what a schema note is) but does not disclose requirements such as minimum note counts, performance, or what the suggestion entails beyond the schema itself.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with the core purpose front-loaded and a useful definitional follow-up. No wasted text, though slightly sparse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, annotations, and 80% param coverage, the description is largely complete. The only gap is lack of guidance on prerequisites (e.g., needing enough example notes) or how the suggestion should be interpreted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80%, so the schema documents note_type, threshold, project, project_id, and output_format adequately. The description adds no parameter-level meaning beyond what the schema provides, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Analyze existing notes of one type and suggest a Picoschema definition.' This clearly distinguishes it from sibling schema tools (schema_validate, schema_diff), though it doesn't name an alternative explicitly. The second sentence clarifies what a schema is, aiding understanding.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage (analyze notes to derive a schema) but offers no explicit when-to-use guidance versus schema_validate, schema_diff, or manual schema creation, and no prerequisite conditions like having sufficient notes of that type.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schema_validateValidate SchemaARead-only
Validate notes against their Picoschema definitions. With neither note_type nor identifier it validates every note type that has a schema. A schema is a note with type: schema whose entity field names the note type it describes.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name. Optional -- server will resolve. | |
| note_type | No | Note type to batch-validate (e.g., "person", "meeting"). If provided, validates all notes of this type. | |
| identifier | No | Specific note to validate (permalink, title, or path). If provided, validates only this note. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | text |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context: the default all-types sweep when no filters are given, plus a definition of what a schema object is, which the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the action, second sentence giving the default scope, third defining the jargon. Nothing is padded and the ordering matches how an agent reads.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and read-only annotations cover the safety profile. The one remaining ambiguity is precedence when note_type and identifier are both provided, which the schema leaves implicit and the description does not resolve.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
At 80% schema coverage the baseline is 3, but the description adds the interaction rule the schema does not state: note_type and identifier together determine scope, and omitting both widens the sweep to all schema-bearing types. It stops short of saying what happens when both are supplied simultaneously.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Validate notes against their Picoschema definitions') and even defines the domain term 'schema'. It does not distinguish itself from the nearby schema_infer and schema_diff siblings, leaving the agent to infer which schema tool applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description covers scoping behavior (omitting both filters validates every type that has a schema), which implies how to use it, but never states when to pick this over schema_infer or schema_diff, nor any prerequisites such as a schema existing for the type.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch Knowledge BaseARead-only
OpenAI/ChatGPT connector search adapter. Returns one text item holding JSON {results, total_count, query} for the top 10 search_notes matches. Other MCP clients receive an unsupported-client error; use search_notes instead.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (full-text syntax supported by `search_notes`) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=false, so safety is covered. The description still adds real behavioral facts beyond them: a hard cap of 10 results, a single text-item return envelope carrying JSON, and a hard failure mode for non-OpenAI clients. Slight redundancy with the existing output schema on the return shape keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler. The adapter scope and return shape come first, the client restriction and fallback second — the correct front-loading for an agent deciding whether to call at all.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with an output schema, an agent still gets everything it needs to avoid a wrong call: the client restriction, the error outcome, the result cap, and the fallback tool. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 100% schema description coverage ('Search query (full-text syntax supported by search_notes)'), so the schema already carries the semantics. The description mentions the query only as a field echoed back in the response, adding no syntax or format guidance beyond the schema. Baseline 3 for a fully documented single parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (search adapter over the knowledge base) and immediately bounds it: 'top 10 search_notes matches' returned as one text item of JSON {results, total_count, query}. The first word 'OpenAI/ChatGPT connector' scopes it away from the general search_notes sibling, so an agent can tell them apart 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the exclusion and the alternative: 'Other MCP clients receive an unsupported-client error; use search_notes instead.' This is a rare case where both the when and the when-not are stated with a named fallback tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_notesSearch NotesARead-only
Search notes, observations, and relations in one project, or in several with projects / search_all_projects. The query supports quoted phrases, AND/OR/NOT with parentheses, and tag:name (converted to a tags filter). A plain multi-term query first requires every term and may fall back to any-term matching when that returns nothing. search_type selects text, title, permalink (a * glob matched against the full permalink path), vector/semantic, or hybrid; the default is hybrid when semantic search is enabled, otherwise text. Omit query to search by filters alone (metadata_filters, tags, status, note_types). Results are whole notes by default; a categories or valid-time filter switches the default to observations. after_date filters by when content was last updated. valid_at / valid_overlaps / time_kind filter by dates written inside notes (e.g. @effective[2026-06-10,2026-07-27)) and exclude undated content. Returns ranked, paginated results; read full content with read_note or cat. Syntax reference: memory://man/search-notes(3).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | The page number of results to return (default 1). Aliases: page_number. | |
| tags | No | Optional tag filter (frontmatter tags); shorthand for metadata_filters["tags"]. Accepts a list (["a", "b"]) or a comma-separated string ("a,b"), matching the write_note tags convention and the tag: query shorthand. | |
| query | No | Optional search query string (supports boolean operators, phrases, patterns). Omit or pass None for filter-only searches using metadata_filters, tags, or status. | |
| status | No | Optional status filter (frontmatter status); shorthand for metadata_filters["status"] | |
| compact | No | Omit note bodies and matched excerpts from results. Keep identifiers, metadata, relation targets, scores and pagination for discovery, then read selected notes. | |
| project | No | Project name to search in. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| projects | No | Optional list of project names or external ids to search together. Names are matched exactly as list_memory_projects() reports them (cloud projects by their workspace-qualified name). Ignored when `project` or `project_id` is supplied; an unknown name is an error rather than a silent skip. | |
| valid_at | No | Optional date ("2026-07-28") or RFC 3339 instant ("2026-07-28T09:00:00Z"; a timestamp with no offset is read as UTC). Returns sources whose authored valid range contains it. Sources with no temporal qualifier are excluded. Aliases: as_of, valid_on. | |
| page_size | No | The number of results to return per page (default 10). Aliases: limit, per_page. | |
| time_kind | No | Optional kind of valid time to narrow to: "effective", "valid", "occurred", "due", or "mentioned". Valid on its own. Alias: kind. | |
| after_date | No | Optional date filter for recent content (e.g., "1 week", "2d", "2024-01-01") | |
| categories | No | Observation categories to match exactly (e.g. ["requirement"]). Implies observation results unless entity_types is set. Accepts a list, a comma-separated string, or a JSON-array string. | |
| note_types | No | Filter by the frontmatter `type` field (e.g. "note", "person"). Case-insensitive. Accepts a list, a comma-separated string, or a JSON-array string. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| search_type | No | Type of search to perform, one of: "text", "title", "permalink", "vector", "semantic", "hybrid". Default is dynamic: "hybrid" when semantic search is enabled, otherwise "text". | |
| entity_types | No | Knowledge-graph item types to return: "entity" (whole notes), "observation", "relation". Defaults to entity, or to observation when categories or a valid-time filter is given. Not the frontmatter `type` (use note_types for that). Accepts a list, a comma-separated string, or a JSON-array string. | |
| output_format | No | "text" returns a formatted markdown result list. "json" returns a machine-readable dictionary payload. | text |
| min_similarity | No | Optional float to override the global semantic_min_similarity threshold for this query. E.g., 0.0 to see all vector results, or 0.8 for high precision. Only applies to vector and hybrid search types. | |
| valid_overlaps | No | Optional PostgreSQL-style range literal ("[2026-06-10,2026-07-27)", "(,2026-07-27]", "[2026-06-10,)"). Returns sources whose authored valid range overlaps it. Mutually exclusive with valid_at; also excludes undated sources. Aliases: overlaps, valid_during. | |
| metadata_filters | No | Structured frontmatter filters, {field: condition}. Nested fields use dot notation ("schema.confidence"). Conditions: a value for equality ({"status": "draft"}); null for absent-or-null ({"owner": null}); a list for array-contains-all ({"tags": ["a", "b"]}); or an operator object using $gt, $gte, $lt, $lte, $in (list), $between ([min, max]), $contains (value or list), $exists (true/false), e.g. {"priority": {"$in": ["high"]}}. Several operators on one field AND together: {"started": {"$gte": "2026-01-01", "$lt": "2026-02-01"}}. The leading $ is optional. | |
| search_all_projects | No | Optional opt-in to search every accessible project. Ignored when `project` or `project_id` is supplied. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/non-destructive annotations: discloses the two-pass matching fallback for plain multi-term queries, the dynamic default search type, that valid-time filters exclude undated content, that `after_date` keys on last-updated content, and that results are ranked and paginated. These are non-obvious behaviors an agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the highest-value routing decision (single vs. multiple projects). It is a dense single block that would scan better as fragments, but nearly every clause carries distinct behavioral or parameter information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the hard parts of a 21-parameter tool: query syntax, search-type defaults, entity-type defaults, temporal filtering, and result defaulting, plus a pointer to man page and read_note for follow-up. With an output schema present it need not describe returns, though pagination/ranking specifics are only gestured at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: `tag:name` query syntax maps to a tags filter, permalink `*` is a glob over the full path, `after_date` semantics, and the valid_at/valid_overlaps/time_kind model with an example. It leaves output_format, compact, and min_similarity entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (search notes/observations/relations) and immediately scopes it to one or several projects. It distinguishes itself from sibling readers by noting that full content requires read_note or cat.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rules throughout: use `projects`/`search_all_projects` for multi-project search, omit `query` for filter-only searches, `search_type` selection with a stated default, and the categories/valid-time rule that flips results to observations. It also names the follow-up tool (read_note/cat) once results are found.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tailTailARead-only
Show recently changed notes. Requires 'project' when several are addressable.
| Name | Required | Description | Default |
|---|---|---|---|
| lines | No | Maximum number of rows to return (1-100). | |
| project | No | Project name. Required when more than one project is addressable. | |
| timeframe | No | Time window, e.g. "7d", "yesterday", "2 days ago". | 7d |
| project_id | No | Project external_id (UUID); takes precedence over `project`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, non-destructive, closed-world operation. The description adds the multi-project addressing precondition, which is helpful, but does not otherwise elaborate behavior beyond what annotations and the output schema already cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with no wasted text, and the core purpose is front-loaded before the conditional requirement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with complete schema coverage, annotations, and an output schema, the description is largely sufficient. It covers the main addressing caveat but could be slightly stronger by naming when to use this instead of nearby alternatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema. The description reinforces the project requirement but adds no new syntax or constraint details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Show recently changed notes.' This is clear and actionable, though it does not distinguish the tool from similarly themed siblings such as recent_activity or search_notes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides one useful usage condition: 'Requires project when several are addressable.' However, it does not explain when to choose this over related tools like recent_activity, search_notes, or read_note.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_noteView NoteARead-only
Read a note (same resolution as read_note) and return it wrapped in an instruction to display it to the user as a markdown artifact. Use when the user wants to see the note rendered; use read_note when you need the content yourself. Not-found results are returned unwrapped.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Project name to read from. Optional - server will resolve using hierarchy. If unknown, use list_memory_projects() to discover available projects. | |
| identifier | Yes | The title or permalink of the note to view | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say read-only/non-destructive; the description adds the non-obvious behavior that the payload is wrapped in display instructions, plus the edge case that not-found results bypass the wrapping. That's the kind of detail an agent can't get from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two to three short sentences, front-loaded with the core behavior, then the sibling routing, then the not-found caveat. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return shape needn't be spelled out, and the description still covers the wrapper transformation and the not-found exception. Everything an agent needs to choose and call it correctly is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so identifier/project/project_id are already documented. The description only adds that resolution matches read_note, which is a thin hint rather than new parameter meaning — baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read a note') and immediately distinguishes the behavior from read_note via the wrapper ('return it wrapped in an instruction to display it as a markdown artifact'). An agent can tell exactly what this returns without opening read_note's schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: 'Use when the user wants to see the note rendered; use read_note when you need the content yourself.' It names the alternative and the condition that selects each, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_noteWrite NoteADestructive
Create a markdown note. If the note already exists, returns an error by default — pass overwrite=True to replace. directory is required. For incremental changes to an existing note use edit_note. A new note's result may list similar existing notes; that is advisory and does not block the write. Pass expected_checksum with overwrite=True to replace the note only if it is still the revision you read.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Tags to categorize the note. Can be a list of strings, a comma-separated string, or None. Note: If passing from external MCP clients, use a string format (e.g. "tag1,tag2,tag3") | |
| title | Yes | The title of the note; written to frontmatter and drives the permalink. No H1 is added for you: content is saved as given, so include a "# Title" heading yourself if the note should open with one. | |
| content | Yes | Markdown content for the note, can include observations and relations. May carry its own frontmatter; a `type:` in content frontmatter takes precedence over the note_type parameter. | |
| project | No | Project name to write to. Optional. Omitting both project and project_id writes to the configured default project. Calls do not remember a project between them, so after working in another project, pass project explicitly. Use "workspace/project" to route to a project in a specific cloud workspace. A bare name that exists in multiple workspaces resolves to the default workspace, so use the qualified form (or project_id) to disambiguate. If unknown, use list_memory_projects() to discover available projects and their qualified names. | |
| metadata | No | Optional dict of extra frontmatter fields merged into entity_metadata. Useful for schema notes or any note that needs custom YAML frontmatter beyond title/type/tags. Nested dicts are supported. Not available from the CLI. | |
| directory | Yes | Directory path relative to project root where the file should be saved. Use forward slashes (/) as separators. Use "/" or "" to write to project root. Examples: "notes", "projects/2025", "research/ml", "/" (root). MCP accepts the aliases folder, dir, and path; the CLI flag is --folder. | |
| note_type | No | Type of note to create (stored in frontmatter `type:`). Defaults to "note". Can be "guide", "report", "config", "person", etc. The CLI flag is --type. A `type:` in content frontmatter takes precedence over this parameter, and this is what schema validation keys on. | note |
| overwrite | No | If True, replace existing note on conflict. If False, error on conflict. If None (default), consult write_note_overwrite_default config setting. Overwrite replaces the body but merges frontmatter: keys the existing note has and this write does not set (custom fields) are kept, while keys this write sets (title, type, tags, metadata, or frontmatter in content) replace the old values. Existing frontmatter that cannot be parsed is discarded rather than merged. To remove a key, rewrite it with edit_note or edit the file. | |
| workspace | No | Workspace slug, name, or tenant_id. When provided with `project`, routes as `workspace/project`. Cannot be combined with `project_id`. | |
| project_id | No | Project external_id (UUID). Prefer this over `project` when known — it routes to the exact project regardless of name collisions across cloud workspaces. Takes precedence over `project`. Get from list_memory_projects(). | |
| output_format | No | "text" returns a markdown summary. "json" returns machine-readable metadata. A refused write (note exists, revision conflict, moved target, disallowed directory) is a tool error; in JSON mode its message is the payload with action: "conflict" and an error code. | text |
| expected_checksum | No | Optional revision precondition for overwrite=True: the checksum of the note you read (from a JSON read_note, write_note or edit_note result). The note is replaced only while it is still that revision; otherwise the tool reports a revision conflict with the current checksum and changes nothing. Omit it to replace the note unconditionally. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=false; the description goes well beyond by explaining the default conflict-error behavior, the frontmatter merge semantics on overwrite (kept vs replaced keys, unparseable frontmatter discarded), and the checksum revision precondition. This is exactly the kind of consequence-level detail annotations can't carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and conflict default, and every sentence carries non-obvious information. The overwrite/checksum sentence is dense and slightly run-on, but no content is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return-value detail isn't needed, and the description still covers refusal modes, the advisory similar-notes behavior, and conditional overwrite. Nothing an agent needs to invoke this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so overwrite, expected_checksum, directory, and project routing are already documented in structured form. The description mainly restates those (directory required, overwrite+checksum pairing) and adds no syntax or format detail the schema lacks. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a markdown note') and immediately distinguishes the create path from the mutate path by naming edit_note. An agent can tell write_note apart from edit_note, move_note, and read_note without inspecting any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: use edit_note for incremental changes, use overwrite=True to replace, pair overwrite with expected_checksum for conditional replacement. It also notes that the similar-notes result is advisory and non-blocking, so an agent won't mistakenly abort.
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.
40 tool updates
v0.24.1- Added
basic_memory_diagnostics - Added
bm_context - Added
bm_delete - Added
bm_edit - Added
bm_find - Added
bm_list - Added
bm_man - Added
bm_move - Added
bm_project - Added
bm_read - Added
bm_schema - Added
bm_search - Added
bm_write - Changed
build_context28 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / compactAdded value: +{ + "default": false, + "description": "Omit note bodies and entity observation lists for graph discovery; the server skips loading observations. Preserve identifiers, relation targets and pagination; use read_note for selected content. Not a guaranteed token budget.", + "type": "boolean" +} - added
Input schema / properties / depth / descriptionAdded value: +"How many relation hops to traverse (1-3 recommended, maximum: 5)" - removed
Input schema / properties / depth / titleRemoved value: -"Depth" - added
Input schema / properties / max_related / descriptionAdded value: +"Maximum total related results to return (default: 10, maximum: 100)" - removed
Input schema / properties / max_related / titleRemoved value: -"Max Related" - added
Input schema / properties / output_formatAdded value: +{ + "default": "json", + "description": "Response format - \"json\" for structured JSON dict,\n\"text\" for compact markdown text", + "enum": [ + "json", + "text" + ], + "type": "string" +} - added
Input schema / properties / page / descriptionAdded value: +"Page number of results to return (default: 1)" - removed
Input schema / properties / page / titleRemoved value: -"Page" - added
Input schema / properties / page_size / descriptionAdded value: +"Number of primary results to return per page (default: 10, maximum: 50)" - removed
Input schema / properties / page_size / titleRemoved value: -"Page Size" - added
Input schema / properties / project / descriptionAdded value: +"Project name to build context from. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / timeframe / descriptionAdded value: +"How far back to look. Supports natural language like \"2 days ago\", \"last week\"" - removed
Input schema / properties / timeframe / titleRemoved value: -"Timeframe" - added
Input schema / properties / url / descriptionAdded value: +"memory:// URI pointing to discussion content (e.g. memory://specs/search),\nor a bare permalink path." - removed
Input schema / properties / url / titleRemoved value: -"Url" - removed
Output schema / $defsRemoved value: -{ - "ContextResult": { - "description": "Context result containing a primary item with its observations and related items.", - "properties": { - "observations": { - "description": "Observations belonging to this entity", - "items": { - "$ref": "#/$defs/ObservationSummary" - }, - "title": "Observations", - "type": "array" - }, - "primary_result": { - "description": "Primary item", - "discriminator": { - "mapping": { - "entity": "#/$defs/EntitySummary", - "observation": "#/$defs/ObservationSummary", - "relation": "#/$defs/RelationSummary" - }, - "propertyName": "type" - }, - "oneOf": [ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } - ], - "title": "Primary Result" - }, - "related_results": { - "description": "Related items", - "items": { - "discriminator": { - "mapping": { - "entity": "#/$defs/EntitySummary", - "observation": "#/$defs/ObservationSummary", - "relation": "#/$defs/RelationSummary" - }, - "propertyName": "type" - }, - "oneOf": [ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } - ] - }, - "title": "Related Results", - "type": "array" - } - }, - "required": [ - "primary_result" - ], - "title": "ContextResult", - "type": "object" - }, - "EntitySummary": { - "description": "Simplified entity representation.", - "properties": { - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Content" - }, - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "entity_id": { - "title": "Entity Id", - "type": "integer" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "permalink": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Permalink" - }, - "title": { - "title": "Title", - "type": "string" - }, - "type": { - "const": "entity", - "default": "entity", - "title": "Type", - "type": "string" - } - }, - "required": [ - "entity_id", - "permalink", - "title", - "file_path", - "created_at" - ], - "title": "EntitySummary", - "type": "object" - }, - "MemoryMetadata": { - "description": "Simplified response metadata.", - "properties": { - "depth": { - "title": "Depth", - "type": "integer" - }, - "generated_at": { - "format": "date-time", - "title": "Generated At", - "type": "string" - }, - "primary_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Primary Count" - }, - "related_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Related Count" - }, - "timeframe": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Timeframe" - }, - "total_observations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Observations" - }, - "total_relations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Relations" - }, - "total_results": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Results" - }, - "types": { - "anyOf": [ - { - "items": { - "$ref": "#/$defs/SearchItemType" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Types" - }, - "uri": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Uri" - } - }, - "required": [ - "depth", - "generated_at" - ], - "title": "MemoryMetadata", - "type": "object" - }, - "ObservationSummary": { - "description": "Simplified observation representation.", - "properties": { - "category": { - "title": "Category", - "type": "string" - }, - "content": { - "title": "Content", - "type": "string" - }, - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "entity_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Entity Id" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "observation_id": { - "title": "Observation Id", - "type": "integer" - }, - "permalink": { - "title": "Permalink", - "type": "string" - }, - "title": { - "title": "Title", - "type": "string" - }, - "type": { - "const": "observation", - "default": "observation", - "title": "Type", - "type": "string" - } - }, - "required": [ - "observation_id", - "title", - "file_path", - "permalink", - "category", - "content", - "created_at" - ], - "title": "ObservationSummary", - "type": "object" - }, - "RelationSummary": { - "description": "Simplified relation representation.", - "properties": { - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "entity_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Entity Id" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "from_entity": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "From Entity" - }, - "from_entity_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "From Entity Id" - }, - "permalink": { - "title": "Permalink", - "type": "string" - }, - "relation_id": { - "title": "Relation Id", - "type": "integer" - }, - "relation_type": { - "title": "Relation Type", - "type": "string" - }, - "title": { - "title": "Title", - "type": "string" - }, - "to_entity": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "To Entity" - }, - "to_entity_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "To Entity Id" - }, - "type": { - "const": "relation", - "default": "relation", - "title": "Type", - "type": "string" - } - }, - "required": [ - "relation_id", - "title", - "file_path", - "permalink", - "relation_type", - "created_at" - ], - "title": "RelationSummary", - "type": "object" - }, - "SearchItemType": { - "description": "Types of searchable items.", - "enum": [ - "entity", - "observation", - "relation" - ], - "title": "SearchItemType", - "type": "string" - } -} - removed
Output schema / descriptionRemoved value: -"Complete context response." - removed
Output schema / properties / metadataRemoved value: -{ - "$ref": "#/$defs/MemoryMetadata" -} - removed
Output schema / properties / pageRemoved value: -{ - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Page" -} - removed
Output schema / properties / page_sizeRemoved value: -{ - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Page Size" -} - added
Output schema / properties / resultAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } + ] +} - removed
Output schema / properties / resultsRemoved value: -{ - "description": "Hierarchical results with related items nested", - "items": { - "$ref": "#/$defs/ContextResult" - }, - "title": "Results", - "type": "array" -} - changed
Output schema / requiredPrevious value: -[ - "metadata" -]New value: +[ + "result" +] - removed
Output schema / titleRemoved value: -"GraphContext" - added
Output schema / x-fastmcp-wrap-resultAdded value: +true
- Removed
canvas - Added
cat - Changed
create_memory_project13 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns human-readable result text.\n\"json\" returns structured project creation metadata.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / project_name / descriptionAdded value: +"Name for the new project (must be unique)" - removed
Input schema / properties / project_name / titleRemoved value: -"Project Name" - added
Input schema / properties / project_path / descriptionAdded value: +"File system path where the project will be stored" - removed
Input schema / properties / project_path / titleRemoved value: -"Project Path" - added
Input schema / properties / set_default / descriptionAdded value: +"Whether to set this project as the default (optional, defaults to False)" - removed
Input schema / properties / set_default / titleRemoved value: -"Set Default" - added
Input schema / properties / workspaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional cloud workspace selector to create the project in. Slug is\npreferred for AI callers, but tenant_id and unique name are also accepted.\nWhen omitted, the connection's default workspace is used. Discover values\nvia `list_workspaces`. A workspace selector implies cloud routing:\nwithout cloud credentials the call fails fast instead of silently\ncreating a local project." +} - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
delete_note11 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / identifier / descriptionAdded value: +"For files: note title or permalink to delete.\n For directories: the directory path (e.g., \"docs\", \"projects/2025\").\n Can be a title like \"Meeting Notes\" or permalink like \"notes/meeting-notes\"" - removed
Input schema / properties / identifier / titleRemoved value: -"Identifier" - added
Input schema / properties / is_directoryAdded value: +{ + "default": false, + "description": "If True, deletes an entire directory and all its contents.\n When True, identifier should be a directory path\n (without file extensions). Defaults to False.", + "type": "boolean" +} - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns true/false for a single note (false if not found),\na markdown summary for directories, or markdown guidance on error. \"json\"\nreturns machine-readable deletion metadata.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to delete from. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "type": "boolean" - }, - { - "type": "string" - } -]New value: +[ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "additionalProperties": true, + "type": "object" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Removed
delete_project - Changed
edit_note29 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / content / descriptionAdded value: +"The content to add or use for replacement" - removed
Input schema / properties / content / titleRemoved value: -"Content" - added
Input schema / properties / expected_checksumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional revision precondition: the full `checksum` that\nread_note, write_note, or edit_note returned in JSON mode (the accepted\nrevision's checksum; text output shows only its first 8 characters). When the\nnote has changed since, the edit is refused with a revision conflict that\nnames the current checksum, and nothing is written. A refused precondition\nnever auto-creates the note. To refresh a stale checksum without reading the\nwhole note, call read_note(identifier=..., include_content=False)." +} - added
Input schema / properties / expected_replacements / anyOfAdded value: +[ + { + "type": "integer" + }, + { + "type": "null" + } +] - changed
Input schema / properties / expected_replacements / defaultPrevious value: -1New value: +null - added
Input schema / properties / expected_replacements / descriptionAdded value: +"For find_replace: required occurrence count of find_text\n(default 1). A mismatch fails without writing." - removed
Input schema / properties / expected_replacements / titleRemoved value: -"Expected Replacements" - removed
Input schema / properties / expected_replacements / typeRemoved value: -"integer" - added
Input schema / properties / find_text / descriptionAdded value: +"For find_replace operation - the exact, case-sensitive text to replace" - removed
Input schema / properties / find_text / titleRemoved value: -"Find Text" - added
Input schema / properties / identifier / descriptionAdded value: +"The exact title, permalink, or memory:// URL of the note to edit.\n Must be an exact match - fuzzy matching is not supported for edit operations.\n Use search_notes() or read_note() first to find the correct identifier if uncertain.\n From the CLI this is a positional argument, not a flag." - removed
Input schema / properties / identifier / titleRemoved value: -"Identifier" - added
Input schema / properties / metadataAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional dict of frontmatter fields to merge, independent of `operation`.\nProvided keys overwrite existing frontmatter values (or are added if new);\nunrelated frontmatter keys and the note body are left untouched. Can be\ncombined with any operation in the same call. `title` and `permalink` are\nignored since those have their own dedicated handling; `type` is applied like\nany other frontmatter field. Key deletion is not supported." +} - added
Input schema / properties / operation / descriptionAdded value: +"The editing operation to perform:\n - \"append\": Add content to the end of the note (creates the note if it doesn't exist)\n - \"prepend\": Add content to the beginning of the note (creates the note if it doesn't exist)\n - \"find_replace\": Replace occurrences of find_text with content (note must exist)\n - \"replace_section\": Replace a markdown section identified by its header (note and section must exist).\n The heading must match exactly, including trailing tags or text; a miss fails without writing.\n By default the section spans through the next heading of the same or higher\n level, so its subsections are replaced too; see replace_subsections.\n - \"insert_before_section\": Insert content before a section heading without consuming it (note must exist)\n - \"insert_after_section\": Insert content after a section heading without consuming it (note must exist)" - added
Input schema / properties / operation / enumAdded value: +[ + "append", + "prepend", + "find_replace", + "replace_section", + "insert_before_section", + "insert_after_section" +] - removed
Input schema / properties / operation / titleRemoved value: -"Operation" - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns a markdown summary of the edit and the note's\nresulting observations and relations. \"json\" returns machine-readable edit\nmetadata.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to edit in. Optional - server will resolve using hierarchy.\n Use \"workspace/project\" to route to a project in a specific cloud workspace.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / replace_subsectionsAdded value: +{ + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "For replace_section operation. Default (true): the section\nspans everything through the next heading of the same or higher level in the\noriginal note, so replacing \"## Section\" also replaces its \"###\" subsections —\nthe replacement content may freely introduce new headings. Set to false to\nreplace only the immediate content under the header, stopping at the next\nheading of any level and preserving subsections." +} - added
Input schema / properties / section / descriptionAdded value: +"Heading for replace_section, insert_before_section, and\ninsert_after_section (e.g. \"## Notes\", \"### Implementation\"). Must match exactly." - removed
Input schema / properties / section / titleRemoved value: -"Section" - added
Input schema / properties / workspaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Workspace slug, name, or tenant_id. When provided with `project`,\n routes as `workspace/project`. Cannot be combined with `project_id`." +} - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
fetch5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / id / descriptionAdded value: +"Document identifier (permalink, title, or memory URL)" - removed
Input schema / properties / id / titleRemoved value: -"Id" - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Added
find - Added
grep - Changed
list_directory18 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / depth / descriptionAdded value: +"Recursion depth (1-10, default: 1 for immediate children only)\n Higher values show subdirectory contents recursively" - removed
Input schema / properties / depth / titleRemoved value: -"Depth" - added
Input schema / properties / dir_name / descriptionAdded value: +"Directory path to list (default: root \"/\")\n Examples: \"/\", \"/projects\", \"/research/ml\"" - removed
Input schema / properties / dir_name / titleRemoved value: -"Dir Name" - added
Input schema / properties / file_name_glob / descriptionAdded value: +"Optional glob pattern for filtering file names\n Examples: \"*.md\", \"*meeting*\", \"project_*\"" - removed
Input schema / properties / file_name_glob / titleRemoved value: -"File Name Glob" - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" for a readable listing or \"json\" for structured pagination data", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / pageAdded value: +{ + "default": 1, + "description": "One-indexed result page (default: 1)", + "type": "integer" +} - added
Input schema / properties / page_sizeAdded value: +{ + "default": 10, + "description": "Number of nodes per page (default: 10, maximum: 200)", + "type": "integer" +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to list directory from. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / sortAdded value: +{ + "anyOf": [ + { + "enum": [ + "title_asc", + "title_desc", + "updated_asc", + "updated_desc" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional file ordering: \"title_asc\", \"title_desc\", \"updated_asc\",\n or \"updated_desc\". Directories remain first." +} - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
list_memory_projects6 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns a human-readable project list.\n\"json\" returns structured project metadata.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Added
list_workspaces - Added
ls - Added
man - Changed
move_note17 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / destination_folderAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Move the note into this folder, preserving the original filename.\n Mutually exclusive with destination_path. Only for single-file moves." +} - added
Input schema / properties / destination_path / defaultAdded value: +"" - added
Input schema / properties / destination_path / descriptionAdded value: +"For files: new path relative to project root (e.g., \"work/meetings/note.md\")\n For directories: new directory path (e.g., \"archive/docs\")\n Mutually exclusive with destination_folder." - removed
Input schema / properties / destination_path / titleRemoved value: -"Destination Path" - added
Input schema / properties / identifier / descriptionAdded value: +"For files: exact entity identifier (title, permalink, or memory:// URL).\n For directories: the directory path (e.g., \"docs\", \"projects/2025\").\n Must be an exact match - fuzzy matching is not supported for move operations.\n Use search_notes() or list_directory() first to find the correct path if uncertain." - removed
Input schema / properties / identifier / titleRemoved value: -"Identifier" - added
Input schema / properties / is_directoryAdded value: +{ + "default": false, + "description": "If True, moves an entire directory and all its contents.\n When True, identifier and destination_path should be directory paths\n (without file extensions). Defaults to False.", + "type": "boolean" +} - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns a markdown success or failure message. \"json\"\nreturns machine-readable move metadata, with an error code on failure.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to move within. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - changed
Input schema / requiredPrevious value: -[ - "identifier", - "destination_path" -]New value: +[ + "identifier" +] - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
read_content6 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / path / descriptionAdded value: +"The path or permalink to the file. Can be:\n- A regular file path (docs/example.md)\n- A memory URL (memory://docs/example)\n- A permalink (docs/example)" - removed
Input schema / properties / path / titleRemoved value: -"Path" - added
Input schema / properties / project / descriptionAdded value: +"Project name to read from. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +}
- Changed
read_note19 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / end_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Last document line to read (inclusive); omitted means EOF.\nOut-of-file ranges return empty content; invalid/reversed ranges fail.\nWith either bound, text output is numbered and JSON carries coordinates,\nhas_more, and next_start_line/next_end_line. include_frontmatter does\nnot strip an explicitly addressed range. Edits between calls may shift lines." +} - added
Input schema / properties / identifier / descriptionAdded value: +"The title or permalink of the note to read.\n Can be a full memory:// URL, a permalink, a title, or search text.\n From the CLI this is a positional argument, not a flag." - removed
Input schema / properties / identifier / titleRemoved value: -"Identifier" - added
Input schema / properties / include_contentAdded value: +{ + "default": true, + "description": "Default true. Set to false to return only the note's metadata —\ntitle, permalink, file_path, the full accepted-revision checksum, and\nupdated_at — without the body. Use it to refresh the checksum that\nedit_note/write_note take as expected_checksum without reading the whole\nnote. Cannot be combined with start_line/end_line.", + "type": "boolean" +} - added
Input schema / properties / include_frontmatterAdded value: +{ + "default": false, + "description": "For unsliced JSON reads, include opening YAML in content;\nparsed frontmatter is returned either way. Explicit line ranges are never\nstripped. CLI: --frontmatter (--include-frontmatter is a deprecated alias).", + "type": "boolean" +} - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns markdown content or guidance text.\n\"json\" returns a structured object with title/permalink/file_path/content/frontmatter.\nUnresolved notes carry error=\"NOTE_NOT_FOUND\" and a message, with\nrelated_results when suggestions are available.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / page / descriptionAdded value: +"Page of fallback-search results to use when the identifier does not\nresolve to a note directly (default: 1). A direct or exact-title match\nreturns the note content — page/page_size never chunk the\nnote itself, and the title-match lookup pages through fixed-size pages\nof title results until an exact match is found or results are\nexhausted, regardless of page or page_size. Aliases: page_number." - removed
Input schema / properties / page / titleRemoved value: -"Page" - added
Input schema / properties / page_size / descriptionAdded value: +"Number of fallback-search results per page (default: 10). When no\nmatch is found, this caps how many related-note suggestions are listed.\nAliases: limit, per_page." - removed
Input schema / properties / page_size / titleRemoved value: -"Page Size" - added
Input schema / properties / project / descriptionAdded value: +"Project name to read from. Optional - when omitted, a project prefix\n on a memory:// URL or permalink identifier routes the read; otherwise the\n server uses the configured default project. If unknown, use\n list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / start_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "First document line to read (1-based, inclusive). Defaults to 1\nwhen only end_line is given. Line scans count the full Markdown,\nincluding frontmatter, matching cat's default line coordinates." +} - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
recent_activity17 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / depth / descriptionAdded value: +"How many relation hops to traverse (1-3 recommended, maximum: 5)" - removed
Input schema / properties / depth / titleRemoved value: -"Depth" - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns human-readable summary text. \"json\" returns\na flat list of recent items.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / pageAdded value: +{ + "default": 1, + "description": "Page number for pagination (default 1)", + "type": "integer" +} - added
Input schema / properties / page_sizeAdded value: +{ + "default": 10, + "description": "Number of items per page (default 10, maximum: 100)", + "type": "integer" +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to query. Optional - when omitted, the server uses the\n configured default project, and discovery mode across all projects\n applies only when there is no default.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / timeframe / descriptionAdded value: +"Time window to search. Supports natural language:\n- Relative: \"2 days ago\", \"last week\", \"yesterday\"\n- Points in time: \"2024-01-01\", \"January 1st\"\n- Standard format: \"7d\", \"24h\"\nAliases: since, time_range, lookback." - removed
Input schema / properties / timeframe / titleRemoved value: -"Timeframe" - added
Input schema / properties / type / descriptionAdded value: +"Filter by content type(s). Can be a string or list of strings.\nValid options:\n- \"entity\" or [\"entity\"] for knowledge entities\n- \"relation\" or [\"relation\"] for connections between entities\n- \"observation\" or [\"observation\"] for notes and observations\nMultiple types can be combined: [\"entity\", \"relation\"]\nCase-insensitive: \"ENTITY\" and \"entity\" are treated the same.\nDefault is entity-only. Specify other types explicitly to include\nobservations and relations." - removed
Input schema / properties / type / titleRemoved value: -"Type" - added
Output schema / properties / result / anyOfAdded value: +[ + { + "type": "string" + }, + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Added
schema_diff - Added
schema_infer - Added
schema_validate - Changed
search5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / query / descriptionAdded value: +"Search query (full-text syntax supported by `search_notes`)" - removed
Input schema / properties / query / titleRemoved value: -"Query" - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
search_notes41 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / after_date / descriptionAdded value: +"Optional date filter for recent content (e.g., \"1 week\", \"2d\", \"2024-01-01\")" - removed
Input schema / properties / after_date / titleRemoved value: -"After Date" - added
Input schema / properties / categoriesAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Observation categories to match exactly (e.g. [\"requirement\"]). Implies\nobservation results unless entity_types is set. Accepts a list, a\ncomma-separated string, or a JSON-array string." +} - added
Input schema / properties / compactAdded value: +{ + "default": false, + "description": "Omit note bodies and matched excerpts from results. Keep identifiers, metadata, relation targets, scores and pagination for discovery, then read selected notes.", + "type": "boolean" +} - added
Input schema / properties / entity_types / descriptionAdded value: +"Knowledge-graph item types to return: \"entity\" (whole notes),\n\"observation\", \"relation\". Defaults to entity, or to observation when categories\nor a valid-time filter is given. Not the frontmatter `type` (use note_types for\nthat). Accepts a list, a comma-separated string, or a JSON-array string." - removed
Input schema / properties / entity_types / titleRemoved value: -"Entity Types" - added
Input schema / properties / metadata_filtersAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Structured frontmatter filters, {field: condition}. Nested fields use dot notation (\"schema.confidence\"). Conditions: a value for equality ({\"status\": \"draft\"}); null for absent-or-null ({\"owner\": null}); a list for array-contains-all ({\"tags\": [\"a\", \"b\"]}); or an operator object using $gt, $gte, $lt, $lte, $in (list), $between ([min, max]), $contains (value or list), $exists (true/false), e.g. {\"priority\": {\"$in\": [\"high\"]}}. Several operators on one field AND together: {\"started\": {\"$gte\": \"2026-01-01\", \"$lt\": \"2026-02-01\"}}. The leading $ is optional." +} - added
Input schema / properties / min_similarityAdded value: +{ + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional float to override the global semantic_min_similarity threshold\n for this query. E.g., 0.0 to see all vector results, or 0.8 for high precision.\n Only applies to vector and hybrid search types." +} - added
Input schema / properties / note_typesAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by the frontmatter `type` field (e.g. \"note\", \"person\").\nCase-insensitive. Accepts a list, a comma-separated string, or a JSON-array string." +} - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns a formatted markdown result list. \"json\" returns a\nmachine-readable dictionary payload.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / page / descriptionAdded value: +"The page number of results to return (default 1).\nAliases: page_number." - removed
Input schema / properties / page / titleRemoved value: -"Page" - added
Input schema / properties / page_size / descriptionAdded value: +"The number of results to return per page (default 10).\nAliases: limit, per_page." - removed
Input schema / properties / page_size / titleRemoved value: -"Page Size" - added
Input schema / properties / project / descriptionAdded value: +"Project name to search in. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / projectsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional list of project names or external ids to search together. Names\n are matched exactly as list_memory_projects() reports them (cloud projects\n by their workspace-qualified name). Ignored when `project` or `project_id`\n is supplied; an unknown name is an error rather than a silent skip." +} - added
Input schema / properties / query / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / query / defaultAdded value: +null - added
Input schema / properties / query / descriptionAdded value: +"Optional search query string (supports boolean operators, phrases, patterns).\n Omit or pass None for filter-only searches using metadata_filters, tags, or status." - removed
Input schema / properties / query / titleRemoved value: -"Query" - removed
Input schema / properties / query / typeRemoved value: -"string" - added
Input schema / properties / search_all_projectsAdded value: +{ + "default": false, + "description": "Optional opt-in to search every accessible project. Ignored when\n `project` or `project_id` is supplied.", + "type": "boolean" +} - added
Input schema / properties / search_type / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / search_type / defaultPrevious value: -"text"New value: +null - added
Input schema / properties / search_type / descriptionAdded value: +"Type of search to perform, one of:\n \"text\", \"title\", \"permalink\", \"vector\", \"semantic\", \"hybrid\".\n Default is dynamic: \"hybrid\" when semantic search is enabled, otherwise \"text\"." - removed
Input schema / properties / search_type / titleRemoved value: -"Search Type" - removed
Input schema / properties / search_type / typeRemoved value: -"string" - added
Input schema / properties / statusAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional status filter (frontmatter status); shorthand for metadata_filters[\"status\"]" +} - added
Input schema / properties / tagsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional tag filter (frontmatter tags); shorthand for metadata_filters[\"tags\"].\n Accepts a list ([\"a\", \"b\"]) or a comma-separated string (\"a,b\"), matching the\n write_note tags convention and the tag: query shorthand." +} - added
Input schema / properties / time_kindAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional kind of valid time to narrow to: \"effective\", \"valid\",\n \"occurred\", \"due\", or \"mentioned\". Valid on its own. Alias: kind." +} - removed
Input schema / properties / typesRemoved value: -{ - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Types" -} - added
Input schema / properties / valid_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional date (\"2026-07-28\") or RFC 3339 instant (\"2026-07-28T09:00:00Z\";\n a timestamp with no offset is read as UTC). Returns sources whose authored\n valid range contains it. Sources with no temporal qualifier are excluded.\n Aliases: as_of, valid_on." +} - added
Input schema / properties / valid_overlapsAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional PostgreSQL-style range literal (\"[2026-06-10,2026-07-27)\",\n \"(,2026-07-27]\", \"[2026-06-10,)\"). Returns sources whose authored valid range\n overlaps it. Mutually exclusive with valid_at; also excludes undated sources.\n Aliases: overlaps, valid_during." +} - removed
Input schema / requiredRemoved value: -[ - "query" -] - removed
Output schema / $defsRemoved value: -{ - "SearchItemType": { - "description": "Types of searchable items.", - "enum": [ - "entity", - "observation", - "relation" - ], - "title": "SearchItemType", - "type": "string" - }, - "SearchResponse": { - "description": "Wrapper for search results.", - "properties": { - "current_page": { - "title": "Current Page", - "type": "integer" - }, - "page_size": { - "title": "Page Size", - "type": "integer" - }, - "results": { - "items": { - "$ref": "#/$defs/SearchResult" - }, - "title": "Results", - "type": "array" - } - }, - "required": [ - "results", - "current_page", - "page_size" - ], - "title": "SearchResponse", - "type": "object" - }, - "SearchResult": { - "description": "Search result with score and metadata.", - "properties": { - "category": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Category" - }, - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Content" - }, - "entity": { - "anyOf": [ - { - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Entity" - }, - "entity_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Entity Id" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "from_entity": { - "anyOf": [ - { - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "From Entity" - }, - "metadata": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Metadata" - }, - "observation_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Observation Id" - }, - "permalink": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Permalink" - }, - "relation_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Relation Id" - }, - "relation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Relation Type" - }, - "score": { - "title": "Score", - "type": "number" - }, - "title": { - "title": "Title", - "type": "string" - }, - "to_entity": { - "anyOf": [ - { - "minLength": 1, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "To Entity" - }, - "type": { - "$ref": "#/$defs/SearchItemType" - } - }, - "required": [ - "title", - "type", - "score", - "permalink", - "file_path" - ], - "title": "SearchResult", - "type": "object" - } -} - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "$ref": "#/$defs/SearchResponse" - }, - { - "type": "string" - } -]New value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Added
tail - Changed
view_note10 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / identifier / descriptionAdded value: +"The title or permalink of the note to view" - removed
Input schema / properties / identifier / titleRemoved value: -"Identifier" - removed
Input schema / properties / pageRemoved value: -{ - "default": 1, - "title": "Page", - "type": "integer" -} - removed
Input schema / properties / page_sizeRemoved value: -{ - "default": 10, - "title": "Page Size", - "type": "integer" -} - added
Input schema / properties / project / descriptionAdded value: +"Project name to read from. Optional - server will resolve using hierarchy.\n If unknown, use list_memory_projects() to discover available projects." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / titleRemoved value: -"_WrappedResult"
- Changed
write_note24 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / content / descriptionAdded value: +"Markdown content for the note, can include observations and relations.\nMay carry its own frontmatter; a `type:` in content frontmatter takes\nprecedence over the note_type parameter." - removed
Input schema / properties / content / titleRemoved value: -"Content" - added
Input schema / properties / directoryAdded value: +{ + "description": "Directory path relative to project root where the file should be saved.\n Use forward slashes (/) as separators. Use \"/\" or \"\" to write to project root.\n Examples: \"notes\", \"projects/2025\", \"research/ml\", \"/\" (root).\n MCP accepts the aliases folder, dir, and path; the CLI flag is --folder.", + "type": "string" +} - added
Input schema / properties / expected_checksumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional revision precondition for overwrite=True: the checksum\n of the note you read (from a JSON read_note, write_note or edit_note\n result). The\n note is replaced only while it is still that revision; otherwise the\n tool reports a revision conflict with the current checksum and changes\n nothing. Omit it to replace the note unconditionally." +} - removed
Input schema / properties / folderRemoved value: -{ - "title": "Folder", - "type": "string" -} - added
Input schema / properties / metadataAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional dict of extra frontmatter fields merged into entity_metadata.\n Useful for schema notes or any note that needs custom YAML frontmatter\n beyond title/type/tags. Nested dicts are supported. Not available from the CLI." +} - added
Input schema / properties / note_type / descriptionAdded value: +"Type of note to create (stored in frontmatter `type:`). Defaults to \"note\".\n Can be \"guide\", \"report\", \"config\", \"person\", etc. The CLI flag is --type.\n A `type:` in content frontmatter takes precedence over this parameter, and\n this is what schema validation keys on." - removed
Input schema / properties / note_type / titleRemoved value: -"Note Type" - added
Input schema / properties / output_formatAdded value: +{ + "default": "text", + "description": "\"text\" returns a markdown summary. \"json\" returns\n machine-readable metadata. A refused write (note exists, revision\n conflict, moved target, disallowed directory) is a tool error; in\n JSON mode its message is the payload with action: \"conflict\" and an\n error code.", + "enum": [ + "text", + "json" + ], + "type": "string" +} - added
Input schema / properties / overwriteAdded value: +{ + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If True, replace existing note on conflict. If False, error on conflict.\n If None (default), consult write_note_overwrite_default config setting.\n Overwrite replaces the body but merges frontmatter: keys the existing\n note has and this write does not set (custom fields) are kept, while\n keys this write sets (title, type, tags, metadata, or frontmatter in\n content) replace the old values. Existing frontmatter that cannot be\n parsed is discarded rather than merged. To remove a key, rewrite it\n with edit_note or edit the file." +} - added
Input schema / properties / project / descriptionAdded value: +"Project name to write to. Optional. Omitting both project and project_id\n writes to the configured default project. Calls do not remember a\n project between them, so after working in another project, pass project\n explicitly. Use\n \"workspace/project\" to route to a project in a specific cloud workspace.\n A bare name that exists in multiple workspaces resolves to the default\n workspace, so use the qualified form (or project_id) to disambiguate. If\n unknown, use list_memory_projects() to discover available projects and\n their qualified names." - removed
Input schema / properties / project / titleRemoved value: -"Project" - added
Input schema / properties / project_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Project external_id (UUID). Prefer this over `project` when known —\n it routes to the exact project regardless of name collisions across cloud\n workspaces. Takes precedence over `project`. Get from list_memory_projects()." +} - added
Input schema / properties / tags / descriptionAdded value: +"Tags to categorize the note. Can be a list of strings, a comma-separated string, or None.\n Note: If passing from external MCP clients, use a string format (e.g. \"tag1,tag2,tag3\")" - removed
Input schema / properties / tags / titleRemoved value: -"Tags" - added
Input schema / properties / title / descriptionAdded value: +"The title of the note; written to frontmatter and drives the permalink.\nNo H1 is added for you: content is saved as given, so include a\n\"# Title\" heading yourself if the note should open with one." - removed
Input schema / properties / title / titleRemoved value: -"Title" - added
Input schema / properties / workspaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Workspace slug, name, or tenant_id. When provided with `project`,\n routes as `workspace/project`. Cannot be combined with `project_id`." +} - changed
Input schema / requiredPrevious value: -[ - "title", - "content", - "folder" -]New value: +[ + "title", + "content", + "directory" +] - added
Output schema / properties / result / anyOfAdded value: +[ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "string" + } +] - removed
Output schema / properties / result / titleRemoved value: -"Result" - removed
Output schema / properties / result / typeRemoved value: -"string" - removed
Output schema / titleRemoved value: -"_WrappedResult"
11 tool updates
v1.0.0- Changed
build_context12 fields changed- removed
Input schema / $defsRemoved value: -{ - "StringOrInt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } -} - changed
Input schema / properties / depth / anyOfPrevious value: -[ - { - "$ref": "#/$defs/StringOrInt" - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } +] - added
Output schema / $defs / EntitySummary / properties / entity_idAdded value: +{ + "title": "Entity Id", + "type": "integer" +} - changed
Output schema / $defs / EntitySummary / requiredPrevious value: -[ - "permalink", - "title", - "file_path", - "created_at" -]New value: +[ + "entity_id", + "permalink", + "title", + "file_path", + "created_at" +] - added
Output schema / $defs / ObservationSummary / properties / entity_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Entity Id" +} - added
Output schema / $defs / ObservationSummary / properties / observation_idAdded value: +{ + "title": "Observation Id", + "type": "integer" +} - changed
Output schema / $defs / ObservationSummary / requiredPrevious value: -[ - "title", - "file_path", - "permalink", - "category", - "content", - "created_at" -]New value: +[ + "observation_id", + "title", + "file_path", + "permalink", + "category", + "content", + "created_at" +] - added
Output schema / $defs / RelationSummary / properties / entity_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Entity Id" +} - added
Output schema / $defs / RelationSummary / properties / from_entity_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "From Entity Id" +} - added
Output schema / $defs / RelationSummary / properties / relation_idAdded value: +{ + "title": "Relation Id", + "type": "integer" +} - added
Output schema / $defs / RelationSummary / properties / to_entity_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To Entity Id" +} - changed
Output schema / $defs / RelationSummary / requiredPrevious value: -[ - "title", - "file_path", - "permalink", - "relation_type", - "created_at" -]New value: +[ + "relation_id", + "title", + "file_path", + "permalink", + "relation_type", + "created_at" +]
- Added
fetch - Removed
get_current_project - Changed
list_memory_projects1 field changed- removed
Input schema / properties / _compatibilityRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Compatibility" -}
- Changed
recent_activity13 fields changed- removed
Input schema / properties / max_relatedRemoved value: -{ - "default": 10, - "title": "Max Related", - "type": "integer" -} - removed
Input schema / properties / pageRemoved value: -{ - "default": 1, - "title": "Page", - "type": "integer" -} - removed
Input schema / properties / page_sizeRemoved value: -{ - "default": 10, - "title": "Page Size", - "type": "integer" -} - removed
Output schema / $defsRemoved value: -{ - "ContextResult": { - "description": "Context result containing a primary item with its observations and related items.", - "properties": { - "observations": { - "description": "Observations belonging to this entity", - "items": { - "$ref": "#/$defs/ObservationSummary" - }, - "title": "Observations", - "type": "array" - }, - "primary_result": { - "description": "Primary item", - "discriminator": { - "mapping": { - "entity": "#/$defs/EntitySummary", - "observation": "#/$defs/ObservationSummary", - "relation": "#/$defs/RelationSummary" - }, - "propertyName": "type" - }, - "oneOf": [ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } - ], - "title": "Primary Result" - }, - "related_results": { - "description": "Related items", - "items": { - "discriminator": { - "mapping": { - "entity": "#/$defs/EntitySummary", - "observation": "#/$defs/ObservationSummary", - "relation": "#/$defs/RelationSummary" - }, - "propertyName": "type" - }, - "oneOf": [ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } - ] - }, - "title": "Related Results", - "type": "array" - } - }, - "required": [ - "primary_result" - ], - "title": "ContextResult", - "type": "object" - }, - "EntitySummary": { - "description": "Simplified entity representation.", - "properties": { - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Content" - }, - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "permalink": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Permalink" - }, - "title": { - "title": "Title", - "type": "string" - }, - "type": { - "const": "entity", - "default": "entity", - "title": "Type", - "type": "string" - } - }, - "required": [ - "permalink", - "title", - "file_path", - "created_at" - ], - "title": "EntitySummary", - "type": "object" - }, - "MemoryMetadata": { - "description": "Simplified response metadata.", - "properties": { - "depth": { - "title": "Depth", - "type": "integer" - }, - "generated_at": { - "format": "date-time", - "title": "Generated At", - "type": "string" - }, - "primary_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Primary Count" - }, - "related_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Related Count" - }, - "timeframe": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Timeframe" - }, - "total_observations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Observations" - }, - "total_relations": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Relations" - }, - "total_results": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Total Results" - }, - "types": { - "anyOf": [ - { - "items": { - "$ref": "#/$defs/SearchItemType" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Types" - }, - "uri": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Uri" - } - }, - "required": [ - "depth", - "generated_at" - ], - "title": "MemoryMetadata", - "type": "object" - }, - "ObservationSummary": { - "description": "Simplified observation representation.", - "properties": { - "category": { - "title": "Category", - "type": "string" - }, - "content": { - "title": "Content", - "type": "string" - }, - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "permalink": { - "title": "Permalink", - "type": "string" - }, - "title": { - "title": "Title", - "type": "string" - }, - "type": { - "const": "observation", - "default": "observation", - "title": "Type", - "type": "string" - } - }, - "required": [ - "title", - "file_path", - "permalink", - "category", - "content", - "created_at" - ], - "title": "ObservationSummary", - "type": "object" - }, - "RelationSummary": { - "description": "Simplified relation representation.", - "properties": { - "created_at": { - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "file_path": { - "title": "File Path", - "type": "string" - }, - "from_entity": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "From Entity" - }, - "permalink": { - "title": "Permalink", - "type": "string" - }, - "relation_type": { - "title": "Relation Type", - "type": "string" - }, - "title": { - "title": "Title", - "type": "string" - }, - "to_entity": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "To Entity" - }, - "type": { - "const": "relation", - "default": "relation", - "title": "Type", - "type": "string" - } - }, - "required": [ - "title", - "file_path", - "permalink", - "relation_type", - "created_at" - ], - "title": "RelationSummary", - "type": "object" - }, - "SearchItemType": { - "description": "Types of searchable items.", - "enum": [ - "entity", - "observation", - "relation" - ], - "title": "SearchItemType", - "type": "string" - } -} - removed
Output schema / descriptionRemoved value: -"Complete context response." - removed
Output schema / properties / metadataRemoved value: -{ - "$ref": "#/$defs/MemoryMetadata" -} - removed
Output schema / properties / pageRemoved value: -{ - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Page" -} - removed
Output schema / properties / page_sizeRemoved value: -{ - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Page Size" -} - added
Output schema / properties / resultAdded value: +{ + "title": "Result", + "type": "string" +} - removed
Output schema / properties / resultsRemoved value: -{ - "description": "Hierarchical results with related items nested", - "items": { - "$ref": "#/$defs/ContextResult" - }, - "title": "Results", - "type": "array" -} - changed
Output schema / requiredPrevious value: -[ - "metadata" -]New value: +[ + "result" +] - changed
Output schema / titlePrevious value: -"GraphContext"New value: +"_WrappedResult" - added
Output schema / x-fastmcp-wrap-resultAdded value: +true
- Added
search - Changed
search_notes3 fields changed- added
Output schema / $defs / SearchResult / properties / entity_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Entity Id" +} - added
Output schema / $defs / SearchResult / properties / observation_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Observation Id" +} - added
Output schema / $defs / SearchResult / properties / relation_idAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Relation Id" +}
- Removed
set_default_project - Removed
switch_project - Removed
sync_status - Changed
write_note3 fields changed- removed
Input schema / properties / entity_typeRemoved value: -{ - "default": "note", - "title": "Entity Type", - "type": "string" -} - added
Input schema / properties / note_typeAdded value: +{ + "default": "note", + "title": "Note Type", + "type": "string" +} - added
Input schema / properties / tags / anyOfAdded value: +[ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "null" + } +]
2 tool updates
- Changed
build_context11 fields changed- added
Input schema / $defsAdded value: +{ + "StringOrInt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } +} - changed
Input schema / properties / depth / anyOfPrevious value: -[ - { - "type": "integer" - }, - { - "type": "null" - } -]New value: +[ + { + "$ref": "#/$defs/StringOrInt" + }, + { + "type": "null" + } +] - removed
Output schema / $defs / ContextResult / properties / primary_result / anyOfRemoved value: -[ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } -] - added
Output schema / $defs / ContextResult / properties / primary_result / discriminatorAdded value: +{ + "mapping": { + "entity": "#/$defs/EntitySummary", + "observation": "#/$defs/ObservationSummary", + "relation": "#/$defs/RelationSummary" + }, + "propertyName": "type" +} - added
Output schema / $defs / ContextResult / properties / primary_result / oneOfAdded value: +[ + { + "$ref": "#/$defs/EntitySummary" + }, + { + "$ref": "#/$defs/RelationSummary" + }, + { + "$ref": "#/$defs/ObservationSummary" + } +] - removed
Output schema / $defs / ContextResult / properties / related_results / items / anyOfRemoved value: -[ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } -] - added
Output schema / $defs / ContextResult / properties / related_results / items / discriminatorAdded value: +{ + "mapping": { + "entity": "#/$defs/EntitySummary", + "observation": "#/$defs/ObservationSummary", + "relation": "#/$defs/RelationSummary" + }, + "propertyName": "type" +} - added
Output schema / $defs / ContextResult / properties / related_results / items / oneOfAdded value: +[ + { + "$ref": "#/$defs/EntitySummary" + }, + { + "$ref": "#/$defs/RelationSummary" + }, + { + "$ref": "#/$defs/ObservationSummary" + } +] - added
Output schema / $defs / EntitySummary / properties / type / constAdded value: +"entity" - added
Output schema / $defs / ObservationSummary / properties / type / constAdded value: +"observation" - added
Output schema / $defs / RelationSummary / properties / type / constAdded value: +"relation"
- Changed
recent_activity9 fields changed- removed
Output schema / $defs / ContextResult / properties / primary_result / anyOfRemoved value: -[ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } -] - added
Output schema / $defs / ContextResult / properties / primary_result / discriminatorAdded value: +{ + "mapping": { + "entity": "#/$defs/EntitySummary", + "observation": "#/$defs/ObservationSummary", + "relation": "#/$defs/RelationSummary" + }, + "propertyName": "type" +} - added
Output schema / $defs / ContextResult / properties / primary_result / oneOfAdded value: +[ + { + "$ref": "#/$defs/EntitySummary" + }, + { + "$ref": "#/$defs/RelationSummary" + }, + { + "$ref": "#/$defs/ObservationSummary" + } +] - removed
Output schema / $defs / ContextResult / properties / related_results / items / anyOfRemoved value: -[ - { - "$ref": "#/$defs/EntitySummary" - }, - { - "$ref": "#/$defs/RelationSummary" - }, - { - "$ref": "#/$defs/ObservationSummary" - } -] - added
Output schema / $defs / ContextResult / properties / related_results / items / discriminatorAdded value: +{ + "mapping": { + "entity": "#/$defs/EntitySummary", + "observation": "#/$defs/ObservationSummary", + "relation": "#/$defs/RelationSummary" + }, + "propertyName": "type" +} - added
Output schema / $defs / ContextResult / properties / related_results / items / oneOfAdded value: +[ + { + "$ref": "#/$defs/EntitySummary" + }, + { + "$ref": "#/$defs/RelationSummary" + }, + { + "$ref": "#/$defs/ObservationSummary" + } +] - added
Output schema / $defs / EntitySummary / properties / type / constAdded value: +"entity" - added
Output schema / $defs / ObservationSummary / properties / type / constAdded value: +"observation" - added
Output schema / $defs / RelationSummary / properties / type / constAdded value: +"relation"
19 tool updates
- First observed
build_context - First observed
canvas - First observed
create_memory_project - First observed
delete_note - First observed
delete_project - First observed
edit_note - First observed
get_current_project - First observed
list_directory - First observed
list_memory_projects - First observed
move_note - First observed
read_content - First observed
read_note - First observed
recent_activity - First observed
search_notes - First observed
set_default_project - First observed
switch_project - First observed
sync_status - First observed
view_note - First observed
write_note
TDQS
Scored across 38 tools
The set contains several parallel tool families for the same operations: read_note/bm_read/cat, search_notes/bm_search/grep/search, edit_note/bm_edit, write_note/bm_write, delete_note/bm_delete, list_directory/ls/bm_list, find/bm_find, man/bm_man, and schema_* / bm_schema. Some descriptions distinguish special cases, but an agent can easily misselect among aliases that target the same resource and action.
Naming mixes bm_* prefixed tools, unprefixed snake_case tools, shell-style names like cat/grep/ls/find/tail/man, and one-off basic_memory_diagnostics. There is no single predictable convention across the 38 tools, even though individual names are readable.
38 tools is too many for the apparent scope, especially because many are duplicate aliases across the bm_* and unprefixed families. The useful surface could likely be consolidated to roughly 15-20 tools without losing functionality.
The domain is knowledge-note management, and the surface covers create/read/update/delete, search, listing, moving, project management, schemas, graph context, recent activity, diagnostics, and manual lookup. Despite redundancy, there are no obvious lifecycle gaps or dead ends.
Maintenance
Related MCP Connectors
Personal wiki and memory layer for AI assistants. Persistent, structured memory across sessions.
- ContextaOAuthcc.contexta
Persistent memory and knowledge graph for AI assistants — keyword + vector + graph search.
Persistent, portable memory for AI assistants — your private memory graph, from any MCP client.
Persistent memory for AI agents. Semantic search, memory graph, W3C DID identity.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceProvides persistent memory functionality for AI conversations by creating, managing and querying entities and relationships in a knowledge graph. Features SQLite storage, advanced search capabilities, and Windows auto-start integration for long-term AI memory retention.16 npmMIT
- AlicenseAqualityAmaintenancePersistent memory with knowledge graph visualization, semantic/hybrid search, importance scoring, and cloud sync (S3/R2) for cross-session context management.44744MIT
- AlicenseNot gradedqualityCmaintenanceProvides persistent memory for AI tools by building a local knowledge graph from conversations, enabling cross-session recall and context awareness without cloud dependencies.9MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to share persistent, self-improving memory by ingesting, classifying, synthesizing, and retrieving knowledge from Obsidian vaults, code, documents, transcripts, bookmarks, and sessions through MCP and REST interfaces with token-optimized search.14 npmMIT