Memlord
Memlord is a self-hosted, multi-user MCP memory server with hybrid search, typed memory management, and workspace support via an MCP API and web UI (backed by PostgreSQL + pgvector).
Store memories (
store_memory): Save typed memories (fact,preference,instruction,feedback,decision) with tags, metadata, and workspace assignment. Includes automatic near-duplicate detection.Hybrid search (
retrieve_memory): Semantic (vector KNN) + full-text (BM25) search fused via Reciprocal Rank Fusion, with filtering by memory type, workspace, and similarity threshold. Returns compact snippets by default.Time-based search (
recall_memory): Find memories using natural-language time expressions (e.g., "last week", "about Python last month") combined with semantic search.Fetch a memory (
get_memory): Retrieve full content of a specific memory by numeric ID.List memories (
list_memories): Paginated listing ordered by creation date, filterable by type or tag.Tag search (
search_by_tag): Find memories by exact tag match with AND/OR logic.Update memory (
update_memory): Modify content, type, tags, or metadata of an existing memory by ID.Delete memory (
delete_memory): Permanently remove a memory by ID, including from vector and full-text indexes.Move memory (
move_memory): Transfer a memory between workspaces (requires write access).List workspaces (
list_workspaces): View all personal and shared workspaces you belong to, with roles and member counts.Web UI: Browse, search, edit, delete, import, and export memories in a browser interface.
Local embeddings: Zero-config local ONNX models โ no external API dependencies.
Utilizes PostgreSQL with the pgvector extension as the primary storage backend to provide persistent memory storage, full-text search, and vector-based semantic retrieval.
โจ Features
๐ Hybrid search โ BM25 (full-text) + vector KNN (pgvector) fused via Reciprocal Rank Fusion
๐ Multi-user โ each user sees only their own memories; workspaces for shared team knowledge
๐ ๏ธ 11 MCP tools โ store, retrieve, recall, list, search by tag, get, update, delete, move, list workspaces, dream report
๐ค Dreaming โ a guided consolidation pass (
dreamMCP prompt +dream_reporttool): finds near-duplicate and conflicting memories, merges them into insights non-destructively, driven by the client LLM๐ Web UI โ browse, search, edit and delete memories in the browser; export/import JSON
๐ OAuth 2.1 โ full in-process authorization server, always enabled
๐ PostgreSQL โ pgvector for embeddings, tsvector for full-text search
๐ Progressive disclosure โ search returns compact snippets by default; call
get_memory(name)only for what you need, reducing token usage๐ Deduplication โ automatically detects near-identical memories before saving, preventing noise accumulation
Related MCP server: Memory MCP Server
๐ How Memlord compares
Memlord | ||||
Search | BM25 + vector + RRF | Vector only (Qdrant) | BM25 + vector + RRF | BM25 + vector |
Embeddings | Local ONNX, zero config | OpenAI default; Ollama optional | Local ONNX, zero config | Local FastEmbed |
Storage | PostgreSQL + pgvector | PostgreSQL + Qdrant | SQLite-vec / Cloudflare Vectorize | SQLite + Markdown files |
Multi-user | โ | โ single-user in practice | โ ๏ธ agent-ID scoping, no isolation | โ |
Workspaces | โ shared + personal, invite links | โ ๏ธ "Apps" namespace | โ ๏ธ tags + conversation_id | โ per-project flag |
Authentication | โ OAuth 2.1 | โ none (self-hosted) | โ OAuth 2.0 + PKCE | โ |
Web UI | โ browse, edit, export | โ Next.js dashboard | โ rich UI, graph viz, quality scores | โ local; cloud only |
MCP tools | 11 | 5 | 15+ | ~20 |
Self-hosted | โ single process | โ Docker (3 containers) | โ | โ |
Memory input | Manual (explicit store) | Auto-extracted by LLM | Manual | Manual (Markdown notes) |
Memory types | fact / preference / instruction / feedback / decision / insight | auto-extracted facts | โ | observations + wiki links |
Time-aware search | โ natural language dates | โ ๏ธ REST only, not in MCP tools | โ | โ recent_activity |
Token efficiency | โ progressive disclosure | โ | โ | โ build_context traversal |
Import / Export | โ JSON | โ ZIP (JSON + JSONL) | โ | โ Markdown (human-readable) |
License | AGPL-3.0 / Commercial | Apache 2.0 | Apache 2.0 | AGPL-3.0 |
Where competitors have a real edge:
OpenMemory โ auto-extracts memories from raw conversation text; no need to decide what to store manually; good import/export
mcp-memory-service โ richer web UI (graph visualization, quality scoring, 8 tabs); more permissive license (Apache 2.0); multiple transport options (stdio, SSE, HTTP)
basic-memory โ memories are human-readable Markdown files you can edit, version-control, and read without any server; wiki-style entity links form a local knowledge graph; ~20 MCP tools
When to pick Memlord:
You want zero-config local embeddings โ ONNX model ships with the server, no Ollama or external API needed
You run a multi-user team server with proper OAuth 2.1 auth and invite-based workspaces
You want a production-grade database (PostgreSQL) that scales beyond a single machine's SQLite
You manage memories explicitly โ store exactly what matters, typed and tagged, not everything the LLM decides to extract
You want a self-hosted Web UI with full CRUD and JSON export, without a cloud subscription
๐ Quickstart
๐ณ Docker
cp .env.example .env
docker compose upHTTP server (multi-user, Web UI, OAuth)
# Install dependencies
uv sync --dev
# Download ONNX model (~23 MB)
uv run python scripts/download_model.py
# Run migrations
alembic upgrade head
# Start the server
memlordOpen http://localhost:8000 for the Web UI. The MCP endpoint is at /mcp.
๐ How It Works
Each search request runs BM25 and vector KNN in parallel, then merges results via Reciprocal Rank Fusion:
flowchart TD
Q([query]) --> BM25["BM25\nsearch_vector @@ websearch_to_tsquery"]
Q --> EMB["ONNX embed\nparaphrase-multilingual-MiniLM-L12-v2 ยท 384d ยท local"]
EMB --> KNN["KNN\nembedding <=> query_vector\ncosine distance"]
BM25 --> RRF["RRF fusion\nscore = 1/(k+rank_bm25) + 1/(k+rank_vec)\nk=60"]
KNN --> RRF
RRF --> R([top-N results])โ๏ธ Configuration
All settings use the MEMLORD_ prefix. See .env.example for the full list.
Variable | Default | Description |
|
| PostgreSQL connection URL |
|
| Server port |
|
| Public URL for OAuth (HTTP mode) |
|
| JWT signing secret (HTTP mode) |
Set MEMLORD_BASE_URL to your public URL and change MEMLORD_OAUTH_JWT_SECRET before deploying.
๐ ๏ธ MCP Tools
Tool | Description |
| Save a memory (idempotent by content); raises on near-duplicates; optional |
| Hybrid semantic + full-text search; returns snippets by default |
| Search by natural-language time expression; returns snippets by default |
| Paginated list with type/tag filters |
| AND/OR tag search |
| Fetch a single memory by name with full content (expired included) |
| Update content, type, tags, metadata, or expiry by name (and optionally rename) |
| Delete by name |
| Move a memory to a different workspace |
| List workspaces you are a member of (including personal) |
| Read-only consolidation candidates: similar memory pairs, expired and expiring-soon memories |
The dream MCP prompt walks the client LLM through a full consolidation pass over the
dream_report output: classify similar pairs (duplicate / complementary / conflict), merge
into insight memories, retire superseded ones via expires_at โ never destructively.
Workspace management (create, invite, join, leave) is handled via the Web UI.
๐ป System Requirements
Python 3.12
PostgreSQL โฅ 15 with pgvector extension
uv โ Python package manager
๐จโ๐ป Development
pyright src/ # type check
ruff format . # format
pytest # run tests
alembic-autogen-check # verify migrations are up to date๐ License
Memlord is dual-licensed:
AGPL-3.0 โ free for open-source use. If you run a modified version as a network service, you must publish your source code.
Commercial License โ for proprietary or closed-source deployments. Contact sergey@memlord.com or dmitry@memlord.com to purchase.
Available Tools
10 toolsdelete_memoryADestructive
Delete a memory by name. Pass workspace to disambiguate if the name exists in multiple workspaces.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| workspace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true, so description does not need to repeat destructiveness. It adds useful disambiguation context, but no further behavioral traits beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. First sentence states primary action, second adds optional guidance. Ideal conciseness for a simple tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given simple tool with 2 params and output schema present, description covers core operation and disambiguation. Missing details like permissions or confirmation, but adequate for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage for parameters. Description adds the purpose of workspace (disambiguation), but does not describe name parameter type or constraints, leaving gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Delete a memory by name', specifying verb and resource. Sibling tools (get_memory, list_memories, etc.) have different purposes, so no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description explains when to use workspace parameter for disambiguation, but does not explicitly state when not to use this tool or suggest alternatives like update_memory if deletion is not intended.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_memoryARead-only
Fetch full content of a single memory by numeric ID.
Use only when you already know the ID โ e.g. after retrieve_memory() or recall_memory() which return IDs in their results alongside compact snippets. Do NOT use for search โ use retrieve_memory() for semantic/text search or recall_memory() for time-based queries like 'last week'.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| workspace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| tags | Yes | |
| content | Yes | |
| metadata | No | |
| workspace | No | |
| created_at | Yes | |
| memory_type | Yes | fact: established fact about user, project, or system. preference: user's likes, dislikes, habits. instruction: persistent rule Claude must follow. feedback: evaluation of Claude's output. decision: a choice made with reasoning ('chose X over Y because Z'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that the tool fetches 'full content', reinforcing the read-only nature without contradicting annotations. It provides enough context given the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the core purpose, and each sentence serves a distinct role (purpose, usage conditions, exclusions). No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers tool purpose, usage conditions, and exclusions. With output schema present, return values don't need description. However, the lack of parameter clarification is a gap, making it slightly incomplete for a tool with 0% schema description coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description does not explain the parameters. It says 'by numeric ID' but the schema parameter is named 'name', which could confuse an agent. The description should explicitly map 'name' to the numeric ID. This is a missed opportunity to clarify parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches the full content of a single memory by numeric ID, using specific verb and resource. It distinguishes from sibling tools like retrieve_memory (semantic search) and recall_memory (time-based queries).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use (only when ID is known, e.g., after retrieve_memory or recall_memory) and when not to use (do not use for search), naming specific alternative tools. This provides clear guidance for the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_memoriesARead-only
Browse all memories ordered by creation date (newest first). Returns full content (not snippets). Use to enumerate or audit without a specific query.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Case-insensitive exact match on a single tag name | |
| page | No | ||
| page_size | No | ||
| memory_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | No | |
| items | No | |
| total | No | |
| page_size | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only; description adds that it returns full content and ordering, providing useful context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words, front-loaded with purpose and key details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Describes ordering and full content; does not mention pagination or filtering despite parameter presence, but output schema exists. Adequate for a simple list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Description adds no information about parameters; with 25% schema coverage, it should compensate but does not. Schema descriptions are adequate but the tool description ignores them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool browses all memories ordered by creation date (newest first) and returns full content, distinguishing it from query-based tools like recall_memory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use for enumeration or audit without a specific query, implying it's not for searching specific content; lacks explicit mention of alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workspacesARead-only
List all workspaces you are a member of (personal + shared).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. Description adds that it lists workspaces the user is a member of (personal + shared), providing context beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded, no wasted words. Perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has no parameters, has output schema, annotations cover safety, description covers purpose and scope. Complete for a simple read-only list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters; schema description coverage is 100%. Baseline score of 4 for 0 parameters, as description adds no parameter info but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool lists all workspaces the user is a member of, specifying personal and shared. Verb 'List' and resource 'workspaces' are precise. Sibling tools are all memory-related, so no confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description indicates when to use: to list workspaces. No explicit exclusion or alternatives, but given the tool's self-contained nature and distinct sibling set, the guidance is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_memoryA
Move a memory to a different to_workspace.
name: name of the memory to move. workspace: name of the target workspace (must be a member with write access). from_workspace: disambiguate source if the name exists in multiple workspaces.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| to_workspace | Yes | ||
| from_workspace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| created | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate non-destructive, but 'move' typically removes from source. The description adds workspace access requirement but does not clarify if memory is removed from source, potential side effects, or atomicity. There is a mild contradiction with destructiveHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with four lines covering the action and parameters. However, parameter descriptions are listed separately rather than integrated, slightly reducing flow.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the description covers parameters and basic action, it does not explain return values (despite output schema existing), error cases, or behavior on name conflict. For a 3-parameter tool, this is adequate but not comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains each parameter with purpose and constraints (e.g., 'to_workspace: must be a member with write access', 'from_workspace: disambiguate source'). This adds significant value beyond the bare schema, especially with 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Move a memory') and the target ('to a different to_workspace'). It distinguishes this tool from siblings like delete_memory or store_memory by focusing on relocation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for moving a memory between workspaces but does not provide explicit guidance on when to use vs. not use this tool, nor does it mention alternatives like update_memory for changing properties.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recall_memoryARead-only
Search memories by time expression + semantics. Returns names + metadata only.
Examples: "last week", "yesterday", "about Python last month". Use get_memory(name=...) to fetch full content of a specific result. Pass workspace= to search only within a specific workspace.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Query string | |
| n_results | No | ||
| workspace | No | ||
| memory_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it returns only names and metadata, and that search combines time and semantic expressions. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences plus examples, front-loaded with purpose. Every sentence adds value without redundancy. Efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers main usage, examples, workflow (use get_memory for full content), and workspace filtering. Missing details on n_results and memory_type parameters, but output schema exists to document return values, balancing completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains the 'query' parameter with examples and mentions the 'workspace' parameter. However, it does not cover 'n_results' or 'memory_type', and schema description coverage is only 25%, so the description provides partial but not complete compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Search memories by time expression + semantics. Returns names + metadata only.' It identifies the tool's primary function and its output scope, distinguishing it from get_memory which fetches full content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit examples of queries and directs to use get_memory for full content retrieval. Also explains how to limit search to a workspace. However, it does not differentiate from sibling tools like retrieve_memory or search_by_tag.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retrieve_memoryARead-only
Hybrid semantic + full-text search. Returns names + metadata only.
Use get_memory(name=...) to fetch full content of a specific result. Pass workspace= to search only within a specific workspace.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | Query string | |
| workspace | No | ||
| memory_type | No | ||
| similarity_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds that it returns 'names + metadata only' and specifies the search method, providing useful context beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with two sentences that are front-loaded with the core purpose. Every sentence adds value without waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core purpose, alternative tool, and workspace filtering but omits details about memory_type, limit, and similarity_threshold parameters. Given the output schema exists, return values are not needed, but parameter guidance is incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (20%). The description only hints at the workspace parameter and does not explain query, limit, similarity_threshold, or memory_type meanings. It fails to compensate for the schema's lack of detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Hybrid semantic + full-text search' and specifies what it returns ('names + metadata only'). This effectively distinguishes it from siblings like get_memory, which fetches full content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises to use get_memory for full content retrieval, providing clear guidance on when to use an alternative. It also mentions workspace filtering but lacks explicit when-not-to-use scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_tagARead-only
Find memories by exact tag match. Returns all results (no pagination).
operation="AND" (default): memory must have ALL specified tags. operation="OR": memory must have AT LEAST ONE of the specified tags. Tags are case-insensitive. Use retrieve_memory() for semantic/text search or list_memories(tag=...) to browse a single tag with pagination.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | Yes | ||
| operation | No | AND |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | No | |
| items | No | |
| total | No | |
| page_size | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, destructiveHint), the description adds key behaviors: no pagination, case-insensitive tags, and operation semantics. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Highly concise: core purpose in first sentence, operation details in second, alternatives in third. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description covers purpose, behavior, parameters, and usage alternatives. Complete for its complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description must compensate. It explains operation parameter (AND/OR logic) and case-insensitivity, but doesn't elaborate on tags format or uniqueness which is already in schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Find memories by exact tag match. Returns all results (no pagination).' It uses specific verb and resource, and distinguishes from siblings like retrieve_memory and list_memories.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly provides when to use (exact tag match with AND/OR operations) and when not to use, suggesting alternatives: retrieve_memory for semantic search and list_memories for paginated single tag browsing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
store_memoryAIdempotent
Save a new memory. Idempotent: returns existing if content already stored.
name: human-readable name, unique within the workspace. workspace: name of the workspace to store into. Omit to store as a personal memory. force: skip near-duplicate check and store unconditionally.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| tags | No | ||
| force | No | Skip near-duplicate check and store unconditionally. | |
| content | Yes | ||
| metadata | No | ||
| workspace | No | Name of the workspace to store into (must be a member). Omit or pass None to store as a personal memory. | |
| memory_type | Yes | fact: established fact about user, project, or system. preference: user's likes, dislikes, habits. instruction: persistent rule Claude must follow. feedback: evaluation of Claude's output. decision: a choice made with reasoning ('chose X over Y because Z'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| created | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide idempotentHint:true and destructiveHint:false; the description adds specific behavioral context: idempotence, returning existing memory if content exists, and the force parameter skipping near-duplicate checks. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very concise: two sentences for purpose and idempotence, then bullet-point-style parameter explanations. No redundant text; every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters (3 required) and an existing output schema, the description covers idempotence, workspace semantics, and force flag. It lacks explanation of content and tags, but those are either clear from schema or handled by output schema. Overall mostly complete for a creation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 43% (force, workspace, memory_type have schema descriptions). The description explicitly adds meaning for name, workspace, and force parameters, partially compensating for lacking schema descriptions for content, tags, and metadata. However, not all parameters are addressed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Save a new memory' and highlights idempotence, distinguishing it from siblings like update_memory and delete_memory by the idempotent behavior and return of existing memory if content matches.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the workspace and force parameters, and mentions idempotence, but does not explicitly state when to use this tool versus alternatives like recall_memory or search_by_tag. Usage context is implied but not fully differentiated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_memoryB
Update an existing memory identified by name. Only provided fields are changed.
new_name: rename the memory to this name. workspace: disambiguate if the name exists in multiple workspaces.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| tags | No | ||
| content | No | ||
| metadata | No | ||
| new_name | No | ||
| workspace | No | ||
| memory_type | Yes | fact: established fact about user, project, or system. preference: user's likes, dislikes, habits. instruction: persistent rule Claude must follow. feedback: evaluation of Claude's output. decision: a choice made with reasoning ('chose X over Y because Z'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| created | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide no destructive or idempotent hints. The description adds that only provided fields change, but lacks details on side effects, permissions, or conflict handling. Little beyond basic mutation behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is short and front-loaded with the key purpose. Follow-up on new_name and workspace is clear. Could be more structured but efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters and output schema existing, the description covers core behavior but ignores optional fields (tags, content, metadata). Adequate for basic use, but gaps remain for complex inputs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (14%), with only memory_type described. The description adds meaning for new_name and workspace, but content, tags, and metadata remain undocumented. Partial compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it updates an existing memory by name, with partial updates ('Only provided fields are changed'). This distinguishes it from siblings like delete_memory, get_memory, and store_memory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for partial updates ('Only provided fields are changed') but does not explicitly state when to use vs alternatives like store_memory for creation or delete_memory for removal. No exclusions or context are provided.
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.
10 tool updates
- Added
delete_memory - Added
get_memory - Added
list_memories - Added
list_workspaces - Added
move_memory - Added
recall_memory - Added
retrieve_memory - Added
search_by_tag - Added
store_memory - Added
update_memory
10 tool updates
v0.2.8- Removed
delete_memory - Removed
get_memory - Removed
list_memories - Removed
list_workspaces - Removed
move_memory - Removed
recall_memory - Removed
retrieve_memory - Removed
search_by_tag - Removed
store_memory - Removed
update_memory
5 tool updates
v0.2.7- Changed
get_memory1 field changed- removed
Output schema / properties / created_at / formatRemoved value: -"date-time"
- Changed
list_memories5 fields changed- added
Output schema / properties / page / defaultAdded value: +1 - added
Output schema / properties / page_size / defaultAdded value: +0 - added
Output schema / properties / total / defaultAdded value: +0 - added
Output schema / properties / total_pages / defaultAdded value: +0 - removed
Output schema / requiredRemoved value: -[ - "items", - "total", - "page", - "page_size", - "total_pages" -]
- Changed
recall_memory5 fields changed- added
Output schema / properties / itemsAdded value: +{ + "items": { + "properties": { + "content": { + "title": "Content", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "integer" + }, + "memory_type": { + "anyOf": [ + { + "enum": [ + "fact", + "preference", + "instruction", + "feedback" + ], + "title": "MemoryType", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "tags": { + "items": { + "type": "string" + }, + "title": "Tags", + "type": "array", + "uniqueItems": true + }, + "workspace_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Workspace Id" + } + }, + "required": [ + "id", + "content", + "memory_type", + "tags", + "created_at" + ], + "title": "RecallResult", + "type": "object" + }, + "title": "Items", + "type": "array" +} - removed
Output schema / properties / resultRemoved value: -{ - "items": { - "properties": { - "content": { - "type": "string" - }, - "created_at": { - "format": "date-time", - "type": "string" - }, - "id": { - "type": "integer" - }, - "memory_type": { - "anyOf": [ - { - "enum": [ - "fact", - "preference", - "instruction", - "feedback" - ], - "type": "string" - }, - { - "type": "null" - } - ] - }, - "tags": { - "items": { - "type": "string" - }, - "type": "array", - "uniqueItems": true - }, - "workspace_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "required": [ - "id", - "content", - "memory_type", - "tags", - "created_at" - ], - "type": "object" - }, - "type": "array" -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - added
Output schema / titleAdded value: +"RecallPage" - removed
Output schema / x-fastmcp-wrap-resultRemoved value: -true
- Changed
retrieve_memory1 field changed- removed
Output schema / properties / result / items / properties / created_at / formatRemoved value: -"date-time"
- Changed
search_by_tag9 fields changed- added
Output schema / properties / itemsAdded value: +{ + "items": { + "properties": { + "content": { + "title": "Content", + "type": "string" + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "id": { + "title": "Id", + "type": "integer" + }, + "memory_type": { + "enum": [ + "fact", + "preference", + "instruction", + "feedback" + ], + "title": "MemoryType", + "type": "string" + }, + "metadata": { + "additionalProperties": true, + "title": "Metadata", + "type": "object" + }, + "tags": { + "items": { + "type": "string" + }, + "title": "Tags", + "type": "array", + "uniqueItems": true + }, + "workspace_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Workspace Id" + } + }, + "required": [ + "id", + "content", + "memory_type", + "tags", + "created_at" + ], + "title": "MemoryListItem", + "type": "object" + }, + "title": "Items", + "type": "array" +} - added
Output schema / properties / pageAdded value: +{ + "default": 1, + "title": "Page", + "type": "integer" +} - added
Output schema / properties / page_sizeAdded value: +{ + "default": 0, + "title": "Page Size", + "type": "integer" +} - removed
Output schema / properties / resultRemoved value: -{ - "items": { - "properties": { - "content": { - "type": "string" - }, - "created_at": { - "format": "date-time", - "type": "string" - }, - "id": { - "type": "integer" - }, - "memory_type": { - "enum": [ - "fact", - "preference", - "instruction", - "feedback" - ], - "type": "string" - }, - "metadata": { - "additionalProperties": true, - "type": "object" - }, - "tags": { - "items": { - "type": "string" - }, - "type": "array", - "uniqueItems": true - }, - "workspace_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "required": [ - "id", - "content", - "memory_type", - "tags", - "created_at" - ], - "type": "object" - }, - "type": "array" -} - added
Output schema / properties / totalAdded value: +{ + "default": 0, + "title": "Total", + "type": "integer" +} - added
Output schema / properties / total_pagesAdded value: +{ + "default": 0, + "title": "Total Pages", + "type": "integer" +} - removed
Output schema / requiredRemoved value: -[ - "result" -] - added
Output schema / titleAdded value: +"MemoryPage" - removed
Output schema / x-fastmcp-wrap-resultRemoved value: -true
10 tool updates
v0.2.4- First observed
delete_memory - First observed
get_memory - First observed
list_memories - First observed
list_workspaces - First observed
move_memory - First observed
recall_memory - First observed
retrieve_memory - First observed
search_by_tag - First observed
store_memory - First observed
update_memory
TDQS
Scored across 10 tools
The CRUD and workspace tools are clearly separated, but the three search tools (retrieve_memory, recall_memory, search_by_tag) plus list_memories create moderate overlap. The descriptions provide enough guidance to avoid frequent misselection.
Most tools follow a consistent verb_noun pattern like store_memory, get_memory, update_memory, and delete_memory. However, search_by_tag breaks the pattern, and list_memories/list_workspaces use plural nouns, causing minor inconsistency.
Ten tools is well-scoped for a memory server, covering CRUD, multiple retrieval modes, tag search, and workspace management. Each tool has a clear role without significant redundancy.
The core memory lifecycle is well covered: store, retrieve, get, update, delete, and move. A minor gap is that get_memory requires an ID by name is not directly available, so users must list or search first to find the ID.
Maintenance
Related MCP Connectors
Cloud-hosted MCP server for durable AI memory
An MCP memory server. One memory your agents share โ across models, devices and apps.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Related MCP Servers
AlicenseAqualityFmaintenanceAn MCP server that integrates with mem0.ai to help users store, retrieve, and search coding preferences for more consistent programming practices.9661Apache 2.0- AlicenseBqualityDmaintenanceProvides dynamic short-term and long-term memory management with keyword-based relevance scoring, time-decay models, and trigger-based recall. Optimized for Chinese language support with jieba segmentation.216 npm1BSD 3-Clause

Memory Nexusofficial
AlicenseNot gradedqualityDmaintenancePersistent memory and handoff intelligence layer for MCP agents. Most memory servers retrieve text โ Memory Nexus compounds operational context, learning from usage and progressively synthesizing observations into higher-order intelligence across sessions and tools.MIT- FlicenseNot gradedqualityDmaintenanceProvides persistent AI agent memory using a local vector database for long-term semantic storage and short-term session scratchpads. It enables low-latency memory operations including search, storage, and bulk management without external cloud dependencies.-