Skip to main content
Glama

MCP Toplist

License: AGPL v3 PyPI version Python 3.12+ Tests Ruff Ask DeepWiki

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.

Start free trial →

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

Start free trial →

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=allow

Configure your client ↓

What 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 BMFOSS for another 20% off for 3 months (~$11.40/mo).

Start your 7-day free trial →

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

Claude Desktop

stdio/https

macOS / Windows / Linux

Claude Code

stdio/https

claude mcp add

Codex

stdio/https

OpenAI's coding agent

Cursor

stdio/https

.cursor/mcp.json

VS Code

stdio/https

Native MCP support

ChatGPT

https

Custom GPT actions (search / fetch)

Obsidian

—

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-check

Package-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-openclaw

Claude 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-code

That 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 -g

For 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/hermes

Hermes 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-memory

Pick 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 mcp

For 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 tool and Homebrew installs; bm update triggers 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 bm_schema(command="infer"), bm_schema(command="validate"), and bm_schema(command="diff").

  • Per-project cloud routing. Route individual projects through the cloud while others stay local, via API key (bm project set-cloud).

  • Explicit note changes. bm_edit updates existing notes; bm_write creates notes and guards 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. --json output 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=true

The default model is jinaai/jina-reranker-v1-tiny-en. To use a hosted reranker through LiteLLM instead, first install the optional LiteLLM SDK, then configure it:

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: bm_write, bm_read, bm_edit, bm_move, bm_delete

  • Search & discovery: bm_search, bm_list, bm_find

  • Knowledge graph: bm_context

  • Projects: bm_project(command="list" | "create" | "recent"); bm_project_delete is separate and requires server opt-in.

  • Schema: bm_schema(command="validate" | "infer" | "diff")

  • Manual: bm_man

  • Cloud connector adapters: search and fetch are registered by Cloud only. Local diagnostics use bm doctor.

Most tools default to text; bm_context defaults to JSON. Pass output_format="json" for structured responses. Project-scoped tools accept a name, workspace/project, or external UUID through project. Use bm_man(page="bm-search(3)") for the installed contract, or see the tool guide. CLI commands retain their shell names.

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 ...  # 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-json

Routing 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, Homebrew

  • Skipped for uvx (ephemeral runtime managed by uv)

  • Manual: bm update (check + apply) or bm 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=1

This 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

BASIC_MEMORY_LOG_LEVEL

INFO

DEBUG / INFO / WARNING / ERROR

BASIC_MEMORY_CLOUD_MODE

false

API logs to stdout with structured context

BASIC_MEMORY_FORCE_LOCAL

false

Force local API routing

BASIC_MEMORY_FORCE_CLOUD

false

Force cloud API routing

BASIC_MEMORY_EXPLICIT_ROUTING

false

Mark route selection as explicit

BASIC_MEMORY_ENV

dev

Set to test for test mode (stderr only)

BASIC_MEMORY_NO_PROMOS

false

Disable cloud promos and telemetry

BASIC_MEMORY_IMPORT_UPLOAD_MAX_BYTES

104857600

Max uploaded import size

BASIC_MEMORY_LOG_LEVEL=DEBUG basic-memory reindex
tail -f ~/.basic-memory/basic-memory.log

Development

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 migration

Tests use pytest markers: windows, benchmark, smoke. See justfile for the full list.

Contributions welcome — see CONTRIBUTING.md.

License

AGPL-3.0.

Built with ♥️ by Basic Machines

Available Tools

12 tools
bm_contextBuild contextA
Read-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.

NameRequiredDescriptionDefault
pageNoPage number.
depthNoRelation hops to follow (1-5).
sinceNoHow 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
compactNoOmit note bodies and observations; keep the graph shape.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
page_sizeNoPrimary results per page (1-50).
identifierYesWhere to start: a note path, permalink, memory:// URL, or a pattern such as 'specs/*'.
max_relatedNoMost related results to return (0-100).
output_formatNojson

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety bar is met structurally. The description adds real behavioral context beyond them: hop limits of 1-5, that `since` scopes only related results, and that `compact` strips bodies while keeping graph shape.

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

Conciseness5/5

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

Three dense sentences, front-loaded with the core traversal behavior and ending with the handoff to bm_read. No filler and no restatement of the title.

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

Completeness4/5

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

With an output schema present, return values need no explanation, and the description covers the traversal model and the key tuning knobs. It omits mention of the required `project` scoping and pagination (`page`/`page_size`/`max_related`), though the schema carries those adequately.

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

Parameters3/5

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

Schema coverage is 89%, so the schema already documents nearly every parameter, and the description largely restates it (`identifier` forms, `depth` 1-5, `compact` omitting bodies). The one genuine addition is clarifying that `since` limits related results specifically rather than the root note, which is why this sits at baseline rather than below it.

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

Purpose5/5

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

States a specific verb and resource: follow the knowledge graph from a note, returning the note, its observations, and relation-reached notes up to `depth` hops. It also names the boundary against the sibling bm_read, so an agent can distinguish traversal from direct reading 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.

Usage Guidelines4/5

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

The closing clause routes the agent clearly: use `compact` for graph shape, then bm_read for chosen note bodies. That is a genuine when-to-use/alternative statement. It does not, however, say when to prefer this over bm_search or bm_find for discovery.

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

bm_deleteDelete noteA
DestructiveIdempotent

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.

NameRequiredDescriptionDefault
pathNoThe directory to delete, with everything in it.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
recursiveNoRequired true to delete a directory and everything under it.
identifierNoThe note to delete: a path, permalink, memory:// URL or exact title.
output_formatNotext
expected_checksumNoDelete the note only while it is still this revision (from bm_read).

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

Adds meaningful behavior beyond the annotations: irreversibility is stated plainly, directory deletion is gated on `recursive=true`, and a missing note raises an error rather than silently succeeding. The checksum-gated delete is real context an agent cannot get from destructiveHint alone; only cross-parameter conflict behavior is missing.

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

Conciseness5/5

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

Four short sentences, front-loaded with the two deletion modes, followed by preconditions and the irreversibility warning as a closing emphasizer. Nothing is repeated from the schema verbatim and no sentence is filler.

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

Completeness4/5

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

Output schema exists, so return values need not be explained, and the annotations already declare destructive/idempotent semantics. For a destructive mutation the description covers modes, gating flags, existence errors, and irreversibility; only permission/auth expectations and the identifier-vs-path precedence are unstated.

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

Parameters3/5

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

Schema coverage is high (83%) and each parameter already carries its own description, so the schema carries the load. The description reinforces the `recursive` requirement and the provenance of `expected_checksum` (from bm_read) but adds little new syntax or format guidance beyond the schema, making 3 the correct baseline.

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

Purpose4/5

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

States a specific verb (Delete) against two clearly named resource modes — a note via `identifier` or a directory via `path` — which is the main ambiguity an agent would face. It does not contrast itself with sibling mutators like bm_edit or bm_move, so it stops short of full sibling differentiation.

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

Usage Guidelines4/5

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

Gives explicit conditional usage: use `recursive=true` to delete a directory, pass `expected_checksum` from bm_read for revision-guarded deletes. It does not say when to prefer a different tool (e.g., moving or editing instead of deleting) or explicitly state what happens if both `identifier` and `path` are supplied.

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

bm_editEdit noteA
Destructive

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.

NameRequiredDescriptionDefault
commandYesThe edit.
contentNoThe text to add or the replacement. Not used by set_metadata.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
sectionNoThe heading for section commands: "Decisions", "Auth/Decisions" for one under "Auth", or "Decisions[1]" for the second of two.
metadataNoFrontmatter fields to set; other fields are kept.
find_textNoFor find_replace: the exact, case-sensitive text to replace.
identifierYesThe note or file: a file path ('notes/plan.md'), permalink, memory:// URL, exact title, external id, or '<project>/path'.
output_formatNotext
expected_checksumNoEdit only while the note is still this revision (from bm_read).
replace_subsectionsNoFor replace_section: true replaces the section's subsections too; false stops at the first subsection heading.
expected_replacementsNoFor find_replace: how many times find_text must occur.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

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

Goes beyond the destructiveHint=true / idempotentHint=false annotations by disclosing that set_metadata and metadata merge rather than overwrite ('without touching the body'), that find_replace fails unless find_text occurs expected_replacements times, and that expected_checksum enables revision-guarded edits. It does not spell out irreversibility or that replaced section content is destroyed, which is the remaining gap given the destructive flag.

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

Conciseness5/5

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

Front-loads the core action, then groups per-command semantics and the safety/error clauses in a single dense paragraph. Nearly every clause carries distinct information; there is no filler.

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

Completeness4/5

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

For an 11-parameter mutation tool with an output schema (so return values need no explanation) and annotations covering the safety profile, the description covers command selection, concurrency, and the missing-note error. Minor omissions remain, such as content being unused by set_metadata as an explicit precondition or what a section command does when the heading is absent.

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

Parameters4/5

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

Schema coverage is 91%, so the baseline is 3; the description still adds value by tying each parameter to its command and by stating a rule the schema does not — that 'metadata also merges with any other command.' The section-heading syntax and expected_replacements default largely restate the schema text.

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

Purpose5/5

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

Opens with a specific verb+resource+scope: 'Change part of an existing Basic Memory note.' It explicitly carves out the sibling boundary by stating 'A missing note is an error; create notes with bm_write,' so an agent can separate edit from create 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.

Usage Guidelines5/5

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

Enumerates every command with the condition that selects it (append/prepend content, find_replace with expected_replacements, section commands for a heading, set_metadata for frontmatter only) plus the alternative tool for the create case. It also states the failure mode when the note does not exist, which is the main when-not.

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

bm_findFind filesA
Read-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.

NameRequiredDescriptionDefault
nameNoFile-name glob, e.g. '*.md'. Not with `filters`.
pageNoPage number.
pathNoA directory in the project, e.g. 'specs' or 'specs/active'. '/' is the project root; '<project>/path' addresses another project./
depthNoFolder levels to search (1-10).
fieldsNoFrontmatter fields to return per note (dot paths allowed), e.g. ["title", "priority"]. Needs `filters`.
filtersNoFrontmatter 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.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
page_sizeNoResults per page (1-100).
output_formatNotext

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare this as read-only, idempotent, non-destructive, and not open-world. The description adds meaningful behavior beyond annotations: recursive traversal, frontmatter-based filtering, and projecting only requested frontmatter fields per note. It does not discuss permissions, but for a read-only search tool the added behavioral detail is solid.

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

Conciseness5/5

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

The description is four sentences, front-loaded with the core purpose, then organized by query mode, and ends with the key alternative. There is no filler and every sentence contributes to selecting or invoking the tool correctly.

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

Completeness4/5

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

For a 9-parameter tool with a detailed schema, high schema coverage, annotations, and an output schema, the description covers the main behavior and the key alternative. Minor gaps around pagination, depth, and `output_format` are handled by the schema, so the definition is complete enough for correct selection and invocation.

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

Parameters3/5

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

Schema description coverage is 89% and the schema itself contains detailed parameter documentation and examples. The description reinforces `name`, `filters`, `fields`, and `path` with examples, but adds little beyond the structured schema and does not explain pagination, depth, project resolution, or `output_format`.

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

Purpose5/5

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

The description states a specific verb and resource: 'Find files in a Basic Memory project, recursively.' It clearly enumerates the main query modes (`name`, `filters`, `fields`, `path`) and explicitly distinguishes this tool from `bm_search` for ranked text or meaning search.

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

Usage Guidelines4/5

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

Useful usage context is given for `name`, `filters`, `fields`, and `path`, and the description explicitly routes ranked text/meaning search to `bm_search`. However, it does not mention that `name` cannot be combined with `filters` (that constraint is only in the schema) and does not distinguish usage from siblings such as `bm_list`.

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

bm_listList folderA
Read-onlyIdempotent

List one folder of a Basic Memory project: its subfolders, then its files with title, date and id. project is required; '/' lists its root. Discover projects with bm_project(command='list'). Filter files with glob and order them with sort. For a recursive search by name or frontmatter, use bm_find.

NameRequiredDescriptionDefault
globNoFile-name glob, e.g. '*.md' or '*meeting*'.
pageNoPage number.
pathNoA directory in the project, e.g. 'specs' or 'specs/active'. '/' is the project root; '<project>/path' addresses another project./
sortNoFile order. Folders always come first.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
page_sizeNoResults per page (1-100).
output_formatNotext

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, closed-world and non-destructive, so safety is covered. The description adds genuine context beyond them: what the listing contains, that folders always precede files, and that sorting applies only to files. It does not mention paging or that large folders are truncated at page_size, which is the one behavioral trait an agent could trip over.

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

Conciseness5/5

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

Four short sentences, front-loaded with the core action and output shape, then constraints, then the sibling alternative. Every clause carries information; there is no restatement of the tool name or filler.

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

Completeness5/5

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

With an output schema present, return values need not be explained in depth, and the description still previews them. Project discovery, root addressing, filtering, ordering and the sibling alternative are all covered, which is everything needed to invoke a read-only folder lister correctly.

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

Parameters3/5

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

Schema description coverage is 86%, so the schema already carries parameter meaning; the description reinforces that 'glob' filters files (not folders) and that 'sort' orders files only. It adds modest clarification but no format, syntax, or interaction detail (e.g. how glob and path interact) beyond the schema — baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource ('List one folder of a Basic Memory project') and even describes the output shape — subfolders first, then files with title, date and id. It explicitly separates itself from bm_find's recursive search, so an agent can pick between them without opening a schema.

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

Usage Guidelines5/5

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

Gives the prerequisite ('project' is required), the root convention ('/' lists its root), a bootstrapping step (bm_project(command='list')), and an explicit alternative for a different use case ('For a recursive search by name or frontmatter, use bm_find'). Nothing about when to choose this tool is left to inference.

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

bm_manManualA
Read-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.

NameRequiredDescriptionDefault
pageNoThe page to read, e.g. 'bm-search(3)', 'grep(1)' or 'bm_search'.
queryNoWords to find in the manual; lists the pages that mention them all.
output_formatNotext

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

The annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=false. The description adds useful behavioral detail beyond that: what the no-argument form returns, what `page` accepts, and that `query` lists pages mentioning every supplied word, much like `man -k`.

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

Conciseness5/5

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

The description is front-loaded with the core purpose and then efficiently explains each mode in one sentence. There is no redundancy or filler.

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

Completeness4/5

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

With read-only annotations and an output schema present, the description does not need to explain return values or safety. It covers the main calling modes well, though it could briefly mention `output_format` behavior to be fully complete for all three parameters.

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

Parameters4/5

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

The description adds real meaning for `page` by giving accepted forms like 'bm-search(3)', 'grep(1)', and bare tool names, and for `query` by clarifying the all-words matching behavior. It does not describe `output_format`, and schema description coverage is 67%, but the main parameters are well explained.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Read the Basic Memory manual.' It then clearly distinguishes the three modes (index, page, query), so an agent can immediately tell what the tool does without opening the schema.

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

Usage Guidelines4/5

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

It explains how to use each mode: no arguments for the index, `page` for one page, and `query` for keyword listing. It does not explicitly compare this tool to sibling tools like bm_search or bm_find, but the manual-reading context is clear and there are no misleading exclusions.

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.

NameRequiredDescriptionDefault
pathNoThe directory to move, with everything in it, e.g. 'drafts/2025'.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
identifierNoThe note to move: a path, permalink, memory:// URL or exact title.
destinationYesNew path, e.g. 'archive/plan.md'. A trailing '/' ('archive/') moves the note or directory into that folder under its current name.
output_formatNotext
expected_checksumNoMove the note only while it is still this revision (from bm_read).

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

Goes well beyond the annotations (which only mark it as non-read-only, non-idempotent, non-destructive): it discloses the cross-project refusal, extension normalization ('.markdown' may become '.md'), preservation of the current name when destination ends in '/', and optimistic-concurrency behavior via expected_checksum. It does not say what happens if the destination path already exists, which is the one meaningful behavioral gap for a move operation.

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

Conciseness4/5

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

Four dense sentences with the core action and destination semantics front-loaded; the cross-project refusal and checksum note follow logically. Slightly packed with parenthetical detail, but no sentence is filler.

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

Completeness4/5

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

An output schema exists so return values need no explanation, and annotations cover the safety profile; the description fills in the refusal rule and checksum semantics. The missing piece is overwrite/collision behavior when the destination already exists, which matters for a move tool.

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

Parameters4/5

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

Schema coverage is already 83%, so the baseline is 3; the description still adds meaning by framing `destination` as a project-relative path, explaining the trailing-'/' convention in operational terms, and tying `expected_checksum` to a prior bm_read. The extension-change note for notes is additional context not in the schema.

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

Purpose5/5

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

States a specific verb+resource pair ('Move or rename a Basic Memory note or directory') and immediately disambiguates the two modes via the `identifier` vs `path` parameters. The within-project scope constraint further narrows what the tool does, letting an agent separate it from bm_edit (content change) and bm_delete.

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

Usage Guidelines5/5

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

Gives an explicit when-not with the replacement workflow: cross-project moves are refused, so use bm_read, bm_write there, then bm_delete. It also specifies the conditional-move case via `expected_checksum` and the trailing-slash convention for moving into a folder without renaming.

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

bm_projectProjectsB

Basic Memory projects. command: list (projects, grouped by workspace); create (name, path, optional set_default, workspace); recent (what changed lately in the required project: since, items, paging).

NameRequiredDescriptionDefault
nameNoFor create: the new project's name.
pageNoPage number.
pathNoFor create: the folder that holds the project's notes.
itemsNoWhat to return: notes, observations, relations, or a mix. Default: notes.
sinceNoHow 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
commandYesWhat to do.
projectNoProject name, 'workspace/project', or external id. Required for one-project operations; search may instead use `projects` or `all_projects=true`. Project discovery needs no scope.
page_sizeNoResults per page (1-100).
workspaceNoIn Cloud: the workspace slug, name or id that holds the project.
set_defaultNoFor create: make the new project the default.
output_formatNotext

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare non-readOnly, non-destructive, non-idempotent, closed-world, so the safety profile is set. The description adds that `list` groups by workspace and that `recent` requires a project scope, but says nothing about what `create` actually does on disk (folder creation, failure modes, whether it overwrites), which is the one mutating path and the main behavioral risk.

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

Conciseness4/5

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

A single dense sentence that front-loads the resource and then walks the commands in order with their parameters. No filler, though the heavy parenthetical nesting makes it slightly harder to scan than a short bulleted form would be.

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

Completeness3/5

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

With 11 parameters, an output schema, and annotations present, the description covers the command-to-parameter mapping adequately. It leaves gaps on what `create` produces, how errors surface, and why an agent would choose this over bm_list/bm_search for project awareness, which matter given three divergent modes behind one tool.

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

Parameters3/5

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

Schema coverage is 91%, so individual parameters are already well documented, and the description largely restates the schema's per-command mapping (name/path/set_default/workspace for create, since/items/paging for recent). It does clarify which parameters group together per command, a mild add over the schema. Baseline 3 is appropriate.

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

Purpose4/5

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

The description names the resource (Basic Memory projects) and enumerates the three distinct operations (list, create, recent) with the parameters each consumes, so an agent can map intent to command. It does not explicitly contrast with siblings such as bm_list or bm_search, which handle notes rather than project administration, so it falls short of 5.

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

Usage Guidelines3/5

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

"recent (what changed lately in the required `project`)" implies when to pick that command, and the create/list breakdown hints at contexts, but there is no explicit statement of when to use this tool instead of bm_list, bm_read, or bm_search, nor any exclusions. Usage must be inferred from the command names.

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

bm_readRead noteA
Read-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. A text file such as .txt takes start_line/end_line too. 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.

NameRequiredDescriptionDefault
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
sectionNoA heading to read: "Decisions", "Auth/Decisions" for a heading under "Auth", or "Decisions[1]" for the second "Decisions" heading.
end_lineNo
identifierYesThe note or file: a file path ('notes/plan.md'), permalink, memory:// URL, exact title, external id, or '<project>/path'.
max_tokensNoApproximate token budget. Longer content is cut at a section or paragraph boundary, and the result says which line to continue from.
start_lineNo
output_formatNotext
include_contentNoFalse returns only title, paths, checksum and updated_at.
include_frontmatterNoInclude the YAML frontmatter in a whole-note read.

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, it discloses non-obvious behavior: missing notes raise an error rather than returning empty, images come back as images and other binaries as documents, truncation via max_tokens reports a continuation line, and the checksum is the expected_checksum value consumed by bm_write/bm_edit. That cross-tool linkage is exactly the kind of context annotations cannot carry.

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

Conciseness4/5

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

Front-loaded with the core action, then slicing options, then the metadata/checksum mode, then edge cases — a sensible order with no filler. It is dense and long for a read tool, but every clause carries distinct information.

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

Completeness5/5

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

With 9 parameters and no output schema, the description carries the return-value burden well: it says what comes back for notes, text files, images and binaries, what the truncated response includes, and what metadata-only mode yields. Nothing essential for a correct call is missing.

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

Parameters4/5

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

At 67% schema coverage it adds real meaning: line numbers count the whole file including frontmatter, section accepts a heading path or an indexed repeat ('Decisions[1]'), max_tokens cuts at section/paragraph boundaries, and include_content=false returns title, paths, checksum and updated_at. It leaves output_format, start_line and end_line's own semantics (e.g., default end) unstated.

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

Purpose5/5

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

States a specific verb+resource ('Read a Basic Memory note or file') and enumerates the accepted identifier forms (path, permalink, memory:// URL, exact title), which lets an agent map its input to this tool immediately. It also distinguishes itself from the discovery sibling by naming bm_search.

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

Usage Guidelines4/5

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

Gives clear routing: 'A missing note is an error: find notes with bm_search,' and explains the metadata-only mode via include_content=false for checksum lookups. It stops short of naming other plausible alternatives (bm_find, bm_list, bm_context) or stating when not to read a whole file.

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

bm_schemaNote schemasA
Read-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.

NameRequiredDescriptionDefault
commandYesWhat to do.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
note_typeNoThe frontmatter `type:` to check. Required for infer and diff.
thresholdNoFor infer: the share of notes a field must appear in to be suggested.
identifierNoFor validate: one note, instead of a whole note type.
output_formatNotext

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description adds genuine domain context beyond that: the definition of a schema note and the entity field linkage. It doesn't describe failure output or how partial validation results are reported, but an output schema exists to carry that.

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

Conciseness4/5

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

The core capability and the three commands are front-loaded in the first sentence, with the schema definition last. It is dense but every clause carries information; the telegraphic 'infer a schema from the notes of a note_type' phrasing costs a little readability.

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

Completeness4/5

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

For a three-mode tool with a full output schema and rich annotations, the description covers what the commands do and the conceptual model needed to use them. Remaining gaps (threshold behavior, output_format choice) are handled by the schema, so nothing essential is missing.

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

Parameters4/5

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

Schema coverage is 83%, so the baseline is 3, and the description earns a bump by clarifying the mutually exclusive targeting modes (one note_type, one note via identifier, or every type with a schema) that the schema only hints at with per-field 'For validate' notes. The threshold and output_format parameters are not mentioned in the description, but both are documented in the schema.

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

Purpose4/5

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

The description names the resource (Basic Memory note schemas / Picoschema) and gives a specific verb for each of the three commands: validate, infer, and diff. It also defines what a schema is (a note with type: schema whose entity field names the described type). It does not explicitly distinguish itself from siblings such as bm_man or bm_read, relying on the uniqueness of schema operations instead.

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

Usage Guidelines4/5

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

Each command is given a situation: validate for one note_type, one note by identifier, or all types with schemas; infer to derive a schema from existing notes; diff to find drift. That is clear per-command guidance. There are no explicit exclusions or pointers to alternative tools for overlapping needs.

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

bm_writeWrite noteA
Destructive

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]]').

NameRequiredDescriptionDefault
tagsNoTags, as a list or 'a,b,c'.
titleNoNote title. With `directory`, it also names the file. With `identifier`, it is used when the content has no frontmatter title.
contentYesThe note's Markdown. Saved as given; it may start with frontmatter.
projectYesRequired project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it.
metadataNoExtra frontmatter fields, merged into the note's frontmatter.
directoryNoFolder for a note addressed by title, e.g. 'meetings'; '/' is the root.
note_typeNoFrontmatter `type:`. A `type:` in the content wins.note
overwriteNoReplace a note that already exists. Default: the write_note_overwrite_default setting (false unless changed).
identifierNoFile 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_formatNotext
expected_checksumNoReplace the note only while it is still this revision (the checksum from bm_read). Implies overwrite=true.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=false, but the description adds the crucial nuance that writes are non-destructive by default and only overwrite when asked, plus optimistic-concurrency semantics via `expected_checksum`. It also discloses title-resolution precedence (frontmatter, then `title`, then file name). Missing only auth/permission context and whether the project must pre-exist, which keeps it off 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.

Conciseness4/5

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

Four dense sentences ordered from what the tool does, to how to address the note, to conflict handling, to content shape. Zero filler, though the content-syntax sentence packs three concepts (frontmatter, observations, relations) into one trailing clause.

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

Completeness4/5

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

An output schema exists, so return values need not be described, and the remaining parameters (tags, metadata, note_type, output_format) are documented in the schema at 91% coverage. What an agent needs for correct invocation — addressing, overwrite, checksum, content format — is all present; only cross-project path qualification is hinted at rather than explained.

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

Parameters4/5

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

Schema coverage is 91%, so the baseline is 3, but the description adds real precedence rules the schema does not: the title is taken from frontmatter first, then `title`, then the file name, and that a path pins the file exactly. That resolves the ambiguity between the `identifier` and `title`/`directory` parameters.

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

Purpose5/5

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

States a specific verb and resource ('Create or replace a Basic Memory note') and immediately names the sibling it is not ('To change part of a note use bm_edit'). An agent can separate bm_write from bm_edit and bm_delete without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit addressing alternatives (file path as `identifier` vs `title` + `directory`), states that an existing note errors unless `overwrite=true`, and points to bm_read as the source of `expected_checksum` for revision-safe replacement. The redirect to bm_edit is an explicit when-not rule.

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

Tool Schema Changelog

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

  1. 38 tool updates
    • Removedbasic_memory_diagnostics
    • Changedbm_context7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "identifier"
        -]New value: +[
        +  "identifier",
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_delete7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • addedInput schema / required
        Added value: +[
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_edit7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "identifier",
        -  "command"
        -]New value: +[
        +  "identifier",
        +  "command",
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_find7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • addedInput schema / required
        Added value: +[
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_list7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • addedInput schema / required
        Added value: +[
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_man1 field changed
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_move7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "destination"
        -]New value: +[
        +  "destination",
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_project2 fields changed
      • changedInput schema / properties / project / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Project name, 'workspace/project', or external id. Required for one-project operations; search may instead use `projects` or `all_projects=true`. Project discovery needs no scope."
    • Changedbm_read6 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "identifier"
        -]New value: +[
        +  "identifier",
        +  "project"
        +]
    • Changedbm_schema6 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "command"
        -]New value: +[
        +  "command",
        +  "project"
        +]
    • Changedbm_search3 fields changed
      • changedInput schema / properties / project / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Project name, 'workspace/project', or external id. Required for one-project operations; search may instead use `projects` or `all_projects=true`. Project discovery needs no scope."
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Changedbm_write7 fields changed
      • removedInput schema / properties / project / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / project / default
        Removed value: -null
      • changedInput schema / properties / project / description
        Previous value: -"Project name, 'workspace/project', or project external id. Omit to use the default project."New value: +"Required project name, 'workspace/project', or project external id. Discover projects with bm_project(command='list'). Paths are relative to this project; a qualified path must agree with it."
      • addedInput schema / properties / project / minLength
        Added value: +1
      • addedInput schema / properties / project / type
        Added value: +"string"
      • changedInput schema / required
        Previous value: -[
        -  "content"
        -]New value: +[
        +  "content",
        +  "project"
        +]
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "type": "object"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
    • Removedbuild_context
    • Removedcat
    • Removedcreate_memory_project
    • Removeddelete_note
    • Removededit_note
    • Removedfetch
    • Removedfind
    • Removedgrep
    • Removedlist_directory
    • Removedlist_memory_projects
    • Removedlist_workspaces
    • Removedls
    • Removedman
    • Removedmove_note
    • Removedread_content
    • Removedread_note
    • Removedrecent_activity
    • Removedschema_diff
    • Removedschema_infer
    • Removedschema_validate
    • Removedsearch
    • Removedsearch_notes
    • Removedtail
    • Removedview_note
    • Removedwrite_note
  2. 40 tool updatesv0.24.1
    • Addedbasic_memory_diagnostics
    • Addedbm_context
    • Addedbm_delete
    • Addedbm_edit
    • Addedbm_find
    • Addedbm_list
    • Addedbm_man
    • Addedbm_move
    • Addedbm_project
    • Addedbm_read
    • Addedbm_schema
    • Addedbm_search
    • Addedbm_write
    • Changedbuild_context28 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / compact
        Added 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"
        +}
      • addedInput schema / properties / depth / description
        Added value: +"How many relation hops to traverse (1-3 recommended, maximum: 5)"
      • removedInput schema / properties / depth / title
        Removed value: -"Depth"
      • addedInput schema / properties / max_related / description
        Added value: +"Maximum total related results to return (default: 10, maximum: 100)"
      • removedInput schema / properties / max_related / title
        Removed value: -"Max Related"
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "json",
        +  "description": "Response format - \"json\" for structured JSON dict,\n\"text\" for compact markdown text",
        +  "enum": [
        +    "json",
        +    "text"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / page / description
        Added value: +"Page number of results to return (default: 1)"
      • removedInput schema / properties / page / title
        Removed value: -"Page"
      • addedInput schema / properties / page_size / description
        Added value: +"Number of primary results to return per page (default: 10, maximum: 50)"
      • removedInput schema / properties / page_size / title
        Removed value: -"Page Size"
      • addedInput schema / properties / project / description
        Added value: +"Project name to build context from. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / timeframe / description
        Added value: +"How far back to look. Supports natural language like \"2 days ago\", \"last week\""
      • removedInput schema / properties / timeframe / title
        Removed value: -"Timeframe"
      • addedInput schema / properties / url / description
        Added value: +"memory:// URI pointing to discussion content (e.g. memory://specs/search),\nor a bare permalink path."
      • removedInput schema / properties / url / title
        Removed value: -"Url"
      • removedOutput schema / $defs
        Removed 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"
        -  }
        -}
      • removedOutput schema / description
        Removed value: -"Complete context response."
      • removedOutput schema / properties / metadata
        Removed value: -{
        -  "$ref": "#/$defs/MemoryMetadata"
        -}
      • removedOutput schema / properties / page
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "integer"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Page"
        -}
      • removedOutput schema / properties / page_size
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "integer"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Page Size"
        -}
      • addedOutput schema / properties / result
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "string"
        +    }
        +  ]
        +}
      • removedOutput schema / properties / results
        Removed value: -{
        -  "description": "Hierarchical results with related items nested",
        -  "items": {
        -    "$ref": "#/$defs/ContextResult"
        -  },
        -  "title": "Results",
        -  "type": "array"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "metadata"
        -]New value: +[
        +  "result"
        +]
      • removedOutput schema / title
        Removed value: -"GraphContext"
      • addedOutput schema / x-fastmcp-wrap-result
        Added value: +true
    • Removedcanvas
    • Addedcat
    • Changedcreate_memory_project13 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "text",
        +  "description": "\"text\" returns human-readable result text.\n\"json\" returns structured project creation metadata.",
        +  "enum": [
        +    "text",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / project_name / description
        Added value: +"Name for the new project (must be unique)"
      • removedInput schema / properties / project_name / title
        Removed value: -"Project Name"
      • addedInput schema / properties / project_path / description
        Added value: +"File system path where the project will be stored"
      • removedInput schema / properties / project_path / title
        Removed value: -"Project Path"
      • addedInput schema / properties / set_default / description
        Added value: +"Whether to set this project as the default (optional, defaults to False)"
      • removedInput schema / properties / set_default / title
        Removed value: -"Set Default"
      • addedInput schema / properties / workspace
        Added 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."
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changeddelete_note11 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / identifier / description
        Added 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\""
      • removedInput schema / properties / identifier / title
        Removed value: -"Identifier"
      • addedInput schema / properties / is_directory
        Added 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"
        +}
      • addedInput schema / properties / output_format
        Added 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"
        +}
      • addedInput schema / properties / project / description
        Added value: +"Project name to delete from. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Removeddelete_project
    • Changededit_note29 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / content / description
        Added value: +"The content to add or use for replacement"
      • removedInput schema / properties / content / title
        Removed value: -"Content"
      • addedInput schema / properties / expected_checksum
        Added 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)."
        +}
      • addedInput schema / properties / expected_replacements / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / expected_replacements / default
        Previous value: -1New value: +null
      • addedInput schema / properties / expected_replacements / description
        Added value: +"For find_replace: required occurrence count of find_text\n(default 1). A mismatch fails without writing."
      • removedInput schema / properties / expected_replacements / title
        Removed value: -"Expected Replacements"
      • removedInput schema / properties / expected_replacements / type
        Removed value: -"integer"
      • addedInput schema / properties / find_text / description
        Added value: +"For find_replace operation - the exact, case-sensitive text to replace"
      • removedInput schema / properties / find_text / title
        Removed value: -"Find Text"
      • addedInput schema / properties / identifier / description
        Added 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."
      • removedInput schema / properties / identifier / title
        Removed value: -"Identifier"
      • addedInput schema / properties / metadata
        Added 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."
        +}
      • addedInput schema / properties / operation / description
        Added 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)"
      • addedInput schema / properties / operation / enum
        Added value: +[
        +  "append",
        +  "prepend",
        +  "find_replace",
        +  "replace_section",
        +  "insert_before_section",
        +  "insert_after_section"
        +]
      • removedInput schema / properties / operation / title
        Removed value: -"Operation"
      • addedInput schema / properties / output_format
        Added 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"
        +}
      • addedInput schema / properties / project / description
        Added 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."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / replace_subsections
        Added 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."
        +}
      • addedInput schema / properties / section / description
        Added value: +"Heading for replace_section, insert_before_section, and\ninsert_after_section (e.g. \"## Notes\", \"### Implementation\"). Must match exactly."
      • removedInput schema / properties / section / title
        Removed value: -"Section"
      • addedInput schema / properties / workspace
        Added 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`."
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedfetch5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / id / description
        Added value: +"Document identifier (permalink, title, or memory URL)"
      • removedInput schema / properties / id / title
        Removed value: -"Id"
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Addedfind
    • Addedgrep
    • Changedlist_directory18 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / depth / description
        Added value: +"Recursion depth (1-10, default: 1 for immediate children only)\n   Higher values show subdirectory contents recursively"
      • removedInput schema / properties / depth / title
        Removed value: -"Depth"
      • addedInput schema / properties / dir_name / description
        Added value: +"Directory path to list (default: root \"/\")\n     Examples: \"/\", \"/projects\", \"/research/ml\""
      • removedInput schema / properties / dir_name / title
        Removed value: -"Dir Name"
      • addedInput schema / properties / file_name_glob / description
        Added value: +"Optional glob pattern for filtering file names\n           Examples: \"*.md\", \"*meeting*\", \"project_*\""
      • removedInput schema / properties / file_name_glob / title
        Removed value: -"File Name Glob"
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "text",
        +  "description": "\"text\" for a readable listing or \"json\" for structured pagination data",
        +  "enum": [
        +    "text",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "One-indexed result page (default: 1)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / page_size
        Added value: +{
        +  "default": 10,
        +  "description": "Number of nodes per page (default: 10, maximum: 200)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / project / description
        Added value: +"Project name to list directory from. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / sort
        Added 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."
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedlist_memory_projects6 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "text",
        +  "description": "\"text\" returns a human-readable project list.\n\"json\" returns structured project metadata.",
        +  "enum": [
        +    "text",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Addedlist_workspaces
    • Addedls
    • Addedman
    • Changedmove_note17 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / destination_folder
        Added 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."
        +}
      • addedInput schema / properties / destination_path / default
        Added value: +""
      • addedInput schema / properties / destination_path / description
        Added 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."
      • removedInput schema / properties / destination_path / title
        Removed value: -"Destination Path"
      • addedInput schema / properties / identifier / description
        Added 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."
      • removedInput schema / properties / identifier / title
        Removed value: -"Identifier"
      • addedInput schema / properties / is_directory
        Added 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"
        +}
      • addedInput schema / properties / output_format
        Added 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"
        +}
      • addedInput schema / properties / project / description
        Added value: +"Project name to move within. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • changedInput schema / required
        Previous value: -[
        -  "identifier",
        -  "destination_path"
        -]New value: +[
        +  "identifier"
        +]
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedread_content6 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / path / description
        Added 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)"
      • removedInput schema / properties / path / title
        Removed value: -"Path"
      • addedInput schema / properties / project / description
        Added value: +"Project name to read from. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
    • Changedread_note19 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_line
        Added 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."
        +}
      • addedInput schema / properties / identifier / description
        Added 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."
      • removedInput schema / properties / identifier / title
        Removed value: -"Identifier"
      • addedInput schema / properties / include_content
        Added 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"
        +}
      • addedInput schema / properties / include_frontmatter
        Added 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"
        +}
      • addedInput schema / properties / output_format
        Added 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"
        +}
      • addedInput schema / properties / page / description
        Added 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."
      • removedInput schema / properties / page / title
        Removed value: -"Page"
      • addedInput schema / properties / page_size / description
        Added 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."
      • removedInput schema / properties / page_size / title
        Removed value: -"Page Size"
      • addedInput schema / properties / project / description
        Added 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."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / start_line
        Added 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."
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedrecent_activity17 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / depth / description
        Added value: +"How many relation hops to traverse (1-3 recommended, maximum: 5)"
      • removedInput schema / properties / depth / title
        Removed value: -"Depth"
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "text",
        +  "description": "\"text\" returns human-readable summary text. \"json\" returns\na flat list of recent items.",
        +  "enum": [
        +    "text",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "Page number for pagination (default 1)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / page_size
        Added value: +{
        +  "default": 10,
        +  "description": "Number of items per page (default 10, maximum: 100)",
        +  "type": "integer"
        +}
      • addedInput schema / properties / project / description
        Added 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."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / timeframe / description
        Added 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."
      • removedInput schema / properties / timeframe / title
        Removed value: -"Timeframe"
      • addedInput schema / properties / type / description
        Added 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."
      • removedInput schema / properties / type / title
        Removed value: -"Type"
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    "type": "array"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Addedschema_diff
    • Addedschema_infer
    • Addedschema_validate
    • Changedsearch5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / query / description
        Added value: +"Search query (full-text syntax supported by `search_notes`)"
      • removedInput schema / properties / query / title
        Removed value: -"Query"
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedsearch_notes41 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / after_date / description
        Added value: +"Optional date filter for recent content (e.g., \"1 week\", \"2d\", \"2024-01-01\")"
      • removedInput schema / properties / after_date / title
        Removed value: -"After Date"
      • addedInput schema / properties / categories
        Added 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."
        +}
      • addedInput schema / properties / compact
        Added 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"
        +}
      • addedInput schema / properties / entity_types / description
        Added 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."
      • removedInput schema / properties / entity_types / title
        Removed value: -"Entity Types"
      • addedInput schema / properties / metadata_filters
        Added 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."
        +}
      • addedInput schema / properties / min_similarity
        Added 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."
        +}
      • addedInput schema / properties / note_types
        Added 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."
        +}
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "text",
        +  "description": "\"text\" returns a formatted markdown result list. \"json\" returns a\nmachine-readable dictionary payload.",
        +  "enum": [
        +    "text",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / page / description
        Added value: +"The page number of results to return (default 1).\nAliases: page_number."
      • removedInput schema / properties / page / title
        Removed value: -"Page"
      • addedInput schema / properties / page_size / description
        Added value: +"The number of results to return per page (default 10).\nAliases: limit, per_page."
      • removedInput schema / properties / page_size / title
        Removed value: -"Page Size"
      • addedInput schema / properties / project / description
        Added value: +"Project name to search in. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / projects
        Added 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."
        +}
      • addedInput schema / properties / query / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / query / default
        Added value: +null
      • addedInput schema / properties / query / description
        Added 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."
      • removedInput schema / properties / query / title
        Removed value: -"Query"
      • removedInput schema / properties / query / type
        Removed value: -"string"
      • addedInput schema / properties / search_all_projects
        Added value: +{
        +  "default": false,
        +  "description": "Optional opt-in to search every accessible project. Ignored when\n    `project` or `project_id` is supplied.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / search_type / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / search_type / default
        Previous value: -"text"New value: +null
      • addedInput schema / properties / search_type / description
        Added 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\"."
      • removedInput schema / properties / search_type / title
        Removed value: -"Search Type"
      • removedInput schema / properties / search_type / type
        Removed value: -"string"
      • addedInput schema / properties / status
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional status filter (frontmatter status); shorthand for metadata_filters[\"status\"]"
        +}
      • addedInput schema / properties / tags
        Added 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."
        +}
      • addedInput schema / properties / time_kind
        Added 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."
        +}
      • removedInput schema / properties / types
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Types"
        -}
      • addedInput schema / properties / valid_at
        Added 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."
        +}
      • addedInput schema / properties / valid_overlaps
        Added 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."
        +}
      • removedInput schema / required
        Removed value: -[
        -  "query"
        -]
      • removedOutput schema / $defs
        Removed 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"
        -  }
        -}
      • changedOutput schema / properties / result / anyOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/SearchResponse"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Addedtail
    • Changedview_note10 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / identifier / description
        Added value: +"The title or permalink of the note to view"
      • removedInput schema / properties / identifier / title
        Removed value: -"Identifier"
      • removedInput schema / properties / page
        Removed value: -{
        -  "default": 1,
        -  "title": "Page",
        -  "type": "integer"
        -}
      • removedInput schema / properties / page_size
        Removed value: -{
        -  "default": 10,
        -  "title": "Page Size",
        -  "type": "integer"
        -}
      • addedInput schema / properties / project / description
        Added value: +"Project name to read from. Optional - server will resolve using hierarchy.\n    If unknown, use list_memory_projects() to discover available projects."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
    • Changedwrite_note24 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / content / description
        Added 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."
      • removedInput schema / properties / content / title
        Removed value: -"Content"
      • addedInput schema / properties / directory
        Added 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"
        +}
      • addedInput schema / properties / expected_checksum
        Added 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."
        +}
      • removedInput schema / properties / folder
        Removed value: -{
        -  "title": "Folder",
        -  "type": "string"
        -}
      • addedInput schema / properties / metadata
        Added 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."
        +}
      • addedInput schema / properties / note_type / description
        Added 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."
      • removedInput schema / properties / note_type / title
        Removed value: -"Note Type"
      • addedInput schema / properties / output_format
        Added 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"
        +}
      • addedInput schema / properties / overwrite
        Added 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."
        +}
      • addedInput schema / properties / project / description
        Added 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."
      • removedInput schema / properties / project / title
        Removed value: -"Project"
      • addedInput schema / properties / project_id
        Added 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()."
        +}
      • addedInput schema / properties / tags / description
        Added 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\")"
      • removedInput schema / properties / tags / title
        Removed value: -"Tags"
      • addedInput schema / properties / title / description
        Added 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."
      • removedInput schema / properties / title / title
        Removed value: -"Title"
      • addedInput schema / properties / workspace
        Added 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`."
        +}
      • changedInput schema / required
        Previous value: -[
        -  "title",
        -  "content",
        -  "folder"
        -]New value: +[
        +  "title",
        +  "content",
        +  "directory"
        +]
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / properties / result / type
        Removed value: -"string"
      • removedOutput schema / title
        Removed value: -"_WrappedResult"
  3. 11 tool updatesv1.0.0
    • Changedbuild_context12 fields changed
      • removedInput schema / $defs
        Removed value: -{
        -  "StringOrInt": {
        -    "anyOf": [
        -      {
        -        "type": "string"
        -      },
        -      {
        -        "type": "integer"
        -      }
        -    ]
        -  }
        -}
      • changedInput schema / properties / depth / anyOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/StringOrInt"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedOutput schema / $defs / EntitySummary / properties / entity_id
        Added value: +{
        +  "title": "Entity Id",
        +  "type": "integer"
        +}
      • changedOutput schema / $defs / EntitySummary / required
        Previous value: -[
        -  "permalink",
        -  "title",
        -  "file_path",
        -  "created_at"
        -]New value: +[
        +  "entity_id",
        +  "permalink",
        +  "title",
        +  "file_path",
        +  "created_at"
        +]
      • addedOutput schema / $defs / ObservationSummary / properties / entity_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Entity Id"
        +}
      • addedOutput schema / $defs / ObservationSummary / properties / observation_id
        Added value: +{
        +  "title": "Observation Id",
        +  "type": "integer"
        +}
      • changedOutput schema / $defs / ObservationSummary / required
        Previous value: -[
        -  "title",
        -  "file_path",
        -  "permalink",
        -  "category",
        -  "content",
        -  "created_at"
        -]New value: +[
        +  "observation_id",
        +  "title",
        +  "file_path",
        +  "permalink",
        +  "category",
        +  "content",
        +  "created_at"
        +]
      • addedOutput schema / $defs / RelationSummary / properties / entity_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Entity Id"
        +}
      • addedOutput schema / $defs / RelationSummary / properties / from_entity_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "From Entity Id"
        +}
      • addedOutput schema / $defs / RelationSummary / properties / relation_id
        Added value: +{
        +  "title": "Relation Id",
        +  "type": "integer"
        +}
      • addedOutput schema / $defs / RelationSummary / properties / to_entity_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "To Entity Id"
        +}
      • changedOutput schema / $defs / RelationSummary / required
        Previous value: -[
        -  "title",
        -  "file_path",
        -  "permalink",
        -  "relation_type",
        -  "created_at"
        -]New value: +[
        +  "relation_id",
        +  "title",
        +  "file_path",
        +  "permalink",
        +  "relation_type",
        +  "created_at"
        +]
    • Addedfetch
    • Removedget_current_project
    • Changedlist_memory_projects1 field changed
      • removedInput schema / properties / _compatibility
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Compatibility"
        -}
    • Changedrecent_activity13 fields changed
      • removedInput schema / properties / max_related
        Removed value: -{
        -  "default": 10,
        -  "title": "Max Related",
        -  "type": "integer"
        -}
      • removedInput schema / properties / page
        Removed value: -{
        -  "default": 1,
        -  "title": "Page",
        -  "type": "integer"
        -}
      • removedInput schema / properties / page_size
        Removed value: -{
        -  "default": 10,
        -  "title": "Page Size",
        -  "type": "integer"
        -}
      • removedOutput schema / $defs
        Removed 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"
        -  }
        -}
      • removedOutput schema / description
        Removed value: -"Complete context response."
      • removedOutput schema / properties / metadata
        Removed value: -{
        -  "$ref": "#/$defs/MemoryMetadata"
        -}
      • removedOutput schema / properties / page
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "integer"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Page"
        -}
      • removedOutput schema / properties / page_size
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "integer"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Page Size"
        -}
      • addedOutput schema / properties / result
        Added value: +{
        +  "title": "Result",
        +  "type": "string"
        +}
      • removedOutput schema / properties / results
        Removed value: -{
        -  "description": "Hierarchical results with related items nested",
        -  "items": {
        -    "$ref": "#/$defs/ContextResult"
        -  },
        -  "title": "Results",
        -  "type": "array"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "metadata"
        -]New value: +[
        +  "result"
        +]
      • changedOutput schema / title
        Previous value: -"GraphContext"New value: +"_WrappedResult"
      • addedOutput schema / x-fastmcp-wrap-result
        Added value: +true
    • Addedsearch
    • Changedsearch_notes3 fields changed
      • addedOutput schema / $defs / SearchResult / properties / entity_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Entity Id"
        +}
      • addedOutput schema / $defs / SearchResult / properties / observation_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Observation Id"
        +}
      • addedOutput schema / $defs / SearchResult / properties / relation_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Relation Id"
        +}
    • Removedset_default_project
    • Removedswitch_project
    • Removedsync_status
    • Changedwrite_note3 fields changed
      • removedInput schema / properties / entity_type
        Removed value: -{
        -  "default": "note",
        -  "title": "Entity Type",
        -  "type": "string"
        -}
      • addedInput schema / properties / note_type
        Added value: +{
        +  "default": "note",
        +  "title": "Note Type",
        +  "type": "string"
        +}
      • addedInput schema / properties / tags / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  4. 2 tool updates
    • Changedbuild_context11 fields changed
      • addedInput schema / $defs
        Added value: +{
        +  "StringOrInt": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "integer"
        +      }
        +    ]
        +  }
        +}
      • changedInput schema / properties / depth / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/StringOrInt"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / $defs / ContextResult / properties / primary_result / anyOf
        Removed value: -[
        -  {
        -    "$ref": "#/$defs/EntitySummary"
        -  },
        -  {
        -    "$ref": "#/$defs/RelationSummary"
        -  },
        -  {
        -    "$ref": "#/$defs/ObservationSummary"
        -  }
        -]
      • addedOutput schema / $defs / ContextResult / properties / primary_result / discriminator
        Added value: +{
        +  "mapping": {
        +    "entity": "#/$defs/EntitySummary",
        +    "observation": "#/$defs/ObservationSummary",
        +    "relation": "#/$defs/RelationSummary"
        +  },
        +  "propertyName": "type"
        +}
      • addedOutput schema / $defs / ContextResult / properties / primary_result / oneOf
        Added value: +[
        +  {
        +    "$ref": "#/$defs/EntitySummary"
        +  },
        +  {
        +    "$ref": "#/$defs/RelationSummary"
        +  },
        +  {
        +    "$ref": "#/$defs/ObservationSummary"
        +  }
        +]
      • removedOutput schema / $defs / ContextResult / properties / related_results / items / anyOf
        Removed value: -[
        -  {
        -    "$ref": "#/$defs/EntitySummary"
        -  },
        -  {
        -    "$ref": "#/$defs/RelationSummary"
        -  },
        -  {
        -    "$ref": "#/$defs/ObservationSummary"
        -  }
        -]
      • addedOutput schema / $defs / ContextResult / properties / related_results / items / discriminator
        Added value: +{
        +  "mapping": {
        +    "entity": "#/$defs/EntitySummary",
        +    "observation": "#/$defs/ObservationSummary",
        +    "relation": "#/$defs/RelationSummary"
        +  },
        +  "propertyName": "type"
        +}
      • addedOutput schema / $defs / ContextResult / properties / related_results / items / oneOf
        Added value: +[
        +  {
        +    "$ref": "#/$defs/EntitySummary"
        +  },
        +  {
        +    "$ref": "#/$defs/RelationSummary"
        +  },
        +  {
        +    "$ref": "#/$defs/ObservationSummary"
        +  }
        +]
      • addedOutput schema / $defs / EntitySummary / properties / type / const
        Added value: +"entity"
      • addedOutput schema / $defs / ObservationSummary / properties / type / const
        Added value: +"observation"
      • addedOutput schema / $defs / RelationSummary / properties / type / const
        Added value: +"relation"
    • Changedrecent_activity9 fields changed
      • removedOutput schema / $defs / ContextResult / properties / primary_result / anyOf
        Removed value: -[
        -  {
        -    "$ref": "#/$defs/EntitySummary"
        -  },
        -  {
        -    "$ref": "#/$defs/RelationSummary"
        -  },
        -  {
        -    "$ref": "#/$defs/ObservationSummary"
        -  }
        -]
      • addedOutput schema / $defs / ContextResult / properties / primary_result / discriminator
        Added value: +{
        +  "mapping": {
        +    "entity": "#/$defs/EntitySummary",
        +    "observation": "#/$defs/ObservationSummary",
        +    "relation": "#/$defs/RelationSummary"
        +  },
        +  "propertyName": "type"
        +}
      • addedOutput schema / $defs / ContextResult / properties / primary_result / oneOf
        Added value: +[
        +  {
        +    "$ref": "#/$defs/EntitySummary"
        +  },
        +  {
        +    "$ref": "#/$defs/RelationSummary"
        +  },
        +  {
        +    "$ref": "#/$defs/ObservationSummary"
        +  }
        +]
      • removedOutput schema / $defs / ContextResult / properties / related_results / items / anyOf
        Removed value: -[
        -  {
        -    "$ref": "#/$defs/EntitySummary"
        -  },
        -  {
        -    "$ref": "#/$defs/RelationSummary"
        -  },
        -  {
        -    "$ref": "#/$defs/ObservationSummary"
        -  }
        -]
      • addedOutput schema / $defs / ContextResult / properties / related_results / items / discriminator
        Added value: +{
        +  "mapping": {
        +    "entity": "#/$defs/EntitySummary",
        +    "observation": "#/$defs/ObservationSummary",
        +    "relation": "#/$defs/RelationSummary"
        +  },
        +  "propertyName": "type"
        +}
      • addedOutput schema / $defs / ContextResult / properties / related_results / items / oneOf
        Added value: +[
        +  {
        +    "$ref": "#/$defs/EntitySummary"
        +  },
        +  {
        +    "$ref": "#/$defs/RelationSummary"
        +  },
        +  {
        +    "$ref": "#/$defs/ObservationSummary"
        +  }
        +]
      • addedOutput schema / $defs / EntitySummary / properties / type / const
        Added value: +"entity"
      • addedOutput schema / $defs / ObservationSummary / properties / type / const
        Added value: +"observation"
      • addedOutput schema / $defs / RelationSummary / properties / type / const
        Added value: +"relation"
  5. 19 tool updates
    • First observedbuild_context
    • First observedcanvas
    • First observedcreate_memory_project
    • First observeddelete_note
    • First observeddelete_project
    • First observededit_note
    • First observedget_current_project
    • First observedlist_directory
    • First observedlist_memory_projects
    • First observedmove_note
    • First observedread_content
    • First observedread_note
    • First observedrecent_activity
    • First observedsearch_notes
    • First observedset_default_project
    • First observedswitch_project
    • First observedsync_status
    • First observedview_note
    • First observedwrite_note

TDQS

A4/5.0

Scored across 12 tools

Disambiguation4/5

There is real overlap among three retrieval tools (bm_find, bm_list, bm_search), but the descriptions explicitly route the agent: bm_list for one folder, bm_find for recursive name/frontmatter matching, bm_search for ranked text/semantic search. Similarly bm_read (one note body) is distinguished from bm_context (graph traversal) and bm_write (full replace) from bm_edit (partial change). Only a small chance of misselection remains for an agent skimming names.

Naming Consistency4/5

All 12 tools follow a single predictable bm_<word> snake_case pattern with no style mixing. Most suffixes are verbs (find, list, read, write, edit, move, delete, search), but a few are nouns/commands (bm_context, bm_schema, bm_project, bm_man), which is a minor deviation rather than an inconsistency.

Tool Count5/5

Twelve tools sit comfortably in the well-scoped range and each maps to a distinct capability: directory listing, find, search, read, write, edit, move, delete, graph context, schema ops, project ops, and docs. None look like padding, and the surface is not so thin that agents would have to chain workarounds.

Completeness4/5

Note lifecycle is fully covered (create/replace, read, partial edit, move, delete, plus graph context and search), and bm_schema and bm_project cover schema and project management. Minor gaps: bm_project only supports list/create/recent (no rename or delete of projects), and there is no copy/duplicate operation, though the description notes the read+write+delete workaround.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Provides 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.
    41 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides persistent memory for AI tools by building a local knowledge graph from conversations, enabling cross-session recall and context awareness without cloud dependencies.
    9
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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 npm
    MIT