Skip to main content
Glama
asd-noor

Memory Engine MCP Server

by asd-noor

Memory Engine MCP Server

Deprecated: Use ProjectContext.

A high-performance MCP (Model Context Protocol) server providing long-term memory storage with semantic and keyword search capabilities.

Features

  • Fast Semantic Search: Uses fastembed with BAAI/bge-small-en-v1.5 for fast startup and low memory usage

  • Hybrid Search: Combines keyword (FTS5) and vector search using Reciprocal Rank Fusion (RRF)

  • Persistent Storage: SQLite-based storage with sqlite-vec extension

  • Sub-200ms Queries: Keep embedding model in memory for fast response times

  • MCP Native: Exposes save_memory and query_memory as native MCP tools

Related MCP server: Memento

Installation

# Clone the repository
git clone <repo-url>
cd agentmemory

# Install dependencies with uv
uv sync

# Or install globally
uv pip install -e .

Usage

Running the Server

# Run directly
agentmemory

# Or with uv
uv run agentmemory

MCP Configuration

Add to your MCP client configuration (e.g., mcp.json):

{
  "mcpServers": {
    "memory": {
      "command": "uv",
      "args": ["run", "agentmemory"],
      "cwd": "/path/to/agentmemory"
    }
  }
}

Or using the installed script:

{
  "mcpServers": {
    "memory": {
      "command": "agentmemory"
    }
  }
}

MCP Tools

save_memory

Save a memory to long-term storage.

Arguments:

  • category (string): Category of the memory (e.g., "architecture", "preference", "bug_fix")

  • topic (string): Short descriptive title

  • content (string): Detailed memory/decision text

Returns:

{
  "status": "success",
  "doc_id": 123,
  "topic": "Example Topic",
  "category": "architecture"
}

query_memory

Query memories using semantic and keyword search.

Arguments:

  • query (string): Natural language search string

  • top_k (integer, optional): Number of results to return (default: 3)

Returns:

[
  {
    "id": 123,
    "category": "architecture",
    "topic": "Example Topic",
    "content": "Detailed content...",
    "timestamp": "2024-02-04 13:22:00",
    "last_verified": "2024-02-04 13:22:00",
    "score": 0.8542
  }
]

Note: last_verified indicates when the memory was last confirmed as accurate. Use verify_memory to update this timestamp.

delete_memory

Delete a memory by ID.

Arguments:

  • doc_id (integer): The ID of the memory to delete

Returns:

{
  "status": "success",
  "message": "Memory 123 deleted"
}

update_memory

Update a memory by ID.

Arguments:

  • doc_id (integer): The ID of the memory to update

  • category (string, optional): New category

  • topic (string, optional): New topic

  • content (string, optional): New content

Returns:

{
  "status": "success",
  "doc_id": 123,
  "topic": "Updated Topic",
  "category": "updated_category",
  "message": "Memory updated"
}

verify_memory

Mark a memory as verified by updating its last_verified timestamp to now.

Use this when:

  • You've confirmed a memory is still accurate

  • You've checked information against current code

  • You want to prevent hallucinations from stale data

Arguments:

  • doc_id (integer): The ID of the memory to verify

Returns:

{
  "status": "success",
  "doc_id": 123,
  "message": "Memory verified and timestamp updated"
}

Note: This helps track memory freshness. Memories with old last_verified timestamps should be treated with caution.

MCP Resources

memory://usage-guidelines

Provides comprehensive usage guidelines for AI agents using the memory system.

Access via MCP client:

content = await client.read_resource("memory://usage-guidelines")
print(content[0].text)

Contains:

  • When to save memories (DO's and DON'Ts)

  • How to structure memories (category, topic, content)

  • How to query effectively

  • Best practices and common patterns

  • Search features and capabilities

  • Privacy and security considerations

Note: AI agents can read this resource to understand how to use the memory system effectively. The guidelines help ensure memories are saved consistently and can be retrieved efficiently.

Examples

Saving a Technical Decision

Agent: "I'll record that we've decided to use SQLite for its simplicity and local persistence."

save_memory(
    category="architecture",
    topic="Database Choice",
    content="We chose SQLite with sqlite-vec for local vector storage. This avoids external dependencies and keeps data within the project git root."
)

Retrieving Project Context

Agent: "Let me check our previous decisions about the tech stack."

query_memory(query="tech stack decisions")
# Returns: [Database Choice, Python version requirements, etc.]

Preventing Stale Data

Agent: "I just verified that the Python version requirement is still 3.12."

verify_memory(doc_id=123)

Architecture

Technology Stack

  • Framework: FastMCP (Python MCP library)

  • Embeddings: fastembed (BAAI/bge-small-en-v1.5, 384-dim)

  • Database: SQLite with sqlite-vec and FTS5 extensions

  • Communication: JSON-RPC over stdio

Data Flow

  1. Save: Content → Embedding → SQLite (docs + docs_fts + docs_vec)

  2. Query: Query → Embedding → Parallel FTS5 + Vector Search → RRF Fusion → Ranked Results

Database Schema

-- Main documents table
CREATE TABLE docs (
  id INTEGER PRIMARY KEY,
  category TEXT,
  topic TEXT,
  content TEXT,
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
  last_verified DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Full-text search index
CREATE VIRTUAL TABLE docs_fts USING fts5(
  category, topic, content,
  content='docs',
  content_rowid='id'
);

-- Vector search index
CREATE VIRTUAL TABLE docs_vec USING vec0(
  id INTEGER PRIMARY KEY,
  embedding float[384]
);

Storage Location

The database is stored in .ctxhub/memory.sqlite in the git root directory (or current working directory if not in a git repo). This allows the memory to travel with the project while remaining hidden from version control.

Performance

  • First Query: ~500ms (model initialization + query)

  • Subsequent Queries: <200ms (model kept in memory)

  • Embedding Model Size: ~133MB (BAAI/bge-small-en-v1.5)

  • Memory Usage: ~200MB base + model

Development

Project Structure

agentmemory/
├── src/
│   └── agentmemory/
│       ├── __init__.py
│       └── server.py       # MCP server implementation
├── pyproject.toml          # Project configuration
└── .agent-memory/
    └── db.sqlite           # Persistent database (in git root)

Testing

The project includes a comprehensive test suite.

# Quick start: runs main tests and offers to start server
./quickstart.sh

# Run specific tests manually
uv run python tests/test_server.py
uv run python tests/test_freshness.py
uv run python tests/test_updates.py

MCP Inspector

You can also test the tools interactively using the MCP Inspector:

npx @modelcontextprotocol/inspector uv run agentmemory

License

GPLv3

Available Tools

5 tools
delete_memoryA

Delete a memory by ID.

Args:
    doc_id: The ID of the memory to delete

Returns:
    A dictionary with status and message
ParametersJSON Schema
NameRequiredDescriptionDefault
doc_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description must carry the full burden of behavioral disclosure. It states it deletes a memory but does not disclose irreversibility, permission requirements, or behavior when doc_id is not found. The return type is vaguely described as 'a dictionary with status and message' without specifics.

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 concise and structured with Args and Returns sections. It contains no redundant sentences and is appropriately sized for a simple delete operation.

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?

For a simple delete tool with one parameter, the description covers purpose, parameter, and return. However, with no annotations, it lacks important context about permanence and error conditions, making it only minimally complete. It does not reference the existing output schema (if any) or provide example usage.

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 has no description for doc_id (0% coverage). The description compensates by explaining 'The ID of the memory to delete', adding meaning beyond the schema's bare integer type. However, it does not specify format or constraints beyond that.

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 clearly states 'Delete a memory by ID', using a specific verb ('Delete') and resource ('memory'), which distinguishes it from siblings like save_memory and update_memory. The scope is precisely defined by ID.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives. It does not explicitly state that this is for permanent removal or mention any prerequisites or conditions. Sibling tools (update_memory, query_memory) are not referenced as alternatives.

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

query_memoryA

Query memories using semantic and keyword search.

Args:
    query: Natural language search string
    top_k: Number of results to return (default: 3)

Returns:
    A list of matching memories with similarity scores
ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
top_kNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

No annotations are provided, so the description carries the burden. It discloses the search method (semantic and keyword) and the return format (list with similarity scores). While it doesn't explicitly state read-only behavior, the word 'query' implies no mutation, and the description adds useful context beyond a simple 'Query memories.'

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 compact and well-structured with a clear one-sentence purpose followed by Args and Returns sections. Every sentence provides necessary information with no redundancy or fluff.

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

Completeness5/5

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

For a 2-parameter query tool with an output schema, the description covers all essential aspects: purpose, parameter semantics, and return value shape. No additional context is needed for an agent to correctly select and invoke the tool.

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

Parameters5/5

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

The input schema has 0% description coverage, but the description fully compensates by defining each parameter: query as 'Natural language search string' and top_k as 'Number of results to return (default: 3).' This adds semantic meaning beyond the schema's type and default.

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 clearly states the tool's function: 'Query memories using semantic and keyword search.' It specifies a specific verb (query), resource (memories), and distinguishes itself from sibling tools like save_memory and delete_memory by focusing on retrieval.

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?

The description implies usage for searching memories but provides no explicit guidance on when to use this tool versus alternatives like search_agendas. It lacks exclusions or conditions, leaving the agent to infer based on the name and resource.

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

save_memoryA

Save a memory to the long-term storage.

Args:
    category: The category of the memory (e.g., "architecture", "preference", "bug_fix")
    topic: A short descriptive title for the memory
    content: The detailed memory/decision text

Returns:
    A dictionary with status, doc_id, topic, and category
ParametersJSON Schema
NameRequiredDescriptionDefault
topicYes
contentYes
categoryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior2/5

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

No annotations are provided, so the description must convey behavioral context. It mentions 'long-term storage' and a return dictionary containing a doc_id, which implies creation, but it does not disclose whether the operation overwrites existing memories, requires specific permissions, or has other side effects. This is a significant gap for a write operation.

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 highly concise, using a standard Args/Returns docstring format. Every sentence serves a purpose, and there is no redundant information. It is well-structured and immediately readable.

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?

The description covers the essential information: inputs and the return value, and an output schema exists. However, it omits usage scenarios, error conditions, and edge cases (e.g., duplicate topics). For a simple save tool, this is largely sufficient, but a bit more context would improve completeness.

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?

With 0% schema coverage, the description compensates well by explaining each parameter: 'category' includes examples, 'topic' is defined as a short title, and 'content' as detailed text. This adds value beyond the bare parameter names, though it lacks constraints on allowed values or formats.

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 clearly states the tool's function with a specific verb ('Save') and resource ('memory'), and mentions 'long-term storage' to indicate persistence. Sibling tools (delete/update/verify/query) confirm this is a creation operation, distinguishing it from related actions.

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?

The description implies usage ('Save a memory') but provides no explicit guidance on when to use this tool versus alternatives like update_memory or query_memory. There are no exclusions or alternative recommendations, only the inferred distinction from sibling names.

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

update_memoryA

Update a memory by ID.

Args:
    doc_id: The ID of the memory to update
    category: New category (optional)
    topic: New topic (optional)
    content: New content (optional)

Returns:
    A dictionary with status and updated details
ParametersJSON Schema
NameRequiredDescriptionDefault
topicNo
doc_idYes
contentNo
categoryNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior2/5

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

With no annotations, the description must disclose behavioral traits. It only states it updates by ID and returns a status dictionary, but misses crucial behavior such as handling of non-existent IDs, whether unspecified fields are left unchanged, or error conditions. This is a significant gap for a mutating tool.

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 concise and well-structured: a one-sentence purpose, followed by an Args section for each parameter and a Returns section. No redundancy, every sentence adds value.

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 simple update tool, the description covers purpose, parameters, and return format. It misses edge-case behavior like invalid IDs, but given the presence of an output schema and simple params, it's largely complete. A 4 reflects minor gaps.

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

Parameters5/5

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

The description explains each parameter with clear semantics: doc_id is the target, and category/topic/content are optional new values. Since the schema has no descriptions (0% coverage), the description provides complete parameter meaning beyond the schema.

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

Purpose5/5

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

The description clearly states 'Update a memory by ID' with a specific verb and resource, distinguishing it from sibling tools like save_memory and delete_memory by focusing on modification of existing memories.

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?

The description implies usage for modifying an existing memory but doesn't explicitly say when not to use it or name alternatives. It provides no comparison with sibling tools like save_memory for creation, making usage context implicit rather than explicit.

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

verify_memoryA

Mark a memory as verified, updating its last_verified timestamp to now.

Use this when you've confirmed the memory is still accurate and up-to-date.
This helps track memory freshness and prevents hallucinations from outdated information.

Args:
    doc_id: The ID of the memory to verify

Returns:
    A dictionary with status and message
ParametersJSON Schema
NameRequiredDescriptionDefault
doc_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

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

No annotations are present, so the description carries the full burden. It discloses the main side effect (updating the last_verified timestamp) and the return type ('A dictionary with status and message'). However, it does not discuss error handling, permissions, or behavior when the doc_id does not exist, which are relevant for a write operation.

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 well-structured with a clear opening statement, a usage hint, a rationale, and an Args/Returns section. Each sentence earns its place and there is no redundancy.

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 simple single-parameter tool, the description covers the core purpose, usage, parameter, and return value. The output schema existence reduces the need to describe return format, and the description does that anyway. Minor gaps remain regarding error cases, but it is sufficiently complete for an agent to apply it correctly.

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

Parameters5/5

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

The input schema only provides the type (integer) and title for doc_id. The description compensates fully by explaining its meaning: 'doc_id: The ID of the memory to verify.' This is sufficient despite the schema's 0% coverage.

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 clearly identifies the tool's purpose: 'Mark a memory as verified, updating its last_verified timestamp to now.' This is a specific verb+resource combination that distinguishes it from the sibling tools (save_memory, delete_memory, update_memory, query_memory).

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 description provides explicit usage context: 'Use this when you've confirmed the memory is still accurate and up-to-date.' It does not explicitly mention alternatives or when not to use it, but the context is clear enough to guide the agent.

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. 5 tool updatesv1.0.0
    • First observeddelete_memory
    • First observedquery_memory
    • First observedsave_memory
    • First observedupdate_memory
    • First observedverify_memory

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct memory operation: save (create), delete, update, verify, and query (search). There is no overlap in purpose, so an agent can easily select the right tool.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (e.g., save_memory, delete_memory, update_memory), making the API predictable and easy to navigate.

Tool Count5/5

With exactly 5 tools, the server is well-scoped for a memory management domain, covering essential operations without unnecessary complexity.

Completeness5/5

The server provides full CRUD coverage (save, query, update, delete) plus a verify operation for freshness. No critical lifecycle steps are missing for long-term memory storage.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers