Doramagic 项目包 · 项目说明书
agent-memory-mcp 项目
生成时间:2026-05-12 05:48:40 UTC
项目概览
Agent Memory MCP 是一个基于 MCP(Model Context Protocol)的持久化键值存储服务,专为 AI 智能体设计。该项目由 Nous Research 开发,采用 MIT 开源许可证,旨在解决 AI 智能体在会话之间丢失上下文的核心问题。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 项目简介
Agent Memory MCP 是一个基于 MCP(Model Context Protocol)的持久化键值存储服务,专为 AI 智能体设计。该项目由 Nous Research 开发,采用 MIT 开源许可证,旨在解决 AI 智能体在会话之间丢失上下文的核心问题。
核心价值主张: AI 智能体在每次新会话开始时会丢失所有上下文信息。Agent Memory MCP 通过提供持久化、可搜索的内存功能,使智能体能够跨会话、跨重启、跨日期记住重要信息。
项目依赖极为精简,仅需 Python 3.10+ 和 mcp>=1.0.0 两个核心依赖,数据以 JSON 格式存储在本地磁盘 ~/.agent-memory/ 目录下,完全实现本地优先(Local-first)的设计理念。
2. 核心功能特性
Agent Memory MCP 提供了七大核心工具支持完整的内存管理能力:
| 功能 | 描述 |
|---|---|
| memory_remember | 存储键值对,支持可选的 TTL(生存时间) |
| memory_recall | 检索键值对及其完整元数据 |
| memory_forget | 永久删除指定键 |
| memory_search | 按关键词跨命名空间搜索 |
| memory_list_namespaces | 列出所有命名空间及其条目计数 |
| memory_clear_namespace | 清空整个命名空间 |
| memory_stats | 获取全局存储统计信息 |
附加特性:
- 命名空间隔离:按项目、用户或领域组织内存,支持不同智能体使用独立存储空间
- TTL 支持:条目可设置自动过期时间,精确到秒级精度
- 模糊搜索:支持大小写不敏感的子字符串匹配,按访问频率排序
- 访问追踪:每条记忆记录创建时间、最后访问时间和访问次数
- 线程安全:通过
fcntl.flock()实现文件级锁,确保多进程并发安全访问 - 零外部依赖:仅使用 Python 标准库(json、fcntl、pathlib、datetime)
3. 系统架构
3.1 整体架构图
graph TD
subgraph AI层
A["🤖 AI Agent<br/>(Claude/GPT/Codex)"]
end
subgraph MCP协议层
B["📡 MCP Protocol<br/>(stdio JSON-RPC)"]
end
subgraph 服务器层
C["⚙️ Agent Memory MCP Server<br/>(server.py)"]
subgraph 核心模块
D["🗄️ KV Store Engine"]
E["⏱️ TTL Manager"]
F["🔍 Search Engine<br/>(substring match)"]
end
end
subgraph 存储层
G["📁 ~/.agent-memory/"]
H["{namespace}.json"]
I["_meta.json"]
end
A -->|"remember()<br/>recall()<br/>search()<br/>forget()"| B
B --> C
C --> D
C --> E
C --> F
D --> G
E --> G
F --> G
G --> H
G --> I3.2 核心组件职责
| 组件 | 文件位置 | 职责 |
|---|---|---|
| Server 入口 | server.py (main) | 初始化 MCP 服务器,监听 stdio 连接 |
| 工具路由 | server.py (call_tool) | 根据工具名称分发请求到对应处理函数 |
| 存储引擎 | server.py (_read_namespace, _write_namespace) | 读写 JSON 文件,支持文件锁 |
| TTL 管理器 | server.py (_is_expired, _cleanup_expired) | 检查和清理过期条目 |
| 搜索引擎 | server.py (memory_search) | 子字符串模糊匹配 |
| 格式化器 | server.py (_format_response) | 输出 Markdown 或 JSON 格式响应 |
4. 数据存储结构
4.1 存储目录布局
所有数据持久化到 ~/.agent-memory/ 目录:
~/.agent-memory/
├── default.json # 默认命名空间数据
├── preferences.json # 用户偏好命名空间
├── research.json # 研究数据命名空间
├── agent_xxx.json # 智能体专用命名空间
└── _meta.json # 全局元数据和统计
4.2 数据模型
命名空间文件结构({namespace}.json):
[
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
]
元数据文件结构(_meta.json):
{
"total_entries": 156,
"namespace_count": 5,
"oldest_entry": "2026-04-15",
"newest_entry": "2026-05-12"
}
4.3 常量定义
| 常量 | 值 | 说明 |
|---|---|---|
CHARACTER_LIMIT | 25,000 | 单次响应最大字符数 |
DEFAULT_NAMESPACE | "default" | 默认命名空间名称 |
STORAGE_DIR | Path.home() / ".agent-memory" | 数据存储根目录 |
META_FILE | "_meta.json" | 元数据文件名 |
资料来源:server.py:27-31
5. 工具 API 参考
5.1 memory_remember
存储键值对,支持可选 TTL。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | ✅ | 键标识符 |
value | string | ✅ | 要存储的值 |
namespace | string | ❌ | 命名空间(默认:"default") |
ttl_seconds | integer | ❌ | 自动过期秒数 |
format | string | ❌ | 返回格式(markdown/json) |
await memory_remember(
key="user:theme",
value="dark",
namespace="preferences",
ttl_seconds=2592000 # 30天
)
5.2 memory_recall
检索键值对及完整元数据。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | ✅ | 要检索的键 |
namespace | string | ❌ | 命名空间(默认:"default") |
format | string | ❌ | 返回格式(markdown/json) |
返回字段:
| 字段 | 说明 |
|---|---|
value | 存储的值 |
created_at | 创建时间 |
accessed_at | 最后访问时间 |
expires_at | TTL 过期时间(如设置) |
access_count | 访问次数统计 |
5.3 memory_forget
永久删除指定键。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | ✅ | 要删除的键 |
namespace | string | ❌ | 命名空间(默认:"default") |
format | string | ❌ | 返回格式(markdown/json) |
5.4 memory_search
跨命名空间模糊搜索。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query | string | ✅ | 搜索关键词或子字符串 |
namespace | string | ❌ | 限定搜索的命名空间 |
limit | integer | ❌ | 最大返回结果数(默认:10) |
format | string | ❌ | 返回格式(markdown/json) |
搜索特性:
- 大小写不敏感匹配
- 同时匹配键名和值内容
- 按访问次数降序排序
5.5 memory_list_namespaces
列出所有命名空间及其条目统计。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
format | string | ❌ | 返回格式(markdown/json) |
5.6 memory_clear_namespace
清空指定命名空间下的所有条目。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
namespace | string | ✅ | 要清空的命名空间 |
format | string | ❌ | 返回格式(markdown/json) |
5.7 memory_stats
获取全局存储统计信息。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
format | string | ❌ | 返回格式(markdown/json) |
返回字段:
| 字段 | 说明 |
|---|---|
total_entries | 总条目数(仅活跃条目) |
total_size_bytes | 存储总大小(字节) |
total_size_human | 存储总大小(人类可读) |
namespace_count | 命名空间数量 |
oldest_entry | 最旧条目创建时间 |
newest_entry | 最新条目创建时间 |
storage_path | 存储路径 |
free_tier_limit | 免费配额限制 |
pro_tier_limit | Pro 版本限制 |
6. 并发与锁机制
sequenceDiagram
participant Agent1 as Agent Process 1
participant Agent2 as Agent Process 2
participant FS as File System
Agent1->>FS: 请求文件锁 (LOCK_EX)
Note over FS: 锁定 {namespace}.json
Agent1->>FS: 读取/写入数据
Agent1->>FS: 释放文件锁 (LOCK_UN)
Agent2->>FS: 请求文件锁 (LOCK_EX)
Note over FS: 锁定 {namespace}.json
Agent2->>FS: 读取/写入数据
Agent2->>FS: 释放文件锁 (LOCK_UN)Agent Memory MCP 使用 Python 的 fcntl.flock() 实现文件级排他锁,确保多个智能体进程可以安全地并发读写存储文件。锁粒度为单个命名空间文件,而非整个存储目录,这允许不同命名空间的操作并行执行。
7. 命名空间安全
命名空间名称通过正则表达式进行安全过滤,防止目录遍历攻击:
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
资料来源:server.py:59-62
允许的字符集:a-zA-Z0-9_. -,所有非法字符替换为下划线。
8. 响应格式
8.1 Markdown 格式(默认)
## ✅ Success
**key:** user:theme
**value:** dark
**created_at:** 2026-05-12T10:30:00Z
**namespace:** preferences
**expires_at:** 2026-06-11T10:30:00Z
8.2 JSON 格式
{
"status": "ok",
"key": "user:theme",
"value": "dark",
"namespace": "preferences"
}
9. 安装与配置
9.1 环境要求
| 要求 | 最小版本 |
|---|---|
| Python | 3.10+ |
| MCP | >= 1.0.0 |
9.2 安装步骤
# 克隆仓库
git clone https://github.com/Rumblingb/agent-memory-mcp.git
cd agent-memory-mcp
# 安装依赖
pip install -r requirements.txt
# 或仅安装 MCP
pip install mcp
资料来源:README.md:60-68
9.3 MCP 客户端配置
Claude Desktop (config.json):
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["/path/to/agent-memory-mcp/server.py"]
}
}
}
VS Code / Cursor:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["server.py"],
"cwd": "/path/to/agent-memory-mcp"
}
}
}
通用配置(config.yaml):
mcpServers:
agent-memory:
command: python3
args:
- /path/to/agent-memory-mcp/server.py
description: Persistent key-value memory for AI agents
9.4 测试与开发
# 使用 MCP Inspector 测试
npx @modelcontextprotocol/inspector python3 server.py
# 运行测试套件
python3 -m pytest tests/
10. 使用场景示例
10.1 跨会话用户偏好
# 会话 1:智能体学习用户偏好
await memory_remember(
key="user:timezone",
value="America/Chicago",
namespace="preferences"
)
await memory_remember(
key="user:currency",
value="USD",
namespace="preferences"
)
# 会话 2(数天后):智能体立即回忆偏好
tz = await memory_recall("user:timezone", "preferences")
# 无需再次询问用户
10.2 研究积累智能体
# 存储研究发现
await memory_remember(
key="competitor:acme:api_pricing",
value="Acme API Pro: $49/mo for 10k calls. Enterprise: $199/mo. No free tier.",
namespace="research",
ttl_seconds=86400 * 7 # 保留 7 天
)
# 搜索所有竞争对手研究
findings = await memory_search(
query="competitor pricing",
namespace="research"
)
10.3 智能体草稿板
# 智能体使用内存作为工作草稿板
await memory_remember(
key="scratch:task:refactor-auth",
value="Step 1: Extract auth middleware. Step 2: Add token refresh. Step 3: Update tests.",
namespace="agent:code-reviewer"
)
# 检索当前任务状态
state = await memory_recall("scratch:task:refactor-auth", "agent:code-reviewer")
11. 设计原则
| 原则 | 描述 |
|---|---|
| 简单优于复杂 | 定位为类 Redis 的 KV 存储,而非向量数据库,专注于智能体的记忆需求 |
| 本地优先 | 数据存储在本地机器,无云服务、无 API 密钥、无延迟 |
| 自描述 | 工具响应默认采用人类可读的 Markdown 格式,JSON 用于程序调用 |
| 容错设计 | 延迟 TTL 过期、非严格搜索、优雅的错误处理 |
资料来源:README.md:77-84
12. 版本与定价
| 版本 | 价格 | 功能限制 |
|---|---|---|
| 免费版 | $0 | 1,000 条目,5 个命名空间 |
| Pro 版 | $19/月 | 无限条目,无限命名空间,优先支持 |
13. 相关项目
- Agent Cost Tracker MCP — AI 智能体 Token 用量和成本追踪
- Search Proxy MCP — AI 智能体 Web 搜索
- AgentPassport API — 托管支付中间件
资料来源:README.md:86-91
资料来源:[server.py:27-31]()
安装与配置
agent-memory-mcp 是一个基于 Model Context Protocol (MCP) 的持久化键值内存存储服务,专为 AI 代理设计。该项目通过提供 memoryremember、memoryrecall、memoryforget、memorysearch 等工具,使 AI 代理能够在不同会话之间保持上下文记忆。
继续阅读本节完整说明和来源证据。
概述
agent-memory-mcp 是一个基于 Model Context Protocol (MCP) 的持久化键值内存存储服务,专为 AI 代理设计。该项目通过提供 memory_remember、memory_recall、memory_forget、memory_search 等工具,使 AI 代理能够在不同会话之间保持上下文记忆。
本页面详细说明该项目的环境要求、安装方式以及在不同 MCP 客户端中的配置方法。
来源:https://github.com/Rumblingb/agent-memory-mcp / 项目说明书
系统架构
Agent Memory MCP 是一个基于 Model Context Protocol (MCP) 的持久化键值内存存储系统,专为 AI 代理设计。本页面详细说明其整体架构、核心组件、数据存储机制和并发控制策略。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 架构概述
Agent Memory MCP 采用分层架构设计,核心组件包括 MCP 协议层、业务逻辑层和持久化存储层。系统通过标准输入输出(stdio)进行 JSON-RPC 通信,实现与 AI 代理的交互。
┌──────────────────────────────────────────────────────┐
│ AI 代理层 (Claude/GPT/Codex) │
│ remember() / recall() / search() / forget() │
└──────────────────────┬───────────────────────────────┘
│ MCP 协议 (stdio JSON-RPC)
┌──────────────────────▼───────────────────────────────┐
│ Agent Memory MCP 服务器 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ 键值存储 │ │ TTL │ │ 搜索引擎 │ │
│ │ 引擎 │ │ 管理器 │ │ (子字符串匹配) │ │
│ └────┬─────┘ └────┬─────┘ └────────┬──────────┘ │
│ │ │ │ │
│ ┌────▼──────────────▼────────────────▼───────────┐ │
│ │ ~/.agent-memory/ │ │
│ │ {namespace}.json │ _meta.json │ │
│ └────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────┘
资料来源:server.py:1-50
2. 核心组件
2.1 MCP 服务器层
MCP 服务器是系统的核心入口点,负责处理协议级别的通信。
server = Server(
name="agent-memory",
version="1.0.0",
instructions="Agent Memory MCP — Persistent key-value memory for AI agents with TTL, namespaces, and search.",
website_url="https://github.com/nousresearch/agent-memory-mcp",
)
| 属性 | 值 | 说明 |
|---|---|---|
name | agent-memory | 服务器标识名 |
version | 1.0.0 | 语义化版本号 |
instructions | 协议说明 | MCP 客户端可见的指令 |
website_url | GitHub 仓库地址 | 项目主页 |
资料来源:server.py:175-181
2.2 工具注册与路由
系统定义了 7 个工具,全部通过 @server.list_tools() 装饰器注册,并通过 @server.call_tool() 统一路由分发。
@server.list_tools()
async def list_tools() -> List[Tool]:
return [
Tool(name="memory_remember", ...),
Tool(name="memory_recall", ...),
Tool(name="memory_forget", ...),
Tool(name="memory_search", ...),
Tool(name="memory_list_namespaces", ...),
Tool(name="memory_clear_namespace", ...),
Tool(name="memory_stats", ...),
]
@server.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]) -> CallToolResult:
if name == "memory_remember":
text = memory_remember(**arguments, fmt=fmt)
elif name == "memory_recall":
text = memory_recall(**arguments, fmt=fmt)
# ... 其他工具路由
资料来源:server.py:183-240
2.3 工具注解系统
每个工具都携带元数据注解,用于指示工具的行为特性:
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
memory_remember | false | false | false | false |
memory_recall | true | false | true | false |
memory_forget | false | true | true | false |
memory_search | true | false | true | false |
memory_list_namespaces | true | false | true | false |
memory_clear_namespace | false | true | false | false |
memory_stats | true | false | true | false |
- readOnlyHint: 是否为只读操作
- destructiveHint: 是否为破坏性操作
- idempotentHint: 是否为幂等操作
- openWorldHint: 是否与外部世界交互
资料来源:server.py:95-170
3. 数据存储架构
3.1 存储目录结构
数据默认存储在用户家目录下的 .agent-memory 文件夹中:
~/.agent-memory/
├── {namespace}.json # 每个命名空间一个文件
└── _meta.json # 全局元数据
| 常量 | 值 | 说明 |
|---|---|---|
DEFAULT_NAMESPACE | "default" | 默认命名空间名称 |
STORAGE_DIR | Path.home() / ".agent-memory" | 存储根目录 |
META_FILE | "_meta.json" | 元数据文件名 |
CHARACTER_LIMIT | 25,000 | 单次响应字符限制 |
资料来源:server.py:52-59
3.2 文件命名空间隔离
命名空间文件名经过安全处理,防止目录遍历攻击:
def _namespace_path(namespace: str) -> Path:
"""Return the full path for a namespace JSON file."""
# Sanitize the namespace so it can't escape the directory.
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
return STORAGE_DIR / f"{safe}.json"
资料来源:server.py:69-76
3.3 内存条目结构
每个内存条目(Entry)包含以下字段:
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 唯一键标识符 |
value | string | 存储的值 |
created_at | ISO 8601 时间戳 | 创建时间 |
accessed_at | ISO 8601 时间戳 | 最后访问时间 |
expires_at | ISO 8601 时间戳 | TTL 过期时间(可选) |
access_count | integer | 访问计数 |
资料来源:server.py:82-100
3.4 元数据文件结构
_meta.json 存储全局统计信息:
{
"total_entries": 156,
"namespace_count": 5,
"last_updated": "2026-05-12T15:00:00Z"
}
4. 并发控制机制
4.1 文件锁机制
系统使用 fcntl.flock() 实现进程级别的文件锁,确保多代理并发访问的安全性:
@contextmanager
def _locked(namespace: Optional[str] = None) -> Iterator[None]:
"""Context manager for file-level locking."""
if namespace:
path = _namespace_path(namespace)
with open(path, "a+") as fh:
fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
try:
yield
finally:
fcntl.flock(fh.fileno(), fcntl.LOCK_UN)
else:
# Lock the meta file for global operations
with open(_meta_path(), "a+") as fh:
fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
try:
yield
finally:
fcntl.flock(fh.fileno(), fcntl.LOCK_UN)
资料来源:server.py:117-137
4.2 锁粒度设计
| 操作类型 | 锁范围 | 说明 |
|---|---|---|
| 单命名空间操作 | 命名空间文件锁 | 仅锁定特定命名空间 |
| 全局统计操作 | 元数据文件锁 | 锁定 _meta.json |
| 跨命名空间操作 | 无锁(读操作) | 使用懒加载避免死锁 |
graph TD
A[请求进入] --> B{操作类型?}
B -->|单命名空间| C[锁定 namespace.json]
B -->|全局统计| D[锁定 _meta.json]
B -->|跨命名空间搜索| E[遍历+无锁读]
C --> F[执行操作]
D --> F
E --> F
F --> G[释放锁]
G --> H[返回结果]5. 业务逻辑层
5.1 核心功能模块
| 模块 | 功能 | 文件路径 |
|---|---|---|
_ensure_storage() | 确保存储目录存在 | server.py |
_namespace_path() | 生成命名空间文件路径 | server.py |
_read_namespace() | 读取命名空间数据 | server.py |
_write_namespace() | 写入命名空间数据 | server.py |
_is_expired() | 检查 TTL 是否过期 | server.py |
_format_response() | 格式化响应输出 | server.py |
_recalc_meta() | 重新计算元数据 | server.py |
5.2 工具实现流程
#### memory_remember 流程
graph TD
A[memory_remember 调用] --> B[验证 key 和 value]
B --> C{命名空间存在?}
C -->|否| D[自动创建命名空间]
C -->|是| E[获取写锁]
D --> E
E --> F[构建新条目]
F --> G[追加/更新到数组]
G --> H[写入 JSON 文件]
H --> I[释放锁]
I --> J[返回成功响应]资料来源:server.py:140-200
#### memory_recall 流程
graph TD
A[memory_recall 调用] --> B[获取读锁]
B --> C[读取命名空间 JSON]
C --> D[查找指定 key]
D --> E{条目存在?}
E -->|否| F[返回错误]
E -->|是| G{TTL 已过期?}
G -->|是| H[懒删除并返回错误]
G -->|否| I[更新 accessed_at 和 access_count]
I --> J[写入文件]
J --> K[释放锁]
K --> L[返回完整条目]资料来源:server.py:200-260
5.3 TTL 管理机制
系统采用懒过期策略,只在访问时检查 TTL:
def _is_expired(entry: Dict[str, Any]) -> bool:
"""Check if an entry has expired based on its TTL."""
if "expires_at" not in entry or entry["expires_at"] is None:
return False
expires = datetime.fromisoformat(entry["expires_at"])
return datetime.now(timezone.utc) > expires
资料来源:server.py:103-110
| 策略 | 说明 |
|---|---|
| 写入时设置 | 创建条目时指定 expires_at |
| 访问时检查 | recall 操作触发过期检查 |
| 懒删除 | 过期条目在被访问时删除,不主动清理 |
5.4 搜索机制
def _search_entries(entries: List[Dict], query: str, limit: int) -> List[Dict]:
"""Search entries by keyword substring in keys and values."""
results = []
for entry in entries:
if _is_expired(entry):
continue
if query.lower() in entry["key"].lower() or query.lower() in entry["value"].lower():
results.append(entry)
results.sort(key=lambda e: e.get("access_count", 0), reverse=True)
return results[:limit]
资料来源:server.py:110-125
搜索特性:
- 子字符串匹配:支持关键词部分匹配
- 大小写不敏感:自动转换为小写比较
- 跨键值搜索:同时搜索 key 和 value 字段
- 访问频率排序:按 access_count 降序返回结果
6. 响应格式化系统
6.1 格式类型
系统支持两种响应格式,通过 format 参数切换:
| 格式 | 说明 | Content-Type |
|---|---|---|
markdown | 人类可读的 Markdown 格式(默认) | text/markdown |
json | 程序可读的 JSON 格式 | application/json |
6.2 Markdown 格式化示例
def _format_response(result: Dict[str, Any], fmt: Optional[str] = None) -> str:
if fmt == "json":
return json.dumps(result, indent=2)
# Markdown (default)
lines = []
status = result.get("status", "ok")
if status == "error":
lines.append(f"## ❌ Error")
lines.append(f"**{result.get('error', 'Unknown error')}**")
else:
lines.append(f"## ✅ Success")
# ... 格式化其他字段
return "\n".join(lines)
资料来源:server.py:250-290
7. 入口点设计
7.1 主程序流程
async def main() -> None:
_ensure_storage() # 确保存储目录存在
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options(),
)
if __name__ == "__main__":
asyncio.run(main())
资料来源:server.py:310-325
7.2 启动流程图
sequenceDiagram
participant C as MCP 客户端
participant S as Agent Memory MCP
participant FS as 文件系统
C->>S: 启动进程
S->>FS: 创建 ~/.agent-memory/ 目录
FS-->>S: 目录就绪
S->>C: STDIO 服务就绪
C->>S: JSON-RPC 请求
S->>S: 处理工具调用
S->>FS: 读写 JSON 文件
S-->>C: JSON-RPC 响应8. 错误处理机制
8.1 错误响应结构
def _error(message: str, fmt: Optional[str] = None) -> str:
result = {"status": "error", "error": message, "isError": True}
return _format_response(result, fmt)
8.2 异常捕获
@server.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]) -> CallToolResult:
try:
# 工具执行逻辑
...
except Exception as exc:
err_text = _error(f"Internal error in {name}: {exc}", fmt)
return CallToolResult(
content=[TextContent(type="text", text=err_text)],
isError=True,
)
资料来源:server.py:225-237
8.3 错误类型
| 错误场景 | HTTP 类比状态码 | 说明 |
|---|---|---|
| Key 不存在 | 404 | 尝试访问不存在的 key |
| 命名空间错误 | 400 | 无效的命名空间名称 |
| 内部错误 | 500 | 文件系统或处理异常 |
9. 依赖架构
9.1 外部依赖
mcp>=1.0.0
系统仅依赖 MCP SDK,所有其他功能均使用 Python 标准库实现。
9.2 标准库使用
| 模块 | 用途 |
|---|---|
asyncio | 异步 I/O 支持 |
fcntl | 文件锁实现 |
json | 数据序列化 |
pathlib | 跨平台路径处理 |
re | 命名空间名称验证 |
datetime | 时间戳处理 |
资料来源:server.py:10-28
10. 配置常量汇总
| 常量 | 值 | 说明 |
|---|---|---|
CHARACTER_LIMIT | 25,000 | 响应字符数上限 |
DEFAULT_NAMESPACE | "default" | 默认命名空间 |
STORAGE_DIR | ~/.agent-memory/ | 存储根目录 |
META_FILE | "_meta.json" | 元数据文件名 |
资料来源:server.py:52-59
11. 架构优势
| 特性 | 实现方式 | 优势 |
|---|---|---|
| 本地优先 | JSON 文件存储 | 无需网络,数据本地化 |
| 零依赖 | 仅使用标准库 | 部署简单,兼容性强 |
| 并发安全 | fcntl 文件锁 | 多进程安全访问 |
| 命名隔离 | 文件级命名空间 | 避免命名冲突 |
| 幂等操作 | 注解声明 | 便于 MCP 客户端优化 |
12. 扩展方向
当前架构支持以下潜在扩展:
- 压缩存储:对 JSON 文件进行 gzip 压缩
- 索引优化:为高频查询字段建立索引
- TTL 后台清理:定时任务主动清理过期条目
- 审计日志:记录所有操作的详细日志
- 加密存储:对敏感数据进行加密
资料来源:[server.py:1-50]()
核心功能详解
Agent Memory MCP 是一个基于 Model Context Protocol (MCP) 的持久化键值存储系统,专为 AI 代理设计。该项目由 Nous Research 开发,采用 MIT 开源许可证,旨在解决 AI 代理在会话之间丢失所有上下文的问题。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
Agent Memory MCP 是一个基于 Model Context Protocol (MCP) 的持久化键值存储系统,专为 AI 代理设计。该项目由 Nous Research 开发,采用 MIT 开源许可证,旨在解决 AI 代理在会话之间丢失所有上下文的问题。
核心价值主张:赋予 AI 代理持久化、可搜索的记忆能力,使其能够在会话重启、崩溃和上下文窗口限制中存活下来。
资料来源:README.md
系统架构
整体架构图
graph TD
A[AI 代理<br/>Claude/GPT/Codex] --> B[MCP 协议<br/>stdio JSON-RPC]
B --> C[Agent Memory MCP 服务器]
C --> D[键值存储引擎]
C --> E[TTL 管理器]
C --> F[搜索引擎<br/>子串匹配]
D --> G[~/.agent-memory/]
E --> G
F --> G
G --> H[{namespace}.json]
G --> I[_meta.json]核心组件
| 组件 | 职责 | 实现方式 |
|---|---|---|
| MCP Server | 处理 MCP 协议通信 | mcp.server.Server |
| KV Store Engine | 键值存储读写 | JSON 文件操作 |
| TTL Manager | 过期时间管理 | 懒清理机制 |
| Search Engine | 跨命名空间搜索 | 子串匹配 + 访问计数排序 |
| File Locking | 并发安全 | fcntl.flock() POSIX 文件锁 |
资料来源:server.py:1-50
核心工具详解
系统提供 7 个结构化工具,覆盖完整的内存管理生命周期。
资料来源:server.py:140-280
工具概览表
| 工具名称 | 功能描述 | 只读 | 破坏性 | 幂等性 |
|---|---|---|---|---|
memory_remember | 存储键值对 | ❌ | ❌ | ❌ |
memory_recall | 检索键值对 | ✅ | ❌ | ✅ |
memory_forget | 删除键值对 | ❌ | ✅ | ✅ |
memory_search | 关键词搜索 | ✅ | ❌ | ✅ |
memory_list_namespaces | 列出命名空间 | ✅ | ❌ | ✅ |
memory_clear_namespace | 清空命名空间 | ❌ | ✅ | ❌ |
memory_stats | 获取统计信息 | ✅ | ❌ | ✅ |
资料来源:server.py:220-280
资料来源:[README.md]()
存储工具详解
agent-memory-mcp 的存储工具是整个系统的核心模块,提供了基于 MCP(Model Context Protocol)的持久化键值存储能力。这些工具使 AI Agent 能够在不同会话之间保持记忆,支持命名空间隔离、TTL(Time-To-Live)自动过期、模糊搜索和并发安全访问。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
agent-memory-mcp 的存储工具是整个系统的核心模块,提供了基于 MCP(Model Context Protocol)的持久化键值存储能力。这些工具使 AI Agent 能够在不同会话之间保持记忆,支持命名空间隔离、TTL(Time-To-Live)自动过期、模糊搜索和并发安全访问。
存储系统采用本地 JSON 文件存储方案,数据持久化在 ~/.agent-memory/ 目录下,每个命名空间对应一个独立的 JSON 文件,配合元数据文件 _meta.json 记录全局统计信息。资料来源:server.py:1-30
架构设计
系统组件
┌─────────────────────────────────────────────────────────────┐
│ MCP 客户端 (AI Agent) │
│ remember / recall / forget / search / list / clear / stats │
└───────────────────────────┬─────────────────────────────────┘
│ MCP Protocol (stdio JSON-RPC)
┌───────────────────────────▼─────────────────────────────────┐
│ Agent Memory MCP Server │
│ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │
│ │ KV 存储 │ │ TTL 管理 │ │ 搜索引擎 │ │
│ │ 引擎 │ │ 处理器 │ │ (子字符串匹配) │ │
│ └──────┬─────┘ └─────┬──────┘ └─────────┬──────────┘ │
│ │ │ │ │
│ ┌──────▼───────────────▼───────────────────▼──────────┐ │
│ │ ~/.agent-memory/ │ │
│ │ {namespace}.json │ _meta.json │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
存储目录结构
| 文件 | 用途 | 描述 |
|---|---|---|
{namespace}.json | 命名空间数据 | 每个命名空间独立存储,包含内存条目数组 |
_meta.json | 全局元数据 | 记录总条目数、命名空间数量等全局统计 |
资料来源:server.py:47-50
存储工具清单
工具功能对照表
| 工具名称 | 功能描述 | 读取操作 | 写入操作 | 删除操作 |
|---|---|---|---|---|
memory_remember | 存储键值对(支持TTL) | ❌ | ✅ | ❌ |
memory_recall | 检索键值及元数据 | ✅ | ❌ | ❌ |
memory_forget | 删除指定键 | ❌ | ❌ | ✅ |
memory_search | 跨命名空间关键词搜索 | ✅ | ❌ | ❌ |
memory_list_namespaces | 列出所有命名空间 | ✅ | ❌ | ❌ |
memory_clear_namespace | 清空整个命名空间 | ❌ | ❌ | ✅ |
memory_stats | 获取全局存储统计 | ✅ | ❌ | ❌ |
核心 API 参数详解
1. memory_remember
存储一个新的键值对到指定命名空间,支持可选的 TTL 自动过期时间。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 内存条目的唯一标识符 |
value | string | ✅ | - | 要存储的实际内容 |
namespace | string | ❌ | "default" | 目标命名空间 |
ttl_seconds | integer | ❌ | null | 存活秒数,设置后自动过期 |
format | string | ❌ | "markdown" | 返回格式:"markdown" 或 "json" |
条目数据结构:
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T10:30:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 1
}
资料来源:server.py:54-59
2. memory_recall
根据键名检索存储的值,同时返回完整的访问元数据。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 要检索的键名 |
namespace | string | ❌ | "default" | 目标命名空间 |
format | string | ❌ | "markdown" | 返回格式 |
返回的元数据字段:
| 字段 | 类型 | 说明 |
|---|---|---|
value | string | 存储的实际值 |
created_at | string | 创建时间戳(ISO 8601) |
accessed_at | string | 最后访问时间戳 |
expires_at | string/null | TTL 过期时间(未设置则为 null) |
access_count | integer | 累计访问次数 |
每次调用 memory_recall 会自动更新 accessed_at 和 access_count,实现访问追踪功能。资料来源:server.py:63-67
3. memory_forget
永久删除指定的键值对。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 要删除的键名 |
namespace | string | ❌ | "default" | 目标命名空间 |
format | string | ❌ | "markdown" | 返回格式 |
工具注解:
| 注解 | 值 | 说明 |
|---|---|---|
readOnlyHint | false | 修改性操作 |
destructiveHint | true | 破坏性操作 |
idempotentHint | true | 重复执行结果一致 |
资料来源:server.py:73-83
4. memory_search
在所有命名空间或指定命名空间中搜索关键词,匹配键名和值的子字符串。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
query | string | ✅ | - | 搜索关键词或子字符串 |
namespace | string | ❌ | null | 限定搜索范围(为空则搜索全部) |
limit | integer | ❌ | 10 | 最大返回结果数 |
format | string | ❌ | "markdown" | 返回格式 |
搜索特性:
- 大小写不敏感:搜索
"User"可匹配"user"、"USER"等 - 子字符串匹配:搜索
"them"可匹配"theme"、"something"等 - 全字段匹配:同时匹配
key和value - 结果排序:按
access_count降序排列
搜索流程:
graph TD
A[输入搜索查询] --> B{指定 namespace?}
B -->|是| C[只扫描指定命名空间]
B -->|否| D[扫描所有命名空间 JSON 文件]
C --> E[遍历条目列表]
D --> E
E --> F{key 或 value 包含查询?<br/>大小写不敏感}
F -->|是| G[加入结果集]
F -->|否| H[跳过]
G --> I{access_count 高于当前结果?}
I -->|是| J[优先排序]
I -->|否| K[保持原位置]
J --> L{达到 limit?}
K --> L
L -->|否| E
L -->|是| M[返回排序结果]资料来源:server.py:88-110
5. memory_list_namespaces
列出所有已存在的命名空间及其条目统计。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
format | string | ❌ | "markdown" | 返回格式 |
返回数据:
| 字段 | 类型 | 说明 |
|---|---|---|
namespace | string | 命名空间名称 |
active_count | integer | 未过期的条目数 |
expired_count | integer | 已过期但未清理的条目数 |
工具注解:
| 注解 | 值 | 说明 |
|---|---|---|
readOnlyHint | true | 只读操作 |
destructiveHint | false | 非破坏性操作 |
openWorldHint | true | 可能访问外部数据源 |
资料来源:server.py:115-130
6. memory_clear_namespace
清空指定命名空间中的所有条目。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
namespace | string | ✅ | - | 要清空的命名空间 |
format | string | ❌ | "markdown" | 返回格式 |
警告: 此操作不可撤销,会永久删除该命名空间下的所有数据。
工具注解:
| 注解 | 值 | 说明 |
|---|---|---|
readOnlyHint | false | 修改性操作 |
destructiveHint | true | 破坏性操作 |
idempotentHint | true | 重复执行结果一致 |
openWorldHint | false | 仅本地操作 |
资料来源:server.py:135-154
7. memory_stats
获取全局存储统计信息。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
format | string | ❌ | "markdown" | 返回格式 |
返回的统计数据:
| 字段 | 类型 | 说明 |
|---|---|---|
total_entries | integer | 所有命名空间的条目总数(不含过期) |
namespace_count | integer | 命名空间总数 |
total_size | string | 存储目录大小(人类可读格式) |
oldest_entry | string | 最早条目的相对时间 |
newest_entry | string | 最新条目的相对时间 |
expired_entries | integer | 已过期条目数量 |
资料来源:server.py:159-178
存储机制详解
文件路径规范
STORAGE_DIR = Path.home() / ".agent-memory"
命名空间路径通过正则表达式进行安全化处理,防止目录遍历攻击:
def _namespace_path(namespace: str) -> Path:
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
return STORAGE_DIR / f"{safe}.json"
| 原始命名空间 | 安全化后 | 文件路径 |
|---|---|---|
user:preferences | user_preferences | ~/.agent-memory/user_preferences.json |
agent:code-reviewer | agent_code-reviewer | ~/.agent-memory/agent_code-reviewer.json |
../etc/passwd | .._etc_passwd | ~/.agent-memory/.._etc_passwd.json |
资料来源:server.py:63-69
TTL 过期机制
系统采用惰性过期检查策略,在以下时机检查并清理过期条目:
memory_recall- 访问时检查memory_search- 搜索时检查_read_namespace- 读取命名空间时检查
graph LR
A[读取条目] --> B{有 expires_at?}
B -->|是| C{当前时间 > expires_at?}
C -->|是| D[标记为过期<br/>返回 None]
C -->|否| E[正常返回]
B -->|否| E过期检查逻辑:
def _is_expired(entry: Dict[str, Any]) -> bool:
if not entry.get("expires_at"):
return False
return datetime.now(UTC) > datetime.fromisoformat(entry["expires_at"])
资料来源:server.py:115-119
并发控制
系统使用 fcntl.flock() 实现 POSIX 文件锁,确保多进程并发安全:
@contextmanager
def _locked(path: Path, exclusive: bool = True):
with path.open("a+") as fh:
lock_type = fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH
fcntl.flock(fh.fileno(), lock_type)
try:
yield fh
finally:
fcntl.flock(fh.fileno(), fcntl.LOCK_UN)
| 锁类型 | 应用场景 | 并发读 | 并发写 |
|---|---|---|---|
LOCK_EX (排他锁) | memory_remember、memory_forget、memory_clear_namespace | ❌ | ❌ |
LOCK_SH (共享锁) | memory_recall、memory_search、memory_list_namespaces、memory_stats | ✅ | ❌ |
资料来源:server.py:32-41
元数据管理
_meta.json 存储全局统计信息,由 _recalc_meta() 动态计算:
def _recalc_meta() -> None:
total = 0
namespace_count = 0
for p in STORAGE_DIR.glob("*.json"):
if p.stem == "_meta":
continue
namespace_count += 1
entries = _read_namespace(p.stem)
total += len([e for e in entries if not _is_expired(e)])
_write_meta({"total_entries": total, "namespace_count": namespace_count})
资料来源:server.py:195-204
使用示例
基本存储操作
# 存储用户偏好(永久)
await memory_remember(
key="user:theme",
value="dark",
namespace="preferences"
)
# 存储研究数据(7天过期)
await memory_remember(
key="competitor:pricing:stripe",
value="Stripe charges 2.9% + $0.30 per transaction",
namespace="research",
ttl_seconds=604800 # 7 days
)
跨会话记忆
# Session 1: 学习用户偏好
await memory_remember(
key="user:timezone",
value="America/Chicago",
namespace="preferences"
)
# Session 2 (days later): 立即回忆偏好
tz = await memory_recall("user:timezone", "preferences")
# 无需再次询问用户
搜索与清理
# 搜索所有相关研究
findings = await memory_search(
query="competitor pricing",
namespace="research"
)
# 清理旧数据
await memory_clear_namespace(namespace="agent:code-reviewer")
响应格式化
所有工具支持两种响应格式,通过 format 参数控制:
| 格式 | 适用场景 | 示例输出 |
|---|---|---|
"markdown" | 人类可读 | H2 标题、表格、加粗文本 |
"json" | 程序处理 | 结构化 JSON 对象 |
Markdown 格式响应结构:
## ✅ Success
**key:** user:theme
**value:** dark
**created_at:** 2026-05-12T10:30:00Z
**namespace:** preferences
JSON 格式响应结构:
{
"status": "ok",
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"namespace": "preferences"
}
资料来源:server.py:128-154
限制与配额
| 层级 | 价格 | 条目限制 | 命名空间限制 |
|---|---|---|---|
| Free | $0 | 1,000 条 | 5 个 |
| Pro | $19/月 | 无限 | 无限 |
存储大小超过限制时,系统返回警告信息但仍允许写入。资料来源:smithery.yaml:17-27
错误处理
| 错误类型 | HTTP 状态 | 说明 |
|---|---|---|
| 未知工具 | - | 返回 "Unknown tool: {name}" |
| 内部错误 | isError: true | 捕获异常并返回详细错误信息 |
| 命名空间为空 | - | 返回确认消息而非错误 |
except Exception as exc:
err_text = _error(f"Internal error in {name}: {exc}", fmt)
return CallToolResult(
content=[TextContent(type="text", text=err_text)],
isError=True,
)
资料来源:server.py:203-211
工具注解汇总
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
memory_remember | false | false | false | false |
memory_recall | true | false | true | false |
memory_forget | false | true | true | false |
memory_search | true | false | true | true |
memory_list_namespaces | true | false | true | true |
memory_clear_namespace | false | true | false | false |
memory_stats | true | false | true | false |
资料来源:server.py:83-178
扩展配置
MCP 客户端配置
Claude Desktop:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["/path/to/agent-memory-mcp/server.py"]
}
}
}
VS Code / Cursor:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["server.py"],
"cwd": "/path/to/agent-memory-mcp"
}
}
}
环境变量
系统当前无额外环境变量要求。数据目录通过 Path.home() / ".agent-memory" 自动确定。
资料来源:[server.py:47-50]()
查询工具详解
Agent Memory MCP 提供了一套完整的查询工具,用于在持久化内存存储中检索和搜索数据。这套查询工具的核心是 memorysearch(模糊搜索),辅以 memorylistnamespaces(命名空间列表)和 memorystats(存储统计)两个辅助工具。三者共同构成了一个层次化的查询体系,使用户和 AI Agent 能够高效地定位和管理记忆数据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
Agent Memory MCP 提供了一套完整的查询工具,用于在持久化内存存储中检索和搜索数据。这套查询工具的核心是 memory_search(模糊搜索),辅以 memory_list_namespaces(命名空间列表)和 memory_stats(存储统计)两个辅助工具。三者共同构成了一个层次化的查询体系,使用户和 AI Agent 能够高效地定位和管理记忆数据。
查询工具的设计遵循以下原则:
- 读操作为主:所有查询工具均标记为
readOnlyHint=True,不会修改底层数据 - 幂等性保障:重复执行相同查询将返回一致结果(
idempotentHint=True) - 格式灵活:支持 Markdown(人类可读)和 JSON(程序化处理)两种输出格式
资料来源:server.py:1-50
工具清单
| 工具名称 | 功能描述 | 只读 | 幂等 |
|---|---|---|---|
memory_search | 在所有命名空间中按关键词搜索记忆 | ✅ | ✅ |
memory_list_namespaces | 列出所有命名空间及其条目计数 | ✅ | ✅ |
memory_stats | 获取全局存储统计信息 | ✅ | ✅ |
资料来源:server.py:160-200
核心工具详解
1. memory_search(模糊搜索)
memory_search 是 Agent Memory MCP 中功能最强大的查询工具,支持跨命名空间的模糊匹配搜索。
#### 功能特性
- 跨命名空间搜索:默认情况下搜索所有命名空间,可通过
namespace参数限定范围 - 模糊匹配:同时匹配 key 和 value 中的子字符串
- 大小写不敏感:搜索不区分大小写
- 相关性排序:结果按访问次数(
access_count)降序排列,热门记忆优先返回
#### 参数定义
{
"query": {
"type": "string",
"description": "搜索关键词或子字符串",
"required": true
},
"namespace": {
"type": "string",
"description": "可选的命名空间限定。省略则搜索所有命名空间"
},
"limit": {
"type": "integer",
"description": "最大返回结果数(默认: 10)",
"default": 10
},
"format": {
"type": "string",
"enum": ["markdown", "json"],
"description": "响应格式(默认: markdown)"
}
}
资料来源:server.py:180-210
#### 实现逻辑
搜索功能的核心实现在 _search_namespace 辅助函数中:
def _search_namespace(
namespace: str,
query: str,
limit: int = 10,
) -> List[Dict[str, Any]]:
"""Search within a single namespace, returning top matches by access count."""
entries = _read_namespace(namespace)
# Filter: case-insensitive substring match on key OR value
matched = [
e for e in entries
if not _is_expired(e) and (
query.lower() in e["key"].lower() or
query.lower() in str(e.get("value", "")).lower()
)
]
# Sort by access_count descending
matched.sort(key=lambda e: e["access_count"], reverse=True)
return matched[:limit]
关键实现要点:
- 过期检查:使用
_is_expired()函数排除已过期的记忆条目 - 双重匹配:同时检查 key 和 value 是否包含查询字符串
- 排序策略:按
access_count降序排列,确保高频访问的记忆优先显示 - 结果限制:使用切片操作
[:limit]限制返回数量
资料来源:server.py:220-240
2. memory_list_namespaces(命名空间列表)
此工具用于获取系统中所有命名空间的概览信息,包括活跃条目数和过期条目数。
#### 参数定义
{
"format": {
"type": "string",
"enum": ["markdown", "json"],
"description": "响应格式(默认: markdown)"
}
}
#### 返回数据结构
{
"namespaces": [
{
"name": "research",
"active_entries": 42,
"expired_entries": 3
},
{
"name": "preferences",
"active_entries": 15,
"expired_entries": 0
}
]
}
#### 实现逻辑
def memory_list_namespaces(fmt: Optional[str] = None) -> str:
"""List all namespaces with entry counts."""
namespaces = []
for p in STORAGE_DIR.glob("*.json"):
if p.stem == "_meta":
continue
entries = _read_namespace(p.stem)
active = [e for e in entries if not _is_expired(e)]
namespaces.append({
"name": p.stem,
"active_entries": len(active),
"expired_entries": len(entries) - len(active),
})
return _success({"namespaces": namespaces}, fmt)
资料来源:server.py:245-260
3. memory_stats(存储统计)
此工具提供全局存储的统计信息,帮助用户了解存储使用情况和配额限制。
#### 参数定义
{
"format": {
"type": "string",
"enum": ["markdown", "json"],
"description": "响应格式(默认: markdown)"
}
}
#### 返回数据示例(Markdown 格式)
## 存储统计
**总条目数**: 1,247
**存储大小**: 2.3 MB
**命名空间数**: 5
**最早条目**: 2026-04-15(27天前)
**最新条目**: 刚刚
**已过期条目**: 12
#### 实现逻辑
def memory_stats(fmt: Optional[str] = None) -> str:
"""Get storage statistics."""
_recalc_meta() # 重新计算全局元数据
meta = _read_meta()
# 计算存储大小
total_size = sum(p.stat().st_size for p in STORAGE_DIR.glob("*.json"))
# 查找最早和最新条目
oldest, newest = None, None
for p in STORAGE_DIR.glob("*.json"):
if p.stem == "_meta":
continue
entries = _read_namespace(p.stem)
for e in entries:
ts = e.get("created_at")
if ts:
if not oldest or ts < oldest:
oldest = ts
if not newest or ts > newest:
newest = ts
return _success({
"total_entries": meta.get("total_entries", 0),
"storage_size": _format_size(total_size),
"namespace_count": meta.get("namespace_count", 0),
"oldest_entry": oldest,
"newest_entry": newest,
"expired_entries": 0,
}, fmt)
资料来源:server.py:260-290
工具注解(Tool Annotations)
MCP 协议支持为每个工具提供语义注解,帮助客户端理解工具的行为特性:
| 注解字段 | memory_search | memory_list_namespaces | memory_stats |
|---|---|---|---|
readOnlyHint | true | true | true |
destructiveHint | false | false | false |
idempotentHint | true | true | true |
openWorldHint | true | true | true |
注解含义说明:
readOnlyHint:表示该工具不会修改服务器状态destructiveHint:表示该工具不会删除或破坏数据idempotentHint:表示重复执行不会产生额外副作用openWorldHint:表示该工具可能涉及外部世界交互(搜索功能搜索所有命名空间)
资料来源:server.py:195-200
架构流程图
查询请求处理流程
graph TD
A[MCP 客户端请求] --> B{memory_search?}
A --> C{memory_list_namespaces?}
A --> D{memory_stats?}
B --> E[解析 query 参数]
E --> F{namespace 参数存在?}
F -->|是| G[搜索指定命名空间]
F -->|否| H[遍历所有命名空间]
G --> I[过滤过期条目]
H --> I
I --> J[按 access_count 排序]
J --> K[限制返回数量]
K --> L[格式化响应]
C --> M[扫描 STORAGE_DIR]
M --> N[读取每个命名空间文件]
N --> O[统计活跃/过期条目]
O --> L
D --> P[重新计算全局元数据]
P --> Q[计算存储大小]
Q --> R[查找最老/最新条目]
R --> L
L --> S[返回 Markdown 或 JSON]
subgraph "存储层 ~/.agent-memory/"
T["{namespace}.json"]
U["_meta.json"]
end
G --> T
H --> T
N --> T
P --> U
Q --> T
R --> T数据存储结构
graph LR
A["~/.agent-memory/"] --> B["{namespace}.json"]
A --> C["_meta.json"]
B --> D["entries[]"]
D --> E["key"]
D --> F["value"]
D --> G["created_at"]
D --> H["accessed_at"]
D --> I["expires_at"]
D --> J["access_count"]
C --> K["total_entries"]
C --> L["namespace_count"]使用场景示例
跨会话上下文恢复
# Agent 在首次会话中存储用户偏好
await memory_remember(
key="user:timezone",
value="America/Chicago",
namespace="preferences"
)
# 后续会话中快速查询用户时区
tz = await memory_search(
query="timezone",
namespace="preferences"
)
研究积累与检索
# 持续积累研究数据
await memory_remember(
key="competitor:acme:pricing",
value="Acme Pro: $49/mo, Enterprise: $199/mo",
namespace="research"
)
# 在所有命名空间中搜索竞争对手相关信息
results = await memory_search(
query="competitor",
limit=20
)
存储健康检查
# 查看存储使用情况
stats = await memory_stats()
# 检查命名空间分布
namespaces = await memory_list_namespaces()
# 定位过期数据
for ns in namespaces["namespaces"]:
if ns["expired_entries"] > 100:
print(f"命名空间 {ns['name']} 有 {ns['expired_entries']} 个过期条目")
响应格式化
所有查询工具支持两种输出格式,通过 format 参数指定:
Markdown 格式(默认)
## ✅ Success
**key:** user:timezone
**value:** America/Chicago
**created_at:** 2026-05-01T10:00:00Z
**accessed_at:** 2026-05-12T14:22:00Z
**access_count:** 47
JSON 格式
{
"status": "ok",
"key": "user:timezone",
"value": "America/Chicago",
"created_at": "2026-05-01T10:00:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"access_count": 47
}
格式化逻辑统一由 _format_response 函数处理:
def _format_response(result: Dict[str, Any], fmt: Optional[str] = None) -> str:
"""Format a result dictionary as either JSON or Markdown."""
if fmt == "json":
return json.dumps(result, indent=2)
# Markdown (default)
lines = []
# ... 构建 Markdown 格式字符串
return "\n".join(lines)
资料来源:server.py:100-140
错误处理
查询工具的错误处理遵循统一模式:
try:
if name == "memory_search":
text = memory_search(**arguments, fmt=fmt)
elif name == "memory_list_namespaces":
text = memory_list_namespaces(fmt=fmt)
elif name == "memory_stats":
text = memory_stats(fmt=fmt)
# ...
except Exception as exc:
err_text = _error(f"Internal error in {name}: {exc}", fmt)
return CallToolResult(
content=[TextContent(type="text", text=err_text)],
isError=True,
)
错误响应示例:
{
"status": "error",
"error": "Internal error in memory_search: list index out of range",
"isError": true
}
资料来源:server.py:260-280
线程安全性
查询工具虽然都是只读操作,但在并发环境下仍需考虑数据一致性。系统使用 fcntl.flock() 实现文件级锁:
@contextmanager
def _locked(path: Path) -> Any:
"""Context manager for file locking with fcntl.flock."""
with path.open("a") as fh:
fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
try:
yield fh
finally:
fcntl.flock(fh.fileno(), fcntl.LOCK_UN)
所有涉及文件读写的操作(_read_namespace、_write_namespace 等)都通过此上下文管理器保护,确保在多个 Agent 进程并发访问时不会产生数据竞争。
资料来源:server.py:60-80
配额与限制
根据 smithery.yaml 配置,查询工具受以下配额限制:
| 套餐 | 价格 | 条目上限 | 命名空间上限 |
|---|---|---|---|
| Free | $0 | 1,000 条 | 5 个 |
| Pro | $19/月 | 无限 | 无限 |
超出免费配额后,系统仍可正常执行查询操作,但建议用户升级至 Pro 套餐以获得无限存储能力。
资料来源:smithery.yaml:20-35
总结
Agent Memory MCP 的查询工具套件为 AI Agent 提供了一个高效、可靠的记忆检索系统:
memory_search:核心搜索工具,支持跨命名空间模糊匹配和相关性排序memory_list_namespaces:命名空间管理工具,帮助用户了解数据分布memory_stats:系统健康检查工具,提供存储使用统计
这三个工具协同工作,使 Agent 能够在任意会话中快速定位历史记忆,实现真正的持久化上下文管理。所有工具均遵循只读、幂等的设计原则,确保在复杂的多 Agent 环境中安全可靠运行。
资料来源:[server.py:1-50]()
数据存储机制
Agent Memory MCP 的数据存储机制是一个基于文件系统的持久化键值存储系统,专为 AI 代理设计。该系统将所有数据存储在用户本地目录 ~/.agent-memory/ 中,以 JSON 文件格式保存,支持命名空间隔离、时间 TTL(生存时间)管理、访问计数追踪和模糊搜索功能。资料来源:[server.py:27-29]()
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
Agent Memory MCP 的数据存储机制是一个基于文件系统的持久化键值存储系统,专为 AI 代理设计。该系统将所有数据存储在用户本地目录 ~/.agent-memory/ 中,以 JSON 文件格式保存,支持命名空间隔离、时间 TTL(生存时间)管理、访问计数追踪和模糊搜索功能。资料来源:server.py:27-29
graph TD
A[AI Agent] -->|MCP Protocol| B[Agent Memory MCP Server]
B --> C[KV Store Engine]
B --> D[TTL Manager]
B --> E[Search Engine]
C --> F[~/.agent-memory/]
D --> F
E --> F
F --> G[{namespace}.json]
F --> H[_meta.json]存储目录结构
目录位置
默认存储目录位于用户主目录下的隐藏文件夹 .agent-memory/。系统启动时会自动创建该目录,无需手动配置。
| 属性 | 值 |
|---|---|
| 路径 | ~/.agent-memory/ |
| 类型 | 用户主目录下的隐藏文件夹 |
| 创建时机 | 服务首次启动时 |
| 权限 | 继承系统默认权限 |
资料来源:server.py:30
STORAGE_DIR = Path.home() / ".agent-memory"
目录结构设计
~/.agent-memory/
├── _meta.json # 全局元数据统计文件
├── default.json # 默认命名空间数据
├── {namespace1}.json # 各命名空间独立存储
├── {namespace2}.json
└── {namespaceN}.json
每个命名空间对应一个独立的 JSON 文件,全局统计信息存储在 _meta.json 中。
资料来源:server.py:32
META_FILE = "_meta.json"
命名空间管理
命名空间概念
命名空间(Namespace)用于隔离不同用途或不同代理的内存数据。这种设计允许:
- 按项目分离数据
- 按用户分离数据
- 按功能域分离数据
- 实现数据完全独立的存储空间
资料来源:README.md:72-74
命名空间路径解析
系统通过 _namespace_path() 函数将命名空间名称转换为安全的文件路径。命名空间名称会经过正则表达式处理,移除所有非法字符。
def _namespace_path(namespace: str) -> Path:
"""Return the full path for a namespace JSON file."""
# Sanitize the namespace so it can't escape the directory.
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
return STORAGE_DIR / f"{safe}.json"
关键安全措施:
- 只允许字母、数字、下划线、点和连字符
- 所有非法字符替换为下划线
- 空名称回退到默认命名空间
- 文件路径无法逃逸到目录之外
资料来源:server.py:42-51
默认命名空间
如果未指定命名空间,系统使用 default 作为默认值。
DEFAULT_NAMESPACE = "default"
资料来源:server.py:31
数据模型
内存条目结构
每个内存条目(Entry)是一个包含以下字段的 JSON 对象:
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
| 字段 | 类型 | 描述 |
|---|---|---|
key | string | 唯一键标识符 |
value | string | 存储的值/内容 |
created_at | ISO 8601 | 创建时间戳 |
accessed_at | ISO 8601 | 最后访问时间 |
expires_at | ISO 8601 或 null | TTL 过期时间(可选) |
access_count | integer | 访问次数计数器 |
资料来源:README.md:85-93
TTL 过期机制
过期时间(TTL)通过 expires_at 字段实现。当设置 ttl_seconds 参数时,系统计算过期时间戳:
if ttl_seconds:
entry["expires_at"] = datetime.now(timezone.utc).timestamp() + ttl_seconds
else:
entry["expires_at"] = None
过期检查采用惰性清理策略:在 memory_recall 和 memory_search 操作时,系统检查条目是否过期并自动移除。
def _is_expired(entry: Dict[str, Any]) -> bool:
"""检查条目是否已过期"""
if entry.get("expires_at") is None:
return False
return datetime.now(timezone.utc).timestamp() > entry["expires_at"]
资料来源:server.py:108-114
文件操作与并发控制
文件锁定机制
系统使用 POSIX 文件锁 fcntl.flock() 实现线程安全的并发访问。这是实现多进程安全的关键机制。
@contextmanager
def _file_lock(path: Path, lock_type: int = fcntl.LOCK_EX):
"""文件锁上下文管理器,支持读锁和写锁"""
lock_path = path.with_suffix(".lock")
with lock_path.open("w") as lock_file:
try:
fcntl.flock(lock_file.fileno(), lock_type)
yield
finally:
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
| 锁类型 | 用途 | 并发读 | 并发写 |
|---|---|---|---|
LOCK_EX (排他锁) | 写入操作 | ❌ | ❌ |
LOCK_SH (共享锁) | 读取操作 | ✅ | ❌ |
资料来源:server.py:60-74
读写操作实现
读取命名空间数据:
def _read_namespace(namespace: str) -> List[Dict[str, Any]]:
"""读取命名空间的所有条目"""
path = _namespace_path(namespace)
if not path.exists():
return []
with _file_lock(path, fcntl.LOCK_SH):
with path.open("r", encoding="utf-8") as f:
return json.load(f)
写入命名空间数据:
def _write_namespace(namespace: str, entries: List[Dict[str, Any]]) -> None:
"""写入命名空间的所有条目"""
path = _namespace_path(namespace)
with _file_lock(path, fcntl.LOCK_EX):
with path.open("w", encoding="utf-8") as f:
json.dump(entries, f, ensure_ascii=False, indent=2)
资料来源:server.py:76-90
锁定文件结构
对于每个命名空间文件,系统会创建对应的锁文件:
~/.agent-memory/
├── _meta.json
├── _meta.json.lock # 元数据文件锁
├── default.json
├── default.json.lock # 默认命名空间锁
├── research.json
└── research.json.lock # 研究命名空间锁
元数据管理
全局元数据文件
_meta.json 文件存储全局统计信息:
{
"total_entries": 150,
"namespace_count": 5,
"oldest_entry": "2026-04-15T10:00:00Z",
"newest_entry": "2026-06-12T14:30:00Z"
}
元数据计算
系统通过 _recalc_meta() 函数扫描所有命名空间文件来重新计算全局统计:
def _recalc_meta() -> None:
"""Recompute global metadata by scanning all namespaces."""
total = 0
namespace_count = 0
for p in STORAGE_DIR.glob("*.json"):
if p.stem == "_meta":
continue
namespace_count += 1
entries = _read_namespace(p.stem)
total += len([e for e in entries if not _is_expired(e)])
_write_meta({"total_entries": total, "namespace_count": namespace_count})
该函数在 memory_stats 操作时被调用。
资料来源:server.py:167-178
存储操作实现
写入操作 (memory_remember)
graph TD
A[memory_remember 调用] --> B{key 是否存在?}
B -->|存在| C[更新 existing_entry]
B -->|不存在| D[创建 new_entry]
C --> E[更新 accessed_at]
D --> E
E --> F[access_count 递增]
F --> G[写入文件锁]
G --> H[JSON 序列化]
H --> I[写入 {namespace}.json]
I --> J[释放文件锁]
J --> K[返回成功响应]资料来源:server.py:180-230
读取操作 (memory_recall)
graph TD
A[memory_recall 调用] --> B[获取文件锁 SH]
B --> C[读取 JSON]
C --> D{条目存在?}
D -->|否| E[返回错误]
D -->|是| F{条目过期?}
F -->|是| G[删除过期条目]
F -->|否| H[更新 accessed_at]
H --> I[access_count 递增]
G --> J[写入更新]
I --> J
J --> K[释放文件锁]
K --> L[返回记忆数据]资料来源:server.py:232-285
搜索操作 (memory_search)
搜索功能支持模糊匹配,同时搜索键名和值内容:
query_lower = query.lower()
for entry in entries:
if query_lower in entry["key"].lower() or query_lower in entry["value"].lower():
results.append(entry)
results.sort(key=lambda e: e.get("access_count", 0), reverse=True)
搜索特性:
- 大小写不敏感:所有匹配在比较前转换为小写
- 子串匹配:支持关键词子串搜索
- 跨键值搜索:同时匹配键名和值内容
- 访问频率排序:结果按访问次数降序排列
资料来源:server.py:287-345
存储限制与配额
层级限制
| 层级 | 价格 | 条目限制 | 命名空间限制 |
|---|---|---|---|
| Free(免费) | $0 | 1,000 条 | 5 个 |
| Pro(专业) | $19/月 | 无限 | 无限 |
资料来源:README.md:106-111
响应大小限制
系统设置了字符输出限制,防止超大响应导致协议问题:
CHARACTER_LIMIT = 25_000
超过限制的响应会被截断:
def _truncate(text: str, limit: int = CHARACTER_LIMIT) -> str:
"""Truncate text if it exceeds the character limit."""
if len(text) > limit:
return text[: limit - 3] + "..."
return text
资料来源:server.py:35, server.py:143-146
依赖关系
Python 标准库依赖
项目仅依赖 Python 标准库和 MCP SDK:
| 模块 | 用途 |
|---|---|
asyncio | 异步运行时 |
fcntl | POSIX 文件锁定 |
json | JSON 序列化/反序列化 |
pathlib | 跨平台路径操作 |
datetime | 时间戳处理 |
re | 命名空间名称规范化 |
资料来源:server.py:1-18
MCP SDK 依赖
# requirements.txt
mcp>=1.0.0
资料来源:requirements.txt
设计原则
本地优先
所有数据存储在用户本地机器上,不依赖云服务或外部 API。这确保了:
- 零延迟:本地文件 I/O 速度极快
- 数据主权:用户完全掌控自己的数据
- 离线可用:无需网络连接即可工作
- 隐私保护:数据不会离开用户的设备
资料来源:README.md:99-101
简洁性
采用类 Redis 的键值存储设计,而非复杂的向量数据库。这符合 AI 代理的实际需求——记住关键信息,而非大规模语义搜索。
资料来源:README.md:97-99
故障处理
错误响应格式
所有错误以统一格式返回:
{
"status": "error",
"error": "具体错误信息",
"isError": true
}
错误响应支持 Markdown 和 JSON 两种格式,由调用方指定:
def _error(message: str, fmt: Optional[str] = None) -> str:
result = {"status": "error", "error": message, "isError": True}
return _format_response(result, fmt)
资料来源:server.py:151-153
异常捕获
工具调用层统一捕获所有异常并返回结构化错误:
try:
# ... 执行工具逻辑
except Exception as exc:
err_text = _error(f"Internal error in {name}: {exc}", fmt)
return CallToolResult(
content=[TextContent(type="text", text=err_text)],
isError=True,
)
资料来源:server.py:360-368
资料来源:[server.py:30]()
使用场景与最佳实践
本文档详细说明 Agent Memory MCP 的典型使用场景及对应的最佳实践指导,帮助开发者充分利用持久化内存系统的能力。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
核心使用场景概述
Agent Memory MCP 设计用于解决 AI Agent 在会话间的上下文丢失问题。当 Agent 在不同会话间切换时,所有对话上下文都会重置为零。Agent Memory MCP 通过提供持久化、可搜索的内存存储,使 Agent 能够记住关键信息、用户偏好和中间计算结果。
资料来源:README.md
场景一:跨会话用户偏好管理
问题描述
用户在首次对话中提供的偏好信息(如时区、货币、语言等)在会话结束时会被遗忘,导致 Agent 在后续会话中需要重复询问同样的问题,浪费 Token 成本。
解决方案
利用 memory_remember 存储用户偏好,利用 memory_recall 在后续会话中快速检索。
实现示例
# 会话 1:Agent 学习用户偏好
await memory_remember(
key="user:timezone",
value="America/Chicago",
namespace="preferences"
)
await memory_remember(
key="user:currency",
value="USD",
namespace="preferences"
)
# 会话 2(数天后):Agent 立即回忆偏好
tz = await memory_recall(key="user:timezone", namespace="preferences")
# → "America/Chicago"
# 无需再次询问用户
资料来源:README.md:1-100
时效性考虑
对于用户偏好,建议使用较长的 TTL 或永久存储。关键代码逻辑如下:
# 使用 30 天 TTL 存储用户偏好
await memory_remember(
key="user:theme",
value="dark",
namespace="preferences",
ttl_seconds=2592000 # 30 天
)
资料来源:server.py:200-250
场景二:研究积累代理
问题描述
Agent 在执行研究任务时,需要逐步积累发现的信息。传统方式下,这些信息无法跨会话保留,导致重复研究和上下文窗口浪费。
解决方案
创建独立的研究命名空间,系统化存储发现成果。
实现示例
# Agent 存储研究发现的竞品信息
await memory_remember(
key="competitor:acme:api_pricing",
value="Acme API Pro: $49/mo for 10k calls. Enterprise: $199/mo. No free tier.",
namespace="research",
ttl_seconds=86400 * 7 # 保留 7 天
)
# Agent 存储另一个竞品的定价信息
await memory_remember(
key="competitor:stripe:pricing",
value="Stripe charges 2.9% + $0.30 per transaction for US cards",
namespace="research"
)
# 后续:搜索所有竞品相关内容
findings = await memory_search(
query="competitor pricing",
namespace="research"
)
资料来源:README.md:50-80
搜索机制说明
memory_search 执行不区分大小写的子字符串匹配,同时搜索键名和值内容。返回结果按访问次数排序,高频访问的条目优先级更高。
# 模糊搜索示例
await memory_search(
query="stripe",
namespace="research"
)
# 可匹配 key="competitor:stripe:pricing" 或 value 包含 "stripe" 的条目
场景三:Agent 工作区(Scratchpad)
问题描述
复杂任务需要 Agent 在执行过程中记录中间状态、分步骤待办事项或调试信息。这些信息仅在当前任务周期内有用。
解决方案
使用专门的任务命名空间作为工作区,支持读写和清理。
实现示例
# Agent 使用内存作为工作区
await memory_remember(
key="scratch:task:refactor-auth",
value="Step 1: Extract auth middleware. Step 2: Add token refresh. Step 3: Update tests.",
namespace="agent:code-reviewer"
)
# 检索当前任务状态
state = await memory_recall(
key="scratch:task:refactor-auth",
namespace="agent:code-reviewer"
)
# 定期清理已完成的任务数据
await memory_clear_namespace(namespace="agent:code-reviewer")
# → "Cleared 156 entries from 'agent:code-reviewer'"
资料来源:README.md:80-100
命名空间设计建议
| 命名空间模式 | 用途 | TTL 建议 |
|---|---|---|
preferences | 用户偏好 | 长 TTL 或永久 |
research | 研究发现 | 中等 TTL |
agent:{agent-id} | Agent 工作区 | 任务周期 |
session:{session-id} | 会话临时数据 | 会话结束清理 |
场景四:周期性数据清理
问题描述
长期运行的 Agent 会积累大量过期或无效的数据,影响存储效率和检索性能。
解决方案
利用 memory_clear_namespace 定期清理命名空间,或使用 TTL 自动过期。
最佳实践
# Agent 清理旧的研究数据
await memory_clear_namespace(namespace="agent:code-reviewer")
# → "Cleared 156 entries from 'agent:code-reviewer'"
# 检查当前存储统计
stats = await memory_stats()
# 返回:总条目数、命名空间数、最旧/最新条目、过期条目数
资料来源:README.md:95-100
工具注解与语义
Agent Memory MCP 为每个工具提供语义注解,帮助 Agent 理解工具行为:
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
memory_remember | false | false | false | false |
memory_recall | true | false | true | false |
memory_forget | false | true | true | false |
memory_search | true | false | true | false |
memory_list_namespaces | true | false | true | false |
memory_clear_namespace | false | true | false | false |
memory_stats | true | false | true | false |
注解含义
- readOnlyHint: 工具是否仅读取数据
- destructiveHint: 工具是否执行删除操作
- idempotentHint: 工具重复执行是否产生相同结果
- openWorldHint: 工具是否与外部世界交互
资料来源:server.py:100-150
存储架构与数据模型
存储位置
所有数据持久化存储在 ~/.agent-memory/ 目录:
~/.agent-memory/
├── {namespace}.json # 每个命名空间一个文件
└── _meta.json # 全局统计数据
资料来源:README.md:120-140
条目数据结构
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
访问计数机制
每次调用 memory_recall 都会更新 accessed_at 时间戳并递增 access_count,这使得:
- 搜索结果按相关性排序(高频访问条目优先)
- 可以分析记忆条目的使用频率
- 便于识别长期未使用的陈旧数据
资料来源:server.py:250-300
并发安全机制
Agent Memory MCP 使用 POSIX 文件锁 fcntl.flock() 实现线程安全:
graph TD
A[Agent 进程 1] -->|写入| L[文件锁]
B[Agent 进程 2] -->|等待| L
C[Agent 进程 N] -->|等待| L
L -->|解锁| A
L -->|锁定| B
B -->|解锁| B
L -->|锁定| C这允许多个 Agent 进程安全地并发读写内存存储。
资料来源:server.py:80-100
响应格式控制
所有工具支持 format 参数指定返回格式:
# 获取 Markdown 格式输出(人类可读)
result = await memory_stats(format="markdown")
# 获取 JSON 格式输出(程序化使用)
result = await memory_stats(format="json")
JSON 格式响应示例
{
"status": "ok",
"total_entries": 847,
"active_entries": 835,
"expired_entries": 12,
"total_size": "2.4 MB",
"namespaces": 5,
"oldest_entry": "2026-04-15 (27 days ago)",
"newest_entry": "just now"
}
资料来源:server.py:300-350
定价层级与限制
| 层级 | 价格 | 限制 |
|---|---|---|
| 免费版 | $0 | 1,000 条目,5 个命名空间 |
| 专业版 | $19/月 | 无限条目,无限命名空间,优先支持 |
资料来源:README.md:150-160
设计原则
Agent Memory MCP 遵循以下核心设计原则:
- 简洁优于复杂 — 类似 Redis 的键值存储,而非向量数据库。Agent 只需记住关键信息。
- 本地优先 — 数据保留在本地机器上。无云服务、无 API 密钥、无延迟。
- 自描述性 — 工具响应默认采用人类可读的 Markdown 格式,JSON 格式供程序调用。
- 容错性 — 延迟 TTL 过期、非严格搜索、优雅的错误处理。
资料来源:README.md:110-115
最佳实践总结
命名空间策略
- 按项目、用户或领域组织命名空间
- 使用清晰、一致的命名约定(如
agent:{name}、user:{id}) - 定期清理不再需要的命名空间
TTL 设置指南
| 数据类型 | TTL 建议 | 示例 |
|---|---|---|
| 用户偏好 | 永久或长 TTL | 30-90 天 |
| 研究发现 | 中等 TTL | 7-30 天 |
| 工作区数据 | 短 TTL 或清理 | 1-7 天 |
| 会话数据 | 会话结束清理 | 无 TTL |
键命名规范
- 使用冒号分隔层级:
user:preferences:theme - 保持键名简洁但具描述性
- 避免在键名中包含敏感信息
性能优化
- 批量相似操作使用同一命名空间
- 定期调用
memory_stats监控存储使用 - 及时清理过期数据以减少存储开销
资料来源:[README.md](https://github.com/Rumblingb/agent-memory-mcp/blob/main/README.md)
开发指南
本文档为 Agent Memory MCP 项目的完整开发指南,涵盖项目架构、工具实现、数据存储机制、测试方法以及部署配置。通过本指南,开发者可以深入理解系统设计理念,快速上手二次开发或集成工作。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 项目概述
Agent Memory MCP 是一个基于 Model Context Protocol (MCP) 的持久化键值存储服务器,专为 AI Agent 设计。该项目解决了 AI Agent 在会话之间丢失上下文的核心问题,提供持久化、可搜索、带 TTL(生存时间)的记忆存储能力。
项目核心特性包括:
- 7 个结构化工具支持完整的记忆管理
- Namespace 命名空间隔离机制
- TTL 自动过期与延迟清理
- 模糊搜索(子串匹配)
- 访问计数追踪
- 基于
fcntl.flock()的线程安全并发访问 - 零外部依赖(仅依赖
mcp包) - JSON 文件存储,数据保留在本地
~/.agent-memory/
资料来源:server.py:1-30
2. 系统架构
2.1 整体架构图
graph TD
subgraph AI_Agent["AI Agent (Claude/GPT/Codex)"]
A[remember / recall / search / forget]
end
subgraph MCP_Protocol["MCP 协议层 (stdio JSON-RPC)"]
B[Tool Call 请求]
C[JSON-RPC 响应]
end
subgraph Server["Agent Memory MCP Server"]
D[KV Store Engine]
E[TTL Manager]
F[Search Engine<br/>substring match]
end
subgraph Storage["数据持久化层"]
G["~/.agent-memory/"]
H["{namespace}.json"]
I["_meta.json"]
end
A -->|MCP Protocol| B
B --> D
D --> E
E --> F
D --> H
D --> I
F --> G
C -->|响应结果| A架构采用经典的三层设计:协议层处理 MCP 通信、业务层实现核心逻辑、存储层负责数据持久化。fcntl.flock() 文件锁确保多个 Agent 进程可以安全地并发读写。
资料来源:README.md:架构图
2.2 核心组件说明
| 组件 | 文件位置 | 职责 | 依赖 |
|---|---|---|---|
| MCP Server | server.py | 注册工具、处理请求路由 | mcp.server |
| KV Store Engine | server.py | 键值存储 CRUD 操作 | json, pathlib |
| TTL Manager | server.py | 过期检查与延迟清理 | datetime, time |
| Search Engine | server.py | 子串匹配搜索 | re (正则) |
| File Locker | server.py | 并发访问控制 | fcntl |
资料来源:server.py:28-60
3. 项目结构
agent-memory-mcp/
├── server.py # 主服务器实现(核心业务逻辑)
├── requirements.txt # 依赖声明
├── README.md # 项目文档
├── LICENSE # MIT 许可证
└── smithery.yaml # Smithery.ai 部署配置
核心代码全部集中在 server.py 单文件中,采用模块化函数设计,便于维护和理解。
资料来源:requirements.txt
4. 环境配置与安装
4.1 系统要求
| 要求 | 最低版本 | 说明 |
|---|---|---|
| Python | 3.10+ | 需要结构化并发支持 |
| mcp | ≥1.0.0 | MCP Python SDK |
| 操作系统 | POSIX 兼容 | 需要 fcntl 支持 |
4.2 安装步骤
# 克隆仓库
git clone https://github.com/Rumblingb/agent-memory-mcp.git
cd agent-memory-mcp
# 安装依赖
pip install mcp
# 或使用 requirements.txt
pip install -r requirements.txt
资料来源:README.md:安装章节
4.3 存储目录
首次运行时,系统自动创建存储目录:
STORAGE_DIR = Path.home() / ".agent-memory"
数据存储结构如下:
| 文件 | 内容 |
|---|---|
{namespace}.json | 每个命名空间的记忆条目数组 |
_meta.json | 全局统计和索引信息 |
资料来源:server.py:54-56
5. 工具实现详解
5.1 工具注册机制
所有工具通过 MCP Server 的装饰器模式注册:
@server.list_tools()
async def list_tools() -> List[Tool]:
return [Tool(...), Tool(...), ...]
路由分发通过 call_tool 装饰器实现:
@server.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]) -> CallToolResult:
if name == "memory_remember":
text = memory_remember(**arguments, fmt=fmt)
elif name == "memory_recall":
text = memory_recall(**arguments, fmt=fmt)
# ... 其他工具
资料来源:server.py:320-345
5.2 工具清单与参数
#### 5.2.1 memory_remember
存储键值对到指定命名空间。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 唯一键标识符 |
value | string | ✅ | - | 要存储的值 |
namespace | string | ❌ | "default" | 命名空间 |
ttl_seconds | integer | ❌ | - | TTL 秒数 |
Tool Annotations:
ToolAnnotations(
readOnlyHint=False,
destructiveHint=False,
idempotentHint=False,
openWorldHint=False
)
资料来源:server.py:工具定义区域
#### 5.2.2 memory_recall
根据键检索值及其元数据。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 要检索的键 |
namespace | string | ❌ | "default" | 命名空间 |
返回值结构:
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
资料来源:server.py:170-200
#### 5.2.3 memory_forget
删除指定的键值对。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | ✅ | - | 要删除的键 |
namespace | string | ❌ | "default" | 命名空间 |
#### 5.2.4 memory_search
跨命名空间模糊搜索。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
query | string | ✅ | - | 搜索关键词或子串 |
namespace | string | ❌ | - | 限定命名空间(空则搜索全部) |
limit | integer | ❌ | 10 | 最大返回结果数 |
搜索特性:
- 大小写不敏感
- 同时匹配 key 和 value
- 按访问次数排序
#### 5.2.5 memory_list_namespaces
列出所有命名空间及其条目计数。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
format | string | ❌ | "markdown" | 输出格式:markdown 或 json |
#### 5.2.6 memory_clear_namespace
清空指定命名空间的所有条目。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
namespace | string | ✅ | - | 要清空的命名空间 |
#### 5.2.7 memory_stats
获取全局存储统计信息。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
format | string | ❌ | "markdown" | 输出格式:markdown 或 json |
资料来源:server.py:工具定义区域
5.3 工具注解系统
MCP 协议支持工具注解,用于客户端优化行为:
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
memory_remember | false | false | false | false |
memory_recall | true | false | true | false |
memory_forget | false | true | true | false |
memory_search | true | false | true | false |
memory_list_namespaces | true | false | true | false |
memory_clear_namespace | false | true | false | false |
memory_stats | true | false | true | false |
资料来源:README.md:Tool Annotations
6. 数据模型
6.1 记忆条目结构
{
"key": "user:theme",
"value": "dark",
"created_at": "2026-05-12T10:30:00Z",
"accessed_at": "2026-05-12T14:22:00Z",
"expires_at": "2026-06-11T10:30:00Z",
"access_count": 47
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 全局唯一标识符 |
value | string | 存储的实际内容 |
created_at | ISO8601 string | 创建时间 |
accessed_at | ISO8601 string | 最后访问时间 |
expires_at | ISO8601 string 或 null | TTL 过期时间(可选) |
access_count | integer | 访问计数器 |
资料来源:server.py:记忆条目结构
6.2 元数据文件结构
{
"total_entries": 142,
"namespace_count": 5
}
资料来源:server.py:元数据写入
7. 存储实现细节
7.1 文件锁定机制
@contextmanager
def _locked(namespace: str):
lock_path = _namespace_path(namespace).with_suffix(".lock")
with lock_path.open("w") as lock_file:
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
try:
yield
finally:
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
使用 POSIX 文件锁 fcntl.flock() 实现排他锁,确保多进程并发安全。
资料来源:server.py:文件锁定实现
7.2 命名空间安全处理
def _namespace_path(namespace: str) -> Path:
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
return STORAGE_DIR / f"{safe}.json"
使用正则表达式过滤非法字符,防止路径穿越攻击。
资料来源:server.py:命名空间路径安全处理
7.3 TTL 过期检查
def _is_expired(entry: Dict[str, Any]) -> bool:
if "expires_at" not in entry or entry["expires_at"] is None:
return False
expires = datetime.fromisoformat(entry["expires_at"])
return datetime.now(timezone.utc) > expires
采用延迟清理策略,仅在访问时检查过期,避免后台清理线程开销。
资料来源:server.py:TTL检查逻辑
8. 测试与调试
8.1 本地测试
# 使用 MCP Inspector 测试
npx @modelcontextprotocol/inspector python3 server.py
# 运行单元测试
python3 -m pytest tests/
资料来源:README.md:开发章节
8.2 MCP Client 配置
通用配置 (config.yaml):
mcpServers:
agent-memory:
command: python3
args:
- /path/to/agent-memory-mcp/server.py
description: Persistent key-value memory for AI agents
Claude Desktop:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["/path/to/agent-memory-mcp/server.py"]
}
}
}
VS Code / Cursor:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["server.py"],
"cwd": "/path/to/agent-memory-mcp"
}
}
}
资料来源:README.md:MCP Client配置
9. 部署配置
9.1 Smithery.ai 部署
项目提供 Smithery.ai 平台的一键部署配置:
name: agent-memory-mcp
version: 1.0.0
description: Persistent key-value memory for AI agents with TTL, namespaces, and search.
runtime:
type: python
entrypoint: server.py
requirements: requirements.txt
capabilities:
tools:
- memory_remember
- memory_recall
- memory_forget
- memory_search
- memory_list_namespaces
- memory_clear_namespace
- memory_stats
pricing:
free:
max_entries: 1000
pro:
price: 19.00
currency: USD
interval: month
max_entries: unlimited
stripe_link: https://buy.stripe.com/PLACEHOLDER
metadata:
author: Nous Research
license: MIT
repository: https://github.com/nousresearch/agent-memory-mcp
tags:
- memory
- storage
- agents
- persistence
- kv-store
资料来源:smithery.yaml
10. 响应格式化
10.1 格式化策略
系统支持两种响应格式,通过 format 参数控制:
| 格式 | 适用场景 | 示例 |
|---|---|---|
markdown | 人类可读 | ## ✅ Success\nkey: value |
json | 程序化处理 | {"status": "ok", "key": "value"} |
10.2 错误处理
所有工具都包装在统一的异常处理中:
try:
# 工具执行
except Exception as exc:
err_text = _error(f"Internal error in {name}: {exc}", fmt)
return CallToolResult(
content=[TextContent(type="text", text=err_text)],
isError=True,
)
输出长度限制在 25,000 字符以内,防止大响应导致的问题。
资料来源:server.py:异常处理和输出限制
11. 设计原则
项目遵循以下核心设计原则:
- 简洁优于复杂 — 类似 Redis 的 KV 存储,而非向量数据库。Agent 只需要记住事情。
- 本地优先 — 数据保存在本地机器上。无云服务、无 API 密钥、无延迟。
- 自描述 — 工具响应默认是人类可读的 markdown,JSON 用于程序化调用。
- 容错性 — 延迟 TTL 过期、非严格搜索、优雅的错误处理。
资料来源:README.md:设计原则
12. 扩展开发指南
12.1 添加新工具
在 server.py 中添加新工具需要完成以下步骤:
- 在
list_tools()中定义Tool对象 - 在
call_tool()中添加路由分支 - 实现对应的处理函数
- 添加单元测试
# 1. 定义工具
Tool(
name="memory_new_tool",
description="新工具描述",
inputSchema={
"type": "object",
"properties": {...},
"required": [...]
},
annotations=ToolAnnotations(
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=False,
),
)
# 2. 路由分发
elif name == "memory_new_tool":
text = memory_new_tool(**arguments, fmt=fmt)
# 3. 实现函数
def memory_new_tool(key: str, fmt: str = "markdown") -> str:
# 业务逻辑
return _success({"result": "..."}, fmt)
12.2 修改存储后端
当前实现使用 JSON 文件存储。如需切换到其他后端(如 SQLite),需要重写以下函数:
_read_namespace()_write_namespace()_locked()_recalc_meta()
保持接口签名不变,上层业务逻辑无需修改。
13. 相关资源
| 资源 | 链接 |
|---|---|
| 官方仓库 | https://github.com/nousresearch/agent-memory-mcp |
| Nous Research | https://nousresearch.com |
| 相关项目 - Agent Cost Tracker MCP | https://github.com/Rumblingb/agent-cost-tracker-mcp |
| 相关项目 - Search Proxy MCP | https://github.com/Rumblingb/search-proxy-mcp |
| 相关项目 - AgentPassport API | https://github.com/Rumblingb/agentpassport-api |
资料来源:[server.py:1-30]()
部署指南与常见问题
本页面提供 Agent Memory MCP 的完整部署指南与常见问题解答。该项目是一个基于 Model Context Protocol (MCP) 的持久化键值存储系统,专为 AI 代理设计,支持命名空间隔离、TTL 过期机制、模糊搜索和访问计数追踪。资料来源:[server.py:1-30]()
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
本页面提供 Agent Memory MCP 的完整部署指南与常见问题解答。该项目是一个基于 Model Context Protocol (MCP) 的持久化键值存储系统,专为 AI 代理设计,支持命名空间隔离、TTL 过期机制、模糊搜索和访问计数追踪。资料来源:server.py:1-30
系统要求
| 要求项 | 规格 |
|---|---|
| Python 版本 | 3.10+ |
| 操作系统 | macOS、Linux、Windows |
| 依赖包 | mcp >= 1.0.0 |
| 网络 | 仅本地通信,无需外网 |
资料来源:requirements.txt:1
部署方式
方式一:pip 安装(推荐)
通过 Python 包管理器直接安装:
pip install agent-memory-mcp
安装完成后可直接使用 python3 -m agent_memory_mcp 启动服务。资料来源:index.html
方式二:源码安装
适用于需要自定义修改或参与开发的情况:
# 克隆仓库
git clone https://github.com/Rumblingb/agent-memory-mcp.git
cd agent-memory-mcp
# 安装依赖
pip install mcp
# 或使用 requirements.txt
pip install -r requirements.txt
# 启动服务
python3 server.py
资料来源:README.md:89-99
方式三:MCP Inspector 测试
在开发阶段,可使用 MCP Inspector 进行调试:
npx @modelcontextprotocol/inspector python3 server.py
资料来源:README.md:101-102
MCP 客户端配置
Claude Desktop
在 ~/Library/Application Support/Claude/claude_desktop_config.json 中添加:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["/absolute/path/to/agent-memory-mcp/server.py"]
}
}
}
资料来源:README.md:117-123
VS Code / Cursor
在 .cursor/mcp.json 或 VS Code 的 MCP 设置中添加:
{
"mcpServers": {
"agent-memory": {
"command": "python3",
"args": ["server.py"],
"cwd": "/path/to/agent-memory-mcp"
}
}
}
资料来源:README.md:125-132
通用 YAML 配置
mcpServers:
agent-memory:
command: python3
args:
- /path/to/agent-memory-mcp/server.py
description: Persistent key-value memory for AI agents
存储架构
数据存储位置
所有数据存储在用户主目录下的隐藏目录 ~/.agent-memory/ 中:
| 文件 | 用途 |
|---|---|
{namespace}.json | 各命名空间的记忆条目数组 |
_meta.json | 全局统计和索引信息 |
资料来源:server.py:47-49
graph TD
A[AI Agent] -->|MCP Protocol| B[agent-memory Server]
B --> C{操作类型}
C -->|remember| D[写入 JSON 文件]
C -->|recall| E[读取并更新访问计数]
C -->|search| F[模糊匹配搜索]
C -->|forget| G[删除条目]
D --> H[~/.agent-memory/]
E --> H
F --> H
G --> H命名空间隔离机制
每个命名空间对应独立的 JSON 文件,通过命名空间路径函数进行隔离:
def _namespace_path(namespace: str) -> Path:
# Sanitize the namespace so it can't escape the directory.
safe = re.sub(r"[^a-zA-Z0-9_.\-]", "_", namespace)
if not safe:
safe = DEFAULT_NAMESPACE
return STORAGE_DIR / f"{safe}.json"
关键安全措施:命名空间名只能包含 a-zA-Z0-9_.- 字符,其他字符会被替换为下划线,防止目录遍历攻击。资料来源:server.py:58-65
工具函数使用指南
1. memory_remember — 存储记忆
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | ✅ | 记忆的唯一标识键 |
value | string | ✅ | 要存储的值 |
namespace | string | ❌ | 命名空间,默认 "default" |
ttl_seconds | integer | ❌ | 自动过期秒数 |
示例:
# 带 TTL 的用户偏好存储(30天过期)
await memory_remember(
key="user:theme",
value="dark",
namespace="preferences",
ttl_seconds=2592000
)
# 永久存储研究数据
await memory_remember(
key="competitor:pricing:stripe",
value="Stripe charges 2.9% + $0.30 per transaction",
namespace="research"
)
资料来源:README.md:135-145
2. memory_recall — 检索记忆
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | ✅ | 要检索的键名 |
namespace | string | ❌ | 命名空间,默认 "default" |
返回元数据:
| 字段 | 说明 |
|---|---|
value | 存储的值 |
created_at | 创建时间戳 |
accessed_at | 最后访问时间 |
expires_at | TTL 过期时间(如有设置) |
access_count | 访问次数统计 |
资料来源:README.md:147-156
3. memory_forget — 删除记忆
await memory_forget(
key="user:old_preference",
namespace="preferences"
)
4. memory_search — 模糊搜索
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query | string | ✅ | 搜索关键词或子字符串 |
namespace | string | ❌ | 限定命名空间搜索 |
limit | integer | ❌ | 最大返回数量,默认 10 |
format | string | ❌ | 输出格式:markdown 或 json |
# 跨所有命名空间搜索
results = await memory_search(query="competitor pricing")
# 限定命名空间搜索
results = await memory_search(
query="api",
namespace="research",
limit=20
)
搜索特性:大小写不敏感,同时匹配键名和值内容,结果按访问次数排序。资料来源:server.py:275-295
5. memory_list_namespaces — 列出命名空间
# 返回所有命名空间及其活跃/过期条目计数
namespaces = await memory_list_namespaces()
6. memory_clear_namespace — 清除命名空间
# 永久删除指定命名空间的所有条目
await memory_clear_namespace(namespace="research:old")
# → "Cleared 156 entries from 'research:old'"
注意: 此操作不可撤销。资料来源:README.md:177-179
7. memory_stats — 全局统计
# 获取存储统计信息
stats = await memory_stats(format="markdown")
返回字段:
| 字段 | 说明 |
|---|---|
total_entries | 活跃条目总数 |
total_size_bytes | 存储文件总大小(字节) |
total_size_human | 人类可读大小 |
namespace_count | 命名空间数量 |
oldest_entry | 最早条目时间 |
newest_entry | 最新条目时间 |
free_tier_limit | 免费配额限制(1000条) |
资料来源:server.py:345-370
常见问题排查
问题一:导入错误 "ModuleNotFoundError: No module named 'mcp'"
原因: 未安装 MCP 依赖包。
解决方案:
pip install mcp
或者使用项目提供的 requirements.txt:
pip install -r requirements.txt
资料来源:requirements.txt:1
问题二:存储目录权限错误
症状: PermissionError: [Errno 13] Permission denied
原因: 无法在 ~/.agent-memory/ 创建文件。
解决方案:
# 检查并修复目录权限
ls -la ~ | grep agent-memory
chmod 755 ~/.agent-memory
存储目录由以下代码自动创建:
def _ensure_storage() -> None:
"""Create the storage directory if it doesn't exist."""
STORAGE_DIR.mkdir(parents=True, exist_ok=True)
资料来源:server.py:52-54
问题三:并发访问数据不一致
症状: 写入的数据在读取时丢失或损坏。
原因: 未使用正确的并发控制机制。
解决方案: Agent Memory MCP 使用 fcntl.flock() 实现文件级锁,确保多进程安全访问。确保所有访问都通过 MCP 服务器进行,而非直接操作 JSON 文件。资料来源:README.md:203-205
问题四:TTL 过期条目未自动清理
症状: 过期条目仍然出现在搜索结果中。
原因: 系统采用懒清理策略,仅在访问时检查过期状态。
解决方案: 这是设计决策,不影响功能。过期条目会在下次 recall 或 search 时被自动过滤。如需主动清理,可调用 memory_list_namespaces 查看各命名空间状态。
过期检测逻辑:
def _is_expired(entry: Dict[str, Any]) -> bool:
"""Check if an entry has expired based on its TTL."""
expires_at = entry.get("expires_at")
if not expires_at:
return False
expires_time = datetime.fromisoformat(expires_at)
return datetime.now(timezone.utc) > expires_time
资料来源:server.py:120-127
问题五:中文或特殊字符无法正确存储
症状: 存储的中文字符在检索时变成乱码。
原因: 字符编码问题。
解决方案: 确保 JSON 文件使用 UTF-8 编码。Python 的 json 模块默认使用 UTF-8,无需额外配置。如在终端显示乱码,请确保终端编码设置为 UTF-8。
问题六:数据文件过大
症状: ~/.agent-memory/ 目录占用过多磁盘空间。
解决方案:
- 定期清理过期或无用命名空间:
# 清理特定命名空间
await memory_clear_namespace(namespace="temp:sessions")
# 查看统计信息
stats = await memory_stats()
- 手动删除不使用的 JSON 文件:
rm ~/.agent-memory/old_namespace.json
资料来源:server.py:380-385
线程安全机制
Agent Memory MCP 通过 POSIX 文件锁 fcntl.flock() 实现并发安全:
graph LR
A[进程 A] -->|LOCK_EX| C[文件锁]
B[进程 B] -->|等待| C
C -->|解锁| D[完成读写]
D -->|UNLOCK| E[锁释放]
B -->|获锁| D所有文件操作都在锁保护区域内执行,确保同一时间只有一个进程可以写入。资料来源:README.md:203-205
响应格式
工具支持两种输出格式,通过 format 参数指定:
| 格式 | 用途 | 示例 |
|---|---|---|
markdown | 人类可读,默认 | ## ✅ Success\nkey: value |
json | 程序化处理 | {"status": "ok", "key": "value"} |
# 获取 JSON 格式结果
result = await memory_recall(
key="user:theme",
namespace="preferences",
format="json"
)
资料来源:server.py:310-335
开发测试
运行项目测试套件:
python3 -m pytest tests/
使用 MCP Inspector 进行交互式测试:
npx @modelcontextprotocol/inspector python3 server.py
资料来源:README.md:101-104
定价与限制
| 套餐 | 价格 | 限制 |
|---|---|---|
| 免费版 | $0 | 1,000 条目,5 个命名空间 |
| Pro 版 | $19/月 | 无限条目,无限命名空间,优先支持 |
注意:免费版限制为功能性提示,非技术强制限制。数据始终存储在本地,不会因达到限制而丢失。资料来源:index.html
架构总览
graph TD
subgraph AI层
A[Claude/GPT/Codex]
end
subgraph MCP协议层
B[MCP Protocol<br/>stdio JSON-RPC]
end
subgraph 服务层
C[Agent Memory<br/>MCP Server]
D[KV 存储引擎]
E[TTL 管理器]
F[搜索引擎<br/>子字符串匹配]
end
subgraph 存储层
G[~/.agent-memory/]
H[namespace.json]
I[_meta.json]
end
A -->|remember/recall/search| B
B --> C
C --> D
C --> E
C --> F
D --> G
E --> G
F --> G
G --> H
G --> I资料来源:README.md:195-215
参考链接
- 项目仓库:https://github.com/Rumblingb/agent-memory-mcp
- Nous Research:https://nousresearch.com
- 相关项目:
- Agent Cost Tracker MCP
- Search Proxy MCP
- AgentPassport API
资料来源:[requirements.txt:1]()
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
下游已经要求复核,不能在页面中弱化。
Pitfall Log / 踩坑日志
项目:Rumblingb/agent-memory-mcp
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:身份坑 - 仓库名和安装名不一致。
1. 身份坑 · 仓库名和安装名不一致
- 严重度:medium
- 证据强度:runtime_trace
- 发现:仓库名
agent-memory-mcp与安装入口mcp不完全一致。 - 对用户的影响:用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
- 建议检查:在 npm/PyPI/GitHub 上确认包名映射和官方 README 说明。
- 复现命令:
pip install mcp - 防护动作:页面必须同时展示 repo 名和真实安装入口,避免用户搜索错包。
- 证据:identity.distribution | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | repo=agent-memory-mcp; install=mcp
2. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 建议检查:将假设转成下游验证清单。
- 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
- 证据:capability.assumptions | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | README/documentation is current enough for a first validation pass.
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
- 证据:evidence.maintainer_signals | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | last_activity_observed missing
4. 安全/权限坑 · 下游验证发现风险项
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:下游已经要求复核,不能在页面中弱化。
- 建议检查:进入安全/权限治理复核队列。
- 防护动作:下游风险存在时必须保持 review/recommendation 降级。
- 证据:downstream_validation.risk_items | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 建议检查:把风险写入边界卡,并确认是否需要人工复核。
- 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
- 证据:risks.scoring_risks | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
- 防护动作:issue/PR 响应未知时,必须提示维护风险。
- 证据:evidence.maintainer_signals | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
- 证据:evidence.maintainer_signals | github_repo:1236240815 | https://github.com/Rumblingb/agent-memory-mcp | release_recency=unknown
来源:Doramagic 发现、验证与编译记录