搜索架构
Claude-mem 使用基于 MCP 的搜索架构,通过遵循三层工作流模式的 4 个简化工具提供智能记忆检索。
概览
架构: MCP 工具 → MCP 协议 → HTTP API → Worker 服务
关键组件:
- MCP 工具(4 个工具)-
search,timeline,get_observations,__IMPORTANT - MCP 服务器 (
plugin/scripts/mcp-server.cjs) - 基于 HTTP API 的轻量封装 - HTTP API 端点 - 在 Worker 服务(端口 37777)上的快速搜索操作
- Worker 服务 - 带有 FTS5 全文搜索的 Express.js 服务器
- SQLite 数据库 - 使用 FTS5 虚拟表的持久化存储
- Chroma向量数据库 - 结合混合检索的语义搜索
token 效率:通过三层工作流程模式节省约 10 倍
运作方式
1. 用户查询
Claude 可以使用 4 个 MCP 工具。在搜索记忆时,Claude 遵循三层工作流程:
Step 1: search(query="authentication bug", type="bugfix", limit=10)
Step 2: timeline(anchor=<observation_id>, depth_before=3, depth_after=3)
Step 3: get_observations(ids=[123, 456, 789])2. MCP 协议
MCP 服务器通过 stdio 使用 JSON-RPC 接收工具调用:
{
"method": "tools/call",
"params": {
"name": "search",
"arguments": {
"query": "authentication bug",
"type": "bugfix",
"limit": 10
}
}
}3. HTTP API 请求
MCP 服务器转换为 HTTP 请求:
const url = `http://localhost:37777/api/search?query=authentication%20bug&type=bugfix&limit=10`;
const response = await fetch(url);4. Worker 处理
Worker 服务执行 FTS5 查询:
SELECT * FROM observations_fts
WHERE observations_fts MATCH ?
AND type = 'bugfix'
ORDER BY rank
LIMIT 105. 返回的结果
Worker 返回结构化数据 → MCP 服务器 → Claude:
{
"content": [{
"type": "text",
"text": "| ID | Time | Title | Type |\n|---|---|---|---|\n| #123 | 2:15 PM | Fixed auth token expiry | bugfix |"
}]
}6. Claude 处理结果
Claude查看索引,决定哪些观察是相关的,并且可以:
- 使用
timeline获取上下文 - 使用
get_observations获取所选 ID 的完整详细信息
4 个 MCP 工具
__IMPORTANT - 工作流文档
始终对Claude可见。解释三层工作流模式。
描述:
3-LAYER WORKFLOW (ALWAYS FOLLOW):
1. search(query) → Get index with IDs (~50-100 个 token/result)
2. timeline(anchor=ID) → Get context around interesting results
3. get_observations([IDs]) → Fetch full details ONLY for filtered IDs
NEVER fetch full details without filtering first. 10x token savings.目的: 确保 Claude 遵循高效使用 token 的模式
search - 搜索内存索引
工具定义:
{
name: 'search',
description: 'Step 1: Search memory. Returns index with IDs. Params: query, limit, project, type, obs_type, dateStart, dateEnd, offset, orderBy',
inputSchema: {
type: 'object',
properties: {},
additionalProperties: true // Accepts any parameters
}
}HTTP端点: GET /api/search
参数:
query- 全文搜索查询limit- 最大结果数(默认:20)type- 按观测类型过滤project- 按项目名称筛选dateStart,dateEnd- 日期范围筛选offset- 分页偏移orderBy- 排序顺序
返回值: 包含ID、标题、日期、类型的紧凑索引(每个结果约50-100个词)
timeline - 获取时间顺序的背景
工具定义:
{
name: 'timeline',
description: 'Step 2: Get context around results. Params: anchor (observation ID) OR query (finds anchor automatically), depth_before, depth_after, project',
inputSchema: {
type: 'object',
properties: {},
additionalProperties: true
}
}HTTP端点: GET /api/timeline
参数:
anchor- 用于围绕时间轴进行观察的 ID(如果提供查询,则可选)query- 自动查找锚点的搜索查询(如果提供了锚点,则可选)depth_before- 锚点前的观测次数(默认值:3)depth_after- 锚点后的观察次数(默认值:3)project- 按项目名称筛选
返回值: 显示事件发生前/期间/之后的时间顺序视图
get_observations - 获取完整详情
工具定义:
{
name: 'get_observations',
description: 'Step 3: Fetch full details for filtered IDs. Params: ids (array of observation IDs, required), orderBy, limit, project',
inputSchema: {
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'number' },
description: 'Array of observation IDs to fetch (required)'
}
},
required: ['ids'],
additionalProperties: true
}
}HTTP端点: POST /api/observations/batch
正文:
{
"ids": [123, 456, 789],
"orderBy": "date_desc",
"project": "my-app"
}返回: 完整的观察细节(每次观察约 500-1,000 个标记)
MCP 服务器实现
地点: /Users/YOUR_USERNAME/.claude/plugins/marketplaces/thedotmack/plugin/scripts/mcp-server.cjs
角色: 将 MCP 协议转换为 HTTP API 调用的轻量封装
关键特征:
- ~312 行代码(从旧实现的约 2,718 行减少)
- 没有业务逻辑 - 只是协议转换
- 唯一可信来源:Worker HTTP API
- 带有
additionalProperties: true的简单模式
处理程序示例:
{
name: 'search',
handler: async (args: any) => {
const endpoint = '/api/search';
const searchParams = new URLSearchParams();
for (const [key, value] of Object.entries(args)) {
searchParams.append(key, String(value));
}
const url = `http://localhost:37777${endpoint}?${searchParams}`;
const response = await fetch(url);
return await response.json();
}
}Worker HTTP API
地点: src/services/worker-service.ts
端口: 37777
搜索端点:
GET /api/search # Main search (used by MCP search tool)
GET /api/timeline # Timeline context (used by MCP timeline tool)
POST /api/observations/batch # Fetch by IDs (used by MCP get_observations tool)
GET /api/health # Health check数据库访问:
- 使用
SessionSearch服务进行 FTS5 查询 - 使用
SessionStore进行结构化查询 - 使用 ChromaDB 进行语义相似性的混合搜索
FTS5 全文搜索:
// search tool → HTTP GET → FTS5 query
SELECT * FROM observations_fts
WHERE observations_fts MATCH ?
AND type = ?
AND date >= ? AND date <= ?
ORDER BY rank
LIMIT ? OFFSET ?三层工作流模式
设计理念
这三层工作流程体现了渐进披露——claude-mem 架构的核心原则。
第1层:索引(搜索)
- 内容: 带有ID、标题、日期、类型的紧凑表格
- 成本: 每个结果约50-100 个 token
- 目的: 在投入token之前调查现有的情况
- 决策点: “哪些观察是相关的?”
第2层:上下文(时间线)
- 内容: 围绕某一点的观察时间顺序视图
- 费用: 根据深度而变化
- 目的: 理解叙事弧线,了解导致或由某个点产生的情况
- 决策点: “我需要完整的细节吗?”
第3层:详细信息(获取观测)
- 内容: 完整的观察数据(叙述、事实、文件、概念)
- 成本: 每次观测约 500-1,000 token
- 目的: 深入研究经过验证的相关观察
- 决策点: “将知识应用于当前任务”
token 效率
传统 RAG 方法:
Fetch 20 observations upfront: 10,000-20,000 个 token
Relevance: ~10% (only 2 observations actually useful)
Waste: 18,000 个 token on irrelevant context三层工作流:
Step 1: search (20 results) ~1,000-2,000 个 token
Step 2: Review index, filter to 3 relevant IDs
Step 3: get_observations (3 IDs) ~1,500-3,000 个 token
Total: 2,500-5,000 个 token (50-75% savings)10倍节省: 在获取完整详情之前,先在索引级别进行过滤
架构演进
之前:复杂的MCP实现
方法: 9 个 MCP 工具,附带详细的参数结构
token成本: 每次会话大约在 2,500 个工具定义token
search_observations- 全文搜索find_by_type- 按类型筛选find_by_file- 按文件筛选find_by_concept- 按概念筛选get_recent_context- 最近会话get_observation- 获取单个观测值get_session- 获取会话get_prompt- 获取提示help- API 文档
问题:
- 重叠操作(search_observations 与 find_by_type)
- 复杂参数方案
- 没有内置的工作流程指导
- 会话开始时的高 token 成本
代码行数: mcp-server.ts 大约 2,718 行
之后:精简的 MCP 实施
方法: 4 个 MCP 工具遵循三层工作流程
**token 成本:**约 312 行代码,简化的工具定义
工具:
__IMPORTANT- 工作流程指南(始终可见)search- 第1步(索引)timeline- 第2步(上下文)get_observations- 第3步(详情)
好处:
- 工具设计中内置的渐进式揭示
- 没有重叠操作
- 简单模式 (
additionalProperties: true) - 清晰的工作流程模式
- ~10倍token节省
代码行数: mcp-server.ts 中约 312 行(减少 88%)
关键见解
之前: 逐步披露是克洛德必须记住的事情
之后: 渐进式显示由工具设计本身强制执行
三层工作流模式在结构上使浪费token变得困难:
- 在从搜索获取ID之前,无法获取详细信息
- 在看不到工作流提醒 (
__IMPORTANT) 的情况下无法搜索 - 时间线在索引和完整细节之间提供了中间地带
配置
Claude桌面
添加到 claude_desktop_config.json:
{
"mcpServers": {
"mcp-search": {
"command": "node",
"args": [
"/Users/YOUR_USERNAME/.claude/plugins/marketplaces/thedotmack/plugin/scripts/mcp-server.cjs"
]
}
}
}Claude Code
MCP 服务器通过插件安装自动配置,无需手动设置。
两个客户都使用相同的MCP工具——架构对Claude Desktop和Claude Code的工作方式完全相同。
安全
FTS5 注入预防
在 FTS5 处理之前,所有搜索查询都会被转义:
function escapeFTS5Query(query: string): string {
return query.replace(/"/g, '""');
}**测试:**332次注入攻击测试,涵盖特殊字符、SQL关键字、引号转义和布尔运算符。
MCP 协议安全
- 标准输入输出传输(无网络暴露)
- 仅限本地的 HTTP API(localhost:37777)
- 无需身份验证(仅限本地开发)
性能
FTS5 全文搜索: 典型查询低于 10 毫秒
MCP 开销: 最小 - 简单的协议转换
缓存: HTTP 层允许响应缓存(未来增强)
分页: 使用偏移量/限制效率高
批处理: get_observations 在单次调用中接受多个 ID
相对于其他方法的优势
与传统RAG相比
传统 RAG:
- 一次性获取所有内容
- 高token成本
- 低相关性比率
三层 MCP:
- 只获取所需内容
- ~10倍token节省
- 100% 相关性(Claude 选择获取内容)
与之前的 MCP 实现 (v5.x)
上一个(9 个工具):
- 复杂的模式
- 重叠操作
- 没有工作流程指导
- 定义中的约 2,500 个标记
当前(4 个工具):
- 简单的模式
- 清晰的工作流程
- 内置指导
- ~312 行代码
与技能为基础的方法(以前)
技能方法:
- 需要单独的技能文件
- 通过 curl 直接调用的 HTTP API
- 通过技能加载逐步披露
MCP 方法:
- 原生MCP协议(更好的Claude集成)
- 更清晰的架构(协议转换层)
- 适用于 Claude Desktop 和 Claude Code
- 更容易维护(没有技能文件)
迁移: 基于技能的搜索已被移除,取而代之的是精简的 MCP 架构。
故障排除
MCP 服务器未连接
症状: 工具未出现在Claude中
解决方案:
- 检查配置中的 MCP 服务器路径
- 验证Worker 服务是否正在运行:
curl http://localhost:37777/api/health - 重启 Claude 桌面/代码
Worker 服务未运行
症状: MCP 工具因连接错误而失败
解决方案:
npm run worker:status # Check status
npm run worker:restart # Restart worker
npm run worker:logs # View logs搜索结果为空
症状: search() 没有返回结果
故障排除:
- 直接测试 API:
curl "http://localhost:37777/api/search?query=test" - 检查数据库:
ls ~/.claude-mem/claude-mem.db - 验证观察是否存在:
curl "http://localhost:37777/api/health"
下一步
- 内存搜索使用 - 用户指南及示例]
- 渐进显示 - 三层工作流程背后的哲学]
- Worker 服务架构 - HTTP API 详细信息
- 数据库模式 - FTS5 表和索引