托管服务器(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 返回调用方团队当前月份按类型统计的总数:
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 库的更改不会影响它们。
要升级现有技术栈:
- 首先备份。 在旧技术栈仍运行时:
也可以复制卷:先
docker compose down,然后docker run --rm -v <project>_postgres-data:/from -v "$PWD":/to alpine tar czf /to/postgres-data.tgz -C /from . - 仅构建并启动 Postgres,使用新镜像:
- 试运行,列出将要重建的索引,而不会更改任何内容:
- 启动其余部分。
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