Skip to content

搜索架构

Claude-mem 使用基于 MCP 的搜索架构,通过遵循三层工作流模式的 4 个简化工具提供智能记忆检索。

概览

架构: MCP 工具 → MCP 协议 → HTTP API → Worker 服务

关键组件:

  1. MCP 工具(4 个工具)- searchtimelineget_observations__IMPORTANT
  2. MCP 服务器 (plugin/scripts/mcp-server.cjs) - 基于 HTTP API 的轻量封装
  3. HTTP API 端点 - 在 Worker 服务(端口 37777)上的快速搜索操作
  4. Worker 服务 - 带有 FTS5 全文搜索的 Express.js 服务器
  5. SQLite 数据库 - 使用 FTS5 虚拟表的持久化存储
  6. 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 接收工具调用:

json
{
  "method": "tools/call",
  "params": {
    "name": "search",
    "arguments": {
      "query": "authentication bug",
      "type": "bugfix",
      "limit": 10
    }
  }
}

3. HTTP API 请求

MCP 服务器转换为 HTTP 请求:

typescript
const url = `http://localhost:37777/api/search?query=authentication%20bug&type=bugfix&limit=10`;
const response = await fetch(url);

4. Worker 处理

Worker 服务执行 FTS5 查询:

sql
SELECT * FROM observations_fts
WHERE observations_fts MATCH ?
AND type = 'bugfix'
ORDER BY rank
LIMIT 10

5. 返回的结果

Worker 返回结构化数据 → MCP 服务器 → Claude:

json
{
  "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 - 搜索内存索引

工具定义:

typescript
{
  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 - 按项目名称筛选
  • dateStartdateEnd - 日期范围筛选
  • offset - 分页偏移
  • orderBy - 排序顺序

返回值: 包含ID、标题、日期、类型的紧凑索引(每个结果约50-100个词)

timeline - 获取时间顺序的背景

工具定义:

typescript
{
  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 - 获取完整详情

工具定义:

typescript
{
  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

正文:

json
{
  "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 的简单模式

处理程序示例:

typescript
{
  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

搜索端点:

typescript
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 全文搜索:

typescript
// 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 行代码,简化的工具定义

工具:

  1. __IMPORTANT - 工作流程指南(始终可见)
  2. search - 第1步(索引)
  3. timeline - 第2步(上下文)
  4. get_observations - 第3步(详情)

好处:

  • 工具设计中内置的渐进式揭示
  • 没有重叠操作
  • 简单模式 (additionalProperties: true)
  • 清晰的工作流程模式
  • ~10倍token节省

代码行数: mcp-server.ts 中约 312 行(减少 88%)

关键见解

之前: 逐步披露是克洛德必须记住的事情

之后: 渐进式显示由工具设计本身强制执行

三层工作流模式在结构上使浪费token变得困难:

  • 在从搜索获取ID之前,无法获取详细信息
  • 在看不到工作流提醒 (__IMPORTANT) 的情况下无法搜索
  • 时间线在索引和完整细节之间提供了中间地带

配置

Claude桌面

添加到 claude_desktop_config.json

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 处理之前,所有搜索查询都会被转义:

typescript
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中

解决方案:

  1. 检查配置中的 MCP 服务器路径
  2. 验证Worker 服务是否正在运行:curl http://localhost:37777/api/health
  3. 重启 Claude 桌面/代码

Worker 服务未运行

症状: MCP 工具因连接错误而失败

解决方案:

bash
npm run worker:status       # Check status
npm run worker:restart      # Restart worker
npm run worker:logs         # View logs

搜索结果为空

症状: search() 没有返回结果

故障排除:

  1. 直接测试 API:curl "http://localhost:37777/api/search?query=test"
  2. 检查数据库:ls ~/.claude-mem/claude-mem.db
  3. 验证观察是否存在:curl "http://localhost:37777/api/health"

下一步