跳转至

托管服务器(Beta)

Warning

此功能尚处早期,迭代很快。 下面所述的托管服务器采集(capture)、召回(recall)、计量(metering)和删除路径都是真实可用且经过测试的,但围绕它们的 UX 和开发者体验仍在构建中——目前还没有完善的仪表盘、引导流程或自助注册。预期底层管线(plumbing)是可靠的,而表面铺装(paving)尚未完工。随着仪表盘逐步接入,路由、环境变量名以及首个密钥的引导流程可能会调整。如果你正在做集成,请固定版本。

托管服务器是 claude-mem 的云端部分:一个基于 Postgres 的 HTTP 服务(/v1),外加一个独立的 BullMQ 生成 worker。本地插件将记忆保存在你机器上的 ~/.claude-mem/claude-mem.db 中,而托管服务器则按团队和项目将记忆保存在 Postgres 中,并通过经过认证的链接将其暴露给任意 MCP 客户端。

以下三项能力一同落地,并在本文档中一并说明:

远程 MCP 召回

将经过认证的链接粘贴到 Claude Code 中,即可召回你的云端记忆——只读,并限定在团队/项目范围内。

付费就绪

可选加入的速率限制、每月请求/Token 配额,以及用量计量——付费层级所需的防护机制。

数据删除

被遗忘权:可遗忘单条记忆,或清除为某个项目采集的全部数据。

系统结构

 Claude Code (or any MCP client)
        │  Authorization: Bearer cm_...
        ▼
 ┌─────────────────────────────┐        ┌──────────────────────────┐
 │  HTTP server  (/v1)          │  jobs  │  BullMQ generation worker │
 │  - auth (api-key mode)       ├───────▶│  claude-mem server         │
 │  - rate limit / quota / meter │        │    worker start            │
 │  - REST + /v1/mcp recall      │        │  - provider call           │
 │  - data deletion              │        │  - writes observations     │
 └──────────────┬───────────────┘        └────────────┬─────────────┘
                │                                       │
                ▼                                       ▼
        ┌───────────────────────────────────────────────────┐
        │  Postgres  (teams, projects, observations,         │
        │  agent_events, server_sessions, generation jobs,   │
        │  api_keys, usage_events, audit_log)                │
        └───────────────────────────────────────────────────┘

每一行都以 (team_id, project_id) 划分范围。一个 API 密钥始终携带团队范围,并可选携带项目范围;该范围约束着每一次读取、写入和删除。

身份验证

设置 CLAUDE_MEM_AUTH_MODE=api-key,并在每个请求中发送 Authorization: Bearer <key>。权限范围(scope)控制访问:

  • 读取端点(search、context、recall、usage)需要 memories:read。
  • 写入端点(ingest、key issuance、deletion)需要 memories:write。

密钥以 SHA-256 哈希形式存储在 api_keys 表中;原始的 cm_... 值仅在签发时显示一次。

远程认证的 MCP 召回

/v1/mcp 是一个 streamable-HTTP MCP 服务器。它是用户粘贴到 Claude Code 中以召回云端记忆的安全链接。该服务器只读,并使用与 REST 路由相同的 API 密钥(memories:read)进行认证;密钥所属的团队——以及当密钥限定项目时的项目——约束每一次读取。

claude mcp add --transport http claude-mem <server-base>/v1/mcp \
  --header "Authorization: Bearer cm_..."

智能搜索(Smart search)是默认的三步工作流:先查看索引,再检查时间线上下文,最后只获取选中的记录。没有自动或引导模式。每个工具都使用已认证的团队以及请求中指定的项目:

工具 参数 返回
search { projectId, query, limit? } 来自全文搜索的紧凑索引,包含 ID。
timeline { projectId, anchorId, depthBefore?, depthAfter? } 围绕所选 ID 的时间顺序上下文。
get_observations { projectId, ids } 仅针对所选 ID 的有用详情,并标记被缩短的部分。
context { projectId, query, limit? } 旧版聚焦上下文查询;建议优先使用 Smart 工作流。
recent { projectId, limit? } 项目最新观测记录的紧凑索引。

Note

该传输是无状态的——每个请求一个 MCP 服务器 + 传输——因此它在负载均衡器后面不需要会话亲和性。有意不提供会修改数据的工具:粘贴的召回链接永远无法写入或删除。每次读取都会作为 observation.read 事件写入 audit_log,与 POST /v1/search 相同。

连接客户端:密钥签发与连接

两条路由将“我有一台服务器”变成“Claude Code 正在召回我的云端记忆”:

  • POST /v1/keys(需要 memories:write)为调用方的团队生成一个只读 API 密钥,并返回一条可直接粘贴的连接命令。原始密钥仅显示一次。请求体:{ "expiresInDays"?: number }。签发需要写权限,这样只读密钥就无法自行升级以获取更多密钥。
{
  "id": "...",
  "apiKey": "cm_...",
  "scopes": ["memories:read"],
  "expiresAt": null,
  "mcpUrl": "https://<host>/v1/mcp",
  "connectCommand": "claude mcp add --transport http claude-mem https://<host>/v1/mcp --header \"Authorization: Bearer cm_...\""
}
  • GET /v1/connect(需要 memories:read)返回带有 <YOUR_API_KEY> 占位符的相同命令——GET 永远不会签发新密钥。mcpUrl 由 CLAUDE_MEM_PUBLIC_URL 构建(在代理或负载均衡器后面时推荐设置);如果未设置,则使用请求的主机名。

Warning

首个密钥的引导流程仍是最粗糙、尚未打磨的部分。 为团队生成第一个密钥仍然需要一个会话门控路径(Web 仪表盘),因为 POST /v1/keys 本身需要一个写权限密钥。better-auth 的 apiKey() 插件存在,但它写入的存储与这些路由在认证时使用的 Postgres api_keys 表不同——将 better-auth 的 org → team 映射接通,是剩余的工作,也是未来仍待完成的最大一部分开发者体验(devex)工作。

这些防护在认证之后运行,并且通过环境变量选择启用。未设置(默认情况)意味着没有速率限制、没有配额、也没有计量——行为与未安装这些防护的服务器完全相同。每个防护都故障开放:后端存储错误绝不会阻止合法请求。

环境变量 效果 超出限制时的响应
CLAUDE_MEM_RATE_LIMIT_PER_MIN 每个 API 密钥每分钟的最大请求数。 429,附带 Retry-After 和 X-RateLimit-* 响应头。
CLAUDE_MEM_MONTHLY_REQUEST_CAP 每个团队每个自然月(UTC)的最大请求数。 402 quota_exceeded。
CLAUDE_MEM_MONTHLY_TOKEN_CAP 每个团队每月最大 provider Token 数。仅限制写入——读取保持开放,因此超出预算的团队仍然可以回忆。 达到上限时返回 402。
CLAUDE_MEM_USAGE_METERING=1 每次经过认证的调用记录一个 request 用量事件(即发即忘)。 —

Token 与 observation 计量由生成 worker 写入同一个 usage_events 表,因此用量反映的是提供方的实际消耗,而不仅是 HTTP 调用。

GET /v1/usage 返回调用方团队当前月份按类型统计的总数:

{ "since": "2026-06-01T00:00:00.000Z", "usage": { "request": 1280, "observation": 44 } }

Note

“仅限制写入”是刻意为之:摄取驱动生成,而生成消耗 Token。超出 Token 预算的团队仍然可以读取已有记忆——你绝不会因为计费问题而将某人锁在自己的数据之外。

数据删除(遗忘)

被遗忘权。两条路由都需要 memories:write 权限,并且都限定在调用方的团队范围内。两者都会写入一条 audit_log 记录。

  • DELETE /v1/memories/:id — 删除一条观察记录;其 observation_sources 会级联删除。如果该团队不存在这条观察记录,则返回 404。审计事件为 observation.deleted。

  • DELETE /v1/projects/:projectId/memory — 在一个事务中清除某个项目的全部已捕获内容:观察记录、原始 agent 事件、服务器会话和生成任务。项目外壳(配置/成员关系)会保留,以便团队继续使用它。返回按表统计的 counts。如果该项目不属于该团队,返回 404。审计事件为 project.memory_purged。

{ "purged": true, "projectId": "...", "counts": { "observations": 42, "agentEvents": 17, "sessions": 3, "jobs": 17 } }

Note

删除在 SQL 层就限定在团队范围内,因此一个密钥只能擦除自己团队的数据——跨团队或不存在的 projectId 会返回 404,而不是一个具有误导性的成功响应。

事件生成语义

摄取(POST /v1/events)接受两个控制观察记录生成的查询标志:

  • generate=false — 写入事件,但不将生成任务加入队列。
  • wait=true — 返回 generationJob 描述符,使调用方可以轮询 GET /v1/jobs/:id 以获取完成状态。

未设置 wait=true 时,响应包含新的事件行以及一个尽力而为的 generationJob 字段。设置 wait=true 时,该字段始终会被填充(仅当显式禁用生成时才会是 null)。实际的提供方调用发生在独立的 BullMQ worker 中(claude-mem server worker start)——HTTP 路径从不阻塞等待提供方响应。

生成并发性

默认情况下,生成 worker 在其两条通道中各一次处理一个任务:event(逐事件观察记录)和 summary(会话摘要)。如果事件到达的速度超过一次一个任务的处理速度,任务仍然会完成,但积压会增加,观察记录会在其所描述的工作发生数小时后才落地。在生成 worker 上设置 CLAUDE_MEM_SERVER_GENERATION_CONCURRENCY=N,即可每条通道并行运行最多 N 个任务。两条通道都使用该值,因此单个 worker 进程最多可以有 2N 个提供方调用同时进行。根据你的提供方速率限制来调整 N 的大小。高于 64 的值会被限制为 64,无效值会被忽略并发出警告。

如果某个 worker 不再取得进展,可以回收过期的处理锁供另一次尝试使用。只有在仍持有 Postgres 处理锁的情况下,每次尝试才可以持久化观察记录或报告失败。被回收尝试的响应会被丢弃,因此它无法让替代尝试成功或失败。这一所有权检查同样适用于会话摘要,并且在提供方调用期间不会持有数据库锁。恢复仍然可能需要另一次付费的提供方调用;它并不保证提供方执行恰好一次。

通过网关使用 Claude 提供方

当 CLAUDE_MEM_SERVER_PROVIDER=claude 时,生成 worker 会调用 api.anthropic.com。要将其调用通过一个兼容 Anthropic 的网关(Cloudflare AI Gateway、LiteLLM、公司代理)发送,以获得逐调用日志、成本和速率限制,请在生成 worker 上设置以下内容:

设置 描述
CLAUDE_MEM_ANTHROPIC_BASE_URL 网关的 Anthropic 兼容基础 URL;会追加 /v1/messages
CLAUDE_MEM_ANTHROPIC_CUSTOM_HEADERS 每个请求上的额外头,例如网关自身的认证头,格式与 Claude Code 的 ANTHROPIC_CUSTOM_HEADERS 相同:每行一个 Name: Value。它们不能替代 API 密钥、版本或内容类型。不是有效头的行会被跳过,并给出一个包含行号(绝不包含其文本)的警告

Claude Code 自身的 ANTHROPIC_BASE_URL 和 ANTHROPIC_CUSTOM_HEADERS 不会被读取,因此从为 Claude Code 设置了这些变量的 shell 中启动服务器时,不会将其密钥发送到该网关。

cmem.ai 记忆密钥(cm_pro_…)在此提供方上会被拒绝,无论是作为 API 密钥还是放在自定义头中;它只能在 cmem.ai 网关上使用。

自定义生成提供方(高级)

生成 worker 自带 claude、gemini 和 openrouter 提供方,每个提供方都从其环境中读取一组凭据。如果你的部署需要其他方案,例如每个项目使用不同的密钥,请设置 CLAUDE_MEM_SERVER_PROVIDER=custom,并将 CLAUDE_MEM_CUSTOM_PROVIDER_MODULE 指向一个 JavaScript 模块。该模块必须导出 createProvider(helpers),它返回一个带有 generate(context) 方法的对象。helpers 为模块提供本服务器的 prompt 构建器、其 Anthropic 客户端(ClaudeObservationProvider,接受 baseUrl)、其可重试错误类、已解析的 maxOutputTokens,以及一个 apiVersion(当前为 1),只要这些契约中的任何一个发生变化,该版本号就会改变。

Warning

该模块在生成 worker 内运行,并持有该进程拥有的所有内容:数据库 URL、每个 provider 的密钥以及 Redis 凭据。请像对待你部署的任何其他代码一样对待它。该路径仅从进程环境读取,绝不从 settings.json 或 API 路由读取。它必须是绝对路径,且 worker 在加载模块时会记录该路径及文件的 sha256。

按含义搜索

当 Postgres 中使用 pgvector 0.8 或更高版本时,搜索不仅按关键词排序,还会按含义排序:/v1/search、/v1/context 以及 MCP 的 search 和 context 工具会将关键词排名与最接近查询向量的 observations 融合,因此查询可以找到与其没有任何共同词语的记忆。server 在进程内使用 CLAUDE_MEM_EMBEDDING_MODEL 所指定的模型对查询进行嵌入,生成 worker 则对其写入的 observations 进行嵌入。Docker 镜像包含默认模型;如需包含另一个模型,可使用 --build-arg EMBEDDING_REPO=<repo> 构建镜像,该模型的仓库位于 src/services/vector/models.ts 中;否则该模型会在首次使用时下载。如果没有 pgvector,或模型无法加载,则搜索仅按关键词进行。

环境变量 效果
CLAUDE_MEM_SERVER_VECTOR_SEARCH auto(默认)对于新数据库为开启,对于在按含义搜索功能之前创建的数据库为关闭,因此升级不会增加嵌入工作。true 将其开启;已存储的 observations 会在后台获取向量。false 则仅按关键词搜索。请在 server 和 worker 上设置相同的值。
CLAUDE_MEM_EMBEDDING_MODEL all-MiniLM-L6-v2(默认)、paraphrase-multilingual-MiniLM-L12-v2、multilingual-e5-small 或 granite-embedding-97m-multilingual-r2。多语言模型在中文、日文和韩文搜索上远好于默认模型;嵌入成本为默认模型的 1.2(MiniLM-L12)到 4.3(granite)倍。查询只会匹配来自同一模型的向量,因此更改后,已存储的 observations 会在后台重新嵌入,按含义搜索会在它们完成嵌入后覆盖它们。请在 server 和 worker 上设置相同的值。
CLAUDE_MEM_EMBEDDING_BACKFILL_THREADS 在已存储 observations 仍需要向量时,模型可使用的 CPU 线程数,直到下次重启。空值(默认)为机器线程数的一半;0 表示全部线程。

GET /v1/info 会报告 vectorSearch:它是否可用、使用的是哪个模型、按含义搜索目前无法找到多少条 observations,以及最后一条嵌入错误。

在 Docker 之外,模型(约 90 MB)会在首次启动时从 huggingface.co 下载。server 会在启动时开始加载它;在它准备好之前,搜索仅按关键词进行,新记忆不会保存向量(请求最多等待两秒)。一旦模型加载完成,后台回填会嵌入这些记忆;最迟在下次启动时也会执行。 除非设置了 CLAUDE_MEM_SERVER_VECTOR_SEARCH=false,否则 npx claude-mem server start、restart 和 worker start 会安装嵌入器的依赖包(约 300 MB,仅一次)。

向量每 observation 约占用 28 KB 的 Postgres 存储空间(约 40,000 条 observations 需要 1 GB),另加每条嵌入所需的 CPU 时间。

端点参考

所有端点都挂载在 /v1 下;旧版 worker 路由仍位于 /api 下。

GET    /healthz
GET    /v1/info
GET    /v1/projects
POST   /v1/projects
GET    /v1/projects/:id
POST   /v1/sessions/start
POST   /v1/sessions/:id/end
GET    /v1/sessions/:id
POST   /v1/events                 # ?generate= ?wait=
POST   /v1/events/batch
GET    /v1/events/:id
POST   /v1/memories
GET    /v1/memories/:id
PATCH  /v1/memories/:id
DELETE /v1/memories/:id           # forget one observation
POST   /v1/search
POST   /v1/context
POST   /v1/timeline
POST   /v1/observations/batch
ALL    /v1/mcp                    # remote authenticated MCP recall
POST   /v1/keys                   # mint a read-only key (write scope)
GET    /v1/connect                # connect command with key placeholder
GET    /v1/usage                  # current-month usage totals
DELETE /v1/projects/:projectId/memory   # purge a whole project
GET    /v1/audit?projectId=<id>

/v1/search、/v1/context 以及 MCP 的 search 工具使用 Postgres 全文搜索(英文词干提取)来匹配关键词。普通词语的匹配方式取决于 server 运行的 Postgres:

  • 使用 pg_textsearch 时(Docker Compose 镜像):普通词语匹配查询的任意词项,并按 bm25 排序,因此稀有词比常见词权重更高,像 when did we change the retry limit 这样的问题会首先找到关于 retry limit 的记忆。不包含任何词项的记忆会被排除。
  • 未使用 pg_textsearch 时(任何其他 Postgres):普通词语必须全部出现,并像以前一样按 ts_rank 排序。

Web 搜索语法在两种情况下含义相同:"quoted phrase" 按该顺序匹配词语,-term 排除包含该词项的记忆,or 匹配任意一侧。使用其中任意一种语法的查询都会像以前一样精确过滤;bm25 仅对匹配结果排序。

升级 Postgres 镜像(Docker Compose)

docker-compose.yml 会在本地根据 docker/postgres/Dockerfile 构建其 Postgres 镜像,命名为 claude-mem-postgres:17:基于 Debian(trixie)的 Postgres 17,并带有来自 PostgreSQL 项目 apt 仓库的 pgvector 和 pg_textsearch 扩展。不会从第三方注册表拉取任何预构建镜像。该镜像约 650 MB,而早期版本使用的 postgres:17-alpine 镜像为 424 MB。

从 Alpine 迁移到 Debian 会更改现有数据卷下的 C 库(从 musl 变为 glibc),这会改变文本的排序方式。依赖 C 库排序规则对文本进行排序的索引必须重建,否则通过它们进行查找可能会漏掉行。一次性的 postgres-collation 服务会在 server 和 worker 启动前完成此操作:它会查找记录到的排序规则版本与 C 库不同的数据库,仅对依赖排序规则对文本排序的索引执行 REINDEX(vector、全文和 jsonb 索引不受影响),并记录新的排序规则版本。第二次启动时则无需做任何事。新数据库使用 Postgres 内置的 C.UTF-8 区域设置,因此之后 C 库的更改不会影响它们。

要升级现有技术栈:

  1. 首先备份。 在旧技术栈仍运行时:
    docker compose exec postgres pg_dumpall -U "$POSTGRES_USER" > claude-mem-backup.sql
    
    也可以复制卷:先 docker compose down,然后 docker run --rm -v <project>_postgres-data:/from -v "$PWD":/to alpine tar czf /to/postgres-data.tgz -C /from .
  2. 仅构建并启动 Postgres,使用新镜像:
    docker compose build postgres
    docker compose up -d postgres
    
  3. 试运行,列出将要重建的索引,而不会更改任何内容:
    docker compose run --rm -e DRY_RUN=1 postgres-collation
    
  4. 启动其余部分。 docker compose up -d 会执行重建,然后启动服务器和 worker。对于典型数据库,重建只需数秒。

回滚。 从步骤 1 恢复备份;不要将旧镜像指向升级后的卷。重建后,其文本索引是按 glibc 排序的;一旦服务器创建了 pgvector 或 pg_textsearch 对象,postgres:17-alpine(这两种扩展都不包含)就无法使用它们。切回之前的 docker-compose.yml,然后要么把卷副本放回去(docker compose down、docker volume rm <project>_postgres-data、重新创建卷并把 postgres-data.tgz 解压进去),要么在全新卷上启动旧栈,并用 psql -U "$POSTGRES_USER" -d postgres -f claude-mem-backup.sql 加载备份。

已稳固的部分与即将到来的部分

Note

当前已稳固: 基于 Postgres 的多租户存储、带读/写作用域的 api-key 认证、/v1/mcp 召回链接、可选启用的速率限制 + 配额 + 计量,以及可审计的数据删除。所有这些都由 Postgres 门控的 e2e 测试套件覆盖。

仍在建设中(UX / devex): 一个用于初始密钥引导和密钥管理的 Web 仪表盘、自助式注册引导、构建在计量原语之上的账单/套餐 UI,以及比粘贴 CLI 命令更流畅的“将 Claude Code 连接到我的云记忆”流程。这些是接下来的重点——上面的原语就是它们将依托的基础。

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