跳转至

搜索架构

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

概述

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

关键组件: 1. MCP 工具 — 智能搜索(默认):search、timeline、get_observations、important_workflow 2. MCP 服务器(plugin/scripts/mcp-server.cjs)- 对 HTTP API 的轻量封装 3. HTTP API 端点 - 在配置的 Worker Service 端口上执行快速搜索操作 4. Worker Service - 使用 FTS5 全文搜索的 Express.js 服务器 5. SQLite 数据库 - 使用 FTS5 虚拟表的持久化存储 6. Chroma Vector DB - 混合检索的语义搜索

SQLite 保存当前记忆内容;Chroma 保存其搜索投影。 实时索引和启动回填共享每个集合、记录类型和 SQLite ID 的写入器。该写入器负责过时片段清理、每个文档批次以及同步检查点。回填和云同步转发在获得各自的时机后重新读取 SQLite 行,因此缓存的旧快照不能覆盖已完成修订,也不能在重新映射后恢复之前的项目。其他实时调用者可以直接提供其不可变的新行内容。不同记录仍可并发索引。此排序限于单个 worker 进程内;它不提供跨 SQLite 和 Chroma 的事务。在该读取之后发生的 SQL 变更仍需要它们自己的重新索引路径。

Token 效率:通过 3 层工作流模式实现约 10 倍节省

工作原理

1. 用户查询

Claude 可以访问 4 个 MCP 工具。搜索记忆时,Claude 遵循 3 层工作流:

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 workerPort = process.env.CLAUDE_MEM_WORKER_PORT ?? "<worker-port>";
const workerBaseUrl = `http://127.0.0.1:${workerPort}`;
const url = `${workerBaseUrl}/api/search?query=authentication%20bug&type=bugfix&limit=10`;
const response = await fetch(url);

4. Worker 处理

Worker Service 执行 FTS5 查询:

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

5. 返回结果

Worker Service 返回结构化数据 → 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_workflow - 工作流文档

始终对 Claude 可见。解释 3 层工作流模式。

描述:

3-LAYER WORKFLOW (ALWAYS FOLLOW):
1. search(query) → Get index with IDs (~50-100 tokens/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 个 token),按日期标题(### <date>)分组,因此每个返回的结果都带有其时间。日期组按相关性顺序而非时间顺序排列,因此排名最高的匹配项保持在最前面,即使排名较低的匹配项更新也一样。

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,则可选) - query - 用于自动查找锚点的搜索查询(如果提供了 anchor,则可选) - 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 tokens)

MCP 服务器实现

位置:/Users/YOUR_USERNAME/.claude/plugins/marketplaces/thedotmack/plugin/scripts/mcp-server.cjs

角色:轻量包装器,将 MCP 协议转换为 HTTP API 调用

主要特点: - 约 312 行代码(旧实现中为约 2,718 行) - 无业务逻辑——仅协议转换 - 单一事实来源:Worker HTTP API - 带有 additionalProperties: true 的简单 schema

处理器示例:

{
  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 workerPort = process.env.CLAUDE_MEM_WORKER_PORT ?? "<worker-port>";
    const workerBaseUrl = `http://127.0.0.1:${workerPort}`;
    const url = `${workerBaseUrl}${endpoint}?${searchParams}`;
    const response = await fetch(url);
    return await response.json();
  }
}

Worker HTTP API

位置:src/services/worker-service.ts

端口:可配置的 worker 端口。默认为按用户分配(37700 + (uid % 100)),可通过 CLAUDE_MEM_WORKER_PORT 覆盖。

搜索端点:

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 tokens - 目的:在投入 tokens 之前,先概览已存在的内容 - 决策点:“哪些观察是相关的?”

第 2 层:上下文(时间线) - 内容:围绕某一点的观察时间线视图 - 成本:根据深度变化 - 目的:理解叙事脉络,查看某一点的前因后果 - 决策点:“我是否需要完整细节?”

第 3 层:详情(获取观察) - 内容:完整的观察数据(叙事、事实、文件、概念) - 成本:每条观察约 500-1,000 tokens - 目的:深入查看经过验证的相关观察 - 决策点:“将知识应用到当前任务”

Token 效率

传统 RAG 方法:

Fetch 20 observations upfront: 10,000-20,000 tokens
Relevance: ~10% (only 2 observations actually useful)
Waste: 18,000 tokens on irrelevant context

三层工作流:

Step 1: search (20 results)        ~1,000-2,000 tokens
Step 2: timeline around relevant IDs ~300-600 tokens
        Review context, select 3 relevant IDs
Step 3: get_observations (3 IDs)   ~1,500-3,000 tokens
Total: ~2,800-5,600 tokens

10 倍节省:在获取完整详情之前,先在索引层面进行过滤

架构演进

之前:复杂的 MCP 实现

方法:9 个 MCP 工具,带有详细的参数 schema

Token 成本:每个会话中,工具定义约消耗 2,500 tokens - search_observations - 全文搜索 - find_by_type - 按类型过滤 - find_by_file - 按文件过滤 - find_by_concept - 按概念过滤 - get_recent_context - 最近的会话 - get_observation - 获取单条观察 - get_session - 获取会话 - get_prompt - 获取 Prompt - help - API 文档

问题: - 重叠的操作(search_observations 与 find_by_type) - 复杂的参数 schema - 没有内置的工作流指导 - 会话启动时 Token 成本高

代码规模:mcp-server.ts 约 2,718 行

之后:精简的 MCP 实现

方法:4 个 MCP 工具,遵循三层工作流

Token 成本:约 312 行代码,工具定义更简洁

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

优势: - 渐进式披露内置于工具设计 - 没有重叠的操作 - 简单的 schema(additionalProperties: true) - 清晰的工作流模式 - 约 10 倍 Token 节省

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

关键洞察

之前:渐进式披露是需要 Claude 记住的事情

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

三层工作流模式在结构上让 Token 浪费变得困难: - 不先从搜索获取 ID,就无法获取详情 - 不看到工作流提醒(important_workflow),就无法搜索 - 时间线在索引与完整详情之间提供了中间地带

配置

Claude Desktop

添加到 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 协议安全

  • Stdio 传输(无网络暴露)
  • 仅在配置的工作端口上提供本地 HTTP API
  • 无需身份验证(仅限本地开发)

性能

FTS5 全文搜索: 典型查询低于 10ms

MCP 开销: 极小——简单的协议转换

缓存: HTTP 层允许响应缓存(未来增强)

分页: 使用 offset/limit 高效实现

批处理: get_observations 在单次调用中接受多个 ID

相较于替代方案的优势

与传统 RAG 对比

传统 RAG: - 预先获取所有内容 - 高 Token 成本 - 低相关性比率

3 层 MCP: - 仅获取所需内容 - 约 10 倍 Token 节省 - 100% 相关性(由 Claude 选择获取内容)

与之前的 MCP 实现(v5.x)对比

之前(9 个工具): - 复杂的模式 - 重叠的操作 - 无工作流指导 - 定义中约 2,500 Token

当前(4 个工具): - 简单的模式 - 清晰的工作流 - 内置指导 - 约 312 行代码

与基于技能的方法(先前)对比

技能方法: - 需要单独的技能文件 - 通过 curl 直接调用 HTTP API - 通过技能加载实现渐进式披露

MCP 方法: - 原生 MCP 协议(更好的 Claude 集成) - 更简洁的架构(协议转换层) - 同时适用于 Claude Desktop 和 Claude Code - 更易于维护(无需技能文件)

迁移: 基于技能的搜索已被移除,取而代之的是精简的 MCP 架构。

故障排查

要进行直接的 API 检查,请先设置工作端口:

WORKER_PORT=$(jq -r .CLAUDE_MEM_WORKER_PORT ~/.claude-mem/settings.json)

MCP 服务器未连接

症状: 工具未出现在 Claude 中

解决方案: 1. 检查配置中的 MCP 服务器路径 2. 验证工作服务是否正在运行:curl http://127.0.0.1:$WORKER_PORT/api/health 3. 重启 Claude Desktop/Code

工作服务未运行

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

解决方案:

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

搜索结果为空

症状: search() 不返回任何结果

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

后续步骤

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/claude-mem