数据截至 (上游 commit 149589ae7e6b)
MCP 服务器:把记忆装进任意 AI 助手
30 秒导读: 这是 Supermemory 三条分发路径里最主流的一条——把「远端记忆」包装成一个标准 MCP(Model Context Protocol)服务器,任何支持 MCP 的助手(Claude Desktop、Cursor、ChatGPT、Windsurf……)填一个 URL 就能用上
search_memory/add_memory等工具。本章讲apps/mcp这个 Cloudflare Worker:它怎么部署、怎么鉴权、注册了哪些工具、状态放在哪、以及几处防坑设计。数据形态(文档/记忆/画像/空间)见 01-data-model;「一行withSupermemory挂中间件」那条另一条分发路径见 03-framework-middleware。
上游重构提示: 本次同步的上游 commit 对
apps/mcp做了一次大重构,本章多节已重写: ① 单文件src/server.ts/src/client.ts/src/auth.ts/src/index.ts拆进src/server/子包 (tools/、resources/、auth/、client/ 各自成模块);② 鉴权换轨——旧版「API key(sm_前缀走/v3/session)+ OAuth 令牌(走/v3/mcp/session-with-key兑换 apiKey)」的双模自省已移除, 改为每个请求用远程 JWKS 验 JWT(src/server/auth/index.ts);③ 每会话一个 Durable Object 的McpAgent模式已移除——现在是每个 HTTP 请求现场新建McpServer的无状态模式,唯一的 持久状态是SpaceStateDO 里的「活跃空间」与「上传会话」;④ 工具面从 memory/recall 两个大工具 扩成 15 个细粒度工具,并引入 MCP App「视图」(picker/save/upload/graph)与 RBAC 空间权限。
1. 这是什么(零基础也能懂)
一句话定义: apps/mcp 是一个独立部署的 MCP 服务器,它把 Supermemory 的记忆能力,变成 AI 助手能直接调用的一组「工具」。
先说清 MCP 是什么。MCP(模型上下文协议)是 AI 助手和外部能力之间的标准插座——助手是插头,任何遵守 MCP 的服务是插座。一旦某个能力包成 MCP 服务器,Claude Desktop、Cursor、ChatGPT 这些客户端不改代码就能接上它。
那这个服务器给助手插上了什么?长期记忆。 大模型天生没有跨对话的记忆,聊完就忘。接上这个服务器后,助手多出这些动作(完整清单见 §6):
| 助手能做的事 | 对应工具 | 白话 |
|---|---|---|
| 搜记忆 + 用户画像 | search_memory | "关于我 的编程偏好,你记得什么?" |
| 记住 / 忘掉信息 | add_memory(save/forget) | "记一下我用 TypeScript"/"把北京那条删了" |
| 看有哪些空间 | listSpaces | "我的记忆分了哪几个项目?" |
| 切换活跃空间 | select-space / set-active-tag | "以后默认存到工作空间" |
| 看记忆关系图 | memory-graph(App 视图) | 弹出一张力导向图 |
| 传文件入库 | upload-file / prepare-file-upload | "把这个 PDF 记进去" |
| 查自己是谁、有什么权限 | whoAmI | 会话身份 + 空间访问权 |
用起来什么样。 用户根本不写代码,只在 MCP 客户端配置里填一个 URL:
{
"mcpServers": {
"supermemory": { "url": "https://mcp.supermemory.ai/mcp" }
}
}
之后助手在对话里自动调这些工具。首次连接会走 OAuth 让用户登录授权(§5)。
一句话直觉。 把这个服务器想成记忆能力的「转接头」:一头是标准 MCP 插口(什么助手都能插),另一头接的是 Supermemory 的云端 API。转接头本身几乎不存数据(只记"你当前选了哪个空间"),它的活是鉴权 + 把 MCP 的工具调用翻译成对 Supermemory API 的调用。
2. 顶层全景(它大概怎么转)
这一节讲:一次请求从客户端进来,到底路过了哪些部件。
先看整体拓扑。这个服务器夹在「MCP 客户端」和「Supermemory 主 API」中间,自己不碰数据库:
┌──────────────┐ MCP over HTTP ┌───────────────────────────────────────┐
│ MCP 客户端 │ (JSON-RPC/SSE) │ MCP Worker (mcp.supermemory.ai) │
│ Claude/ │ ─────────────────► │ Cloudflare Workers + Hono │
│ ChatGPT/Cursor│ │ │
└──────────────┘ │ ┌─────────────────────────────────┐ │
▲ │ │ Hono 路由 (server/index.ts) │ │
│ 401 + WWW-Authenticate │ │ · / · /.well-known/* │ │
│ (发现鉴权服务器) │ │ · /mcp(验签后转交) / /upload/* │ │
│ │ └───────────────┬─────────────────┘ │
│ │ ▼ │
│ │ ┌─────────────────────────────────┐ │
│ │ │ 每请求新建 McpServer │ │
│ │ │ createSupermemoryServer │ │
│ │ │ · 注册 15 个工具/资源/prompt │ │
│ │ │ · PostHog 埋点包装 │ │
│ │ └───────┬─────────────────┬───────┘ │
│ │ │ │ │
└────────────────────────────┼──────────┼─────────────────┼─────────┘
│ ▼ ▼
JWT 验签(远程 JWKS) │ SpaceState DO(活跃空间/ SupermemoryClient
◄── 每请求一次 ─────────┘ 上传会话,按 org+user 键) (SDK + fetch)
│
▼
┌─────────────────────┐
│ Supermemory 主 API │
│ /v3/* · /v4/* │
└─────────────────────┘
怎么读这张图: 请求从左上进,先被 Hono 路由拦住做 JWT 验签(拿主 API 的 JWKS 公钥本地验),
构造 ActorContext 后现场 createSupermemoryServer 注册好工具再处理;工具通过
SupermemoryClient 回调主 API 完成实际读写;「活跃空间」这类少量跨请求状态单独放 SpaceState DO。
各部 件一句话职责:
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
| Hono app | HTTP 入口、CORS、.well-known 鉴权发现、/mcp 验签转交、/upload/* | apps/mcp/src/server/index.ts |
validateOAuthToken/fetchSession | JWT 验签(远程 JWKS)与会话拉取 | apps/mcp/src/server/auth/index.ts |
createSupermemoryServer | 每请求新建 McpServer:注册工具/资源/prompt + 埋点包装 | apps/mcp/src/server/server.ts |
SupermemoryClient | 薄封装:调 Supermemory SDK 与几个裸 fetch,统一错误映射 | apps/mcp/src/server/client/index.ts |
SpaceState(DO) | 按 org+user 存活跃空间;按 uploadId 存一次性上传会话 | apps/mcp/src/server/space-state.ts |
effectiveContainerTagAccess | RBAC:会话权限 → 每个空间的读/写 | apps/mcp/src/server/auth/rbac.ts |
analytics | PostHog 埋点(工具面/耗时/客户端),包装 registerTool | apps/mcp/src/server/analytics.ts |
主线走一遍(高层): 客户端发 tools/call add_memory → Hono /mcp 处理器取 Authorization
头 → validateOAuthToken 用 JWKS 验签得 AuthUser → 构造 ActorContext → createMcpHandler
现场建 server → add_memory 处理器解析有效空间 → SupermemoryClient.createMemory 调主 API 落库
→ 返回一句 Memory saved (ID: …)。
3. 部署形态:Workers + 无状态请求处理 + 一个状态 DO
这一节讲:这个服务器「活在哪」,状态放哪,以及为什么不再是"每会话一个 DO"。
运行时是 Cloudflare Workers。 wrangler.jsonc 声明了两个 Durable Object 绑定
(apps/mcp/wrangler.jsonc:24-35):
"durable_objects": {
"bindings": [
{ "name": "MCP_SERVER", "class_name": "SupermemoryMCP" }, // 旧协议 DO,仅保回滚
{ "name": "SPACE_STATE", "class_name": "SpaceState" } // 新:空间/上传状态
]
}
请求处理是无状态的(这是本次重构的核心变化)。 README 的 "Runtime Model" 一节写得很直白
(apps/mcp/README.md:6):每个 HTTP 请求都现场新建一个 McpServer,没有 MCP 协议会话、
也没有协议 Durable Object;现代 MCP 2026-07-28 协议之外还带 stateless 兼容模式照顾 2025 老客户端。
代码上就是 handleMcpRequest 里每次都调
createMcpHandler(() => createSupermemoryServer(...), { route: "/mcp", legacy: "stateless", ... })
(apps/mcp/src/server/index.ts:198-213)。
那什么状态还需要活过一次请求? 只有两样,都塞进 SpaceState DO
(apps/mcp/src/server/space-state.ts:17):
| 状态 | key | 谁读写 |
|---|---|---|
| 活跃空间(用户上次选的默认空间) | space:[orgId,userId](space.ts:4-9 spaceStateName) | set-active-tag 写,所有空间感知工具读 |
| 一次性文件上传会话(token 哈希 + 过期) | upload:<uuid>(space-state.ts:21) | prepare-file-upload 建,/upload/:id 消费 |
旧 DO 类只是回滚保险。 SupermemoryMCP 现在是一个空壳:
"Kept for one rollout so the old protocol Durable Object class remains deployable and
rollback-safe. No request path uses this class anymore."(apps/mcp/src/server/legacy-protocol-state.ts:3-5)。
4. 请求入口(Hono 路由)与鉴权发现
这一节讲:HTTP 层怎么 组织,以及 MCP 客户端如何「发现」该去哪登录。
入口是一个 Hono app(apps/mcp/src/server/index.ts:18)。CORS 全放行,但特意 expose
WWW-Authenticate 响应头(server/index.ts:43-52)——它是 OAuth 发现的关键,浏览器默认不让
JS 读,必须显式暴露。
路由分四类:
| 路由 | 作用 | 位置 |
|---|---|---|
GET / | 服务器名/版本/文档链接的自我介绍 JSON | server/index.ts:54-61 |
GET /.well-known/oauth-protected-resource[/mcp] | 告诉客户端「我是受保护资源,去哪个授权服务器登录」 | server/index.ts:63-77 |
GET /.well-known/oauth-authorization-server | 代理:把主 API 的授权服务器元数据透传回来(兼容不读 authorization_servers 的客户端) | server/index.ts:83-101 |
ALL /、/mcp、/mcp/ | 真正的 MCP 端点,验签后转交 | server/index.ts:270-272 |
POST /upload/:uploadId | 一次性文件上传端点(§7) | server/index.ts:220-268 |
鉴权发现遵循 OAuth「受保护资源」规范。 客户端不带令牌来敲 /mcp,服务器回
401 + WWW-Authenticate,用 resource_metadata 指向自己的 .well-known 地址
(unauthorizedResponse,server/index.ts:131-144);令牌无效则回带 error="invalid_token"
的 JSON-RPC 错误体(server/index.ts:146-163)。元数据里写明真正的授权服务器是主 API
的 /api/auth(resourceMetadata,server/index.ts:67-73)。
另有一个小而新的路由:GET /.well-known/openai-apps-challenge(server/index.ts:79-81),
回一个环境变量里的挑战串——接 OpenAI Apps 分发校验用。
MCP 端点怎么转交。 handleMcpRequest(server/index.ts:166-218)先取 Authorization
头剥掉 Bearer (:165-166)→ 验签(§5)→ 构造 ActorContext { userId, organizationId, bearerToken, oauthClientId }(:182-187)→ createMcpHandler 现场建 server 处理,
并带上 authInfo(OAuth clientId/scopes,:107-124)。整套处理没有任何跨请求的协议会话;
allowedOriginHostnames(:98-105)给 handler 限了浏览器来源白名单(Claude/ChatGPT/Gemini/Grok 等,
可配)。
5. 鉴权:每个请求验一次 JWT(远程 JWKS)
这一节讲全章变化最大的部分:令牌怎么变成可信的调用身份。
旧版双模自省已移除。 旧设计里 Authorization 可能是 sm_ API key(走 /v3/session 自省)
或 OAuth 令牌(走 /v3/mcp/session-with-key 兑换真实 apiKey)。新版只有一条路:
Authorization: Bearer <JWT>
│
├─① 取公钥 getRemoteJwks(`${apiUrl}/api/auth/jwks`) 〔按 jwksUrl 缓存 Map〕
│ (server/auth/index.ts:15-28)
├─② 本地验签 jose.jwtVerify(token, keySet, { issuer, audience }) (:64-67)
│ issuer = <apiUrl>/api/auth audience = MCP 资源 URL
├─③ 取声明 payload.sub → userId;payload.organization_id → organizationId (:68-76)
│ scope 字符串拆成 scopes[];azp/client_id → oauthClientId (:78-94)
└─④ 组装 AuthUser { userId, organizationId, bearerToken: token, … } (:85-97)
关键点:
- 验证是本地密码学验证,不是网络自省。 只有取公钥(JWKS)那次走网络,且按 URL 缓存
(
server/auth/index.ts:21-28);每个请求的验签都是本地jwtVerify,又快又不给主 API 添堵。 - 令牌原样透传。
AuthUser.bearerToken就是传入的 JWT(:88),后续SupermemoryClient直接拿它当 Bearer 调主 API——主 API 自己认得自己签的令牌,不存在"兑换 apiKey"这一步。 - 失败一律
null。 验签异常只console.error,返回 null(:98-101);入口拿到 null 就回 401 invalid_token(server/index.ts:187),不区分"过期/伪造/上游挂",不外泄原因。 - 会话信息另有入口。
whoAmI/空间选择器要的"角色/权限/受限空间"来自fetchSession(GET /v3/session,Zod 校验,server/auth/index.ts:30-53)——那是业务数据,不是鉴权路径。
一句话总结这个模式: 服务器不签发令牌、不做网络自省,用主 API 公开的 JWKS 在本地验签, 信任仍然只有主 API 一个来源,但每个请求的鉴权成本从"一次上游往返"降到"一次本地验签"。
6. 工具与资源:模型能调用的动作面板
这一节讲:每请求新建的 server 上到底挂了哪些能力。
注册发生在 createSupermemoryServer(apps/mcp/src/server/server.ts:64)——它建 McpServer
(带一段给模型看的 SERVER_INSTRUCTIONS,server.ts:26-28)、定义 getClient/空间解析/
上传会话等闭包,然后 registerAllTools(server/tools/index.ts:33)批量注册,最后挂资源与
prompt。工具按受众分四个面(analytics 的 TOOL_SURFACES 表,server/analytics.ts:46-62):
| 面 | 工具 | 干什么 |
|---|---|---|
model_tool(模型直接调) | search_memory、listDocuments、getDocument、listMemories、listSpaces、whoAmI、add_memory | 检索 / 浏览 / 存忘 |
app_launcher(打开一个交互视图) | select-space、memory-graph、guided-save、upload-file | 弹空间选择器 / 图 / 表单 / 文件选择器 |
app_action(视图内部回填) | set-active-tag、save-memory、prepare-file-upload | 视图提交后的落库动作 |
app_internal(仅 App 内部) | fetch-graph-data | 图 UI 翻页取数 |
另有 1 个 prompt(context)和 3 个资源(supermemory://profile、supermemory://spaces、
widget HTML)。
6.1 add_memory:save / forget,空间感知
add_memory(apps/mcp/src/server/tools/add-memory.ts:8-21)先解析有效空间——参数里
给了 containerTag 就用显式的,否则用活跃空间(resolveContainerTag,server.ts:72-73)。
save 走 client.createMemory;forget 走 client.forgetMemory(精确匹配→404 则语义搜索兜底,
阈值 0.85,只删真 memory 不删 chunk,见 01 §7)。
6.2 search_memory:画像 + 检索一体
search_memory(apps/mcp/src/server/tools/search-memory.ts:17)默认把用户画像
(## Profile / ## Recent context 两段,includeProfile 可关)和匹配记忆
(- [87%] 文本 带相似度)拼成一段文本,同时返回强类型 structuredContent(带
outputSchema 校验)。搜索固定 hybrid 模式(client/index.ts:253)。
6.3 空间三件套:listSpaces / select-space / set-active-tag
listSpaces(tools/list-container-tags.ts:10)列空间:名字、key、emoji、文档/记忆数、 最近活动,并提示"先用它把名字解析成 key"。select-space(tools/select-space.ts:9)弹一个交互选择器(App 视图picker), 候选空间先过effectiveContainerTagAccess(server/auth/rbac.ts:4)算出每个空间的读/写。set-active-tag(tools/set-active-tag.ts:8)是选择器的提交动作:校验用户确有该空间 访问权后,把活跃空间写进SpaceStateDO(space-state.ts:24,写入前过 zod 校验)。
空间解析的优先级(README Runtime Model 一节 + server.ts:70-73):显式 containerTag
参数(只影响本次调用)> DO 里的持久活跃空间 > 客户端默认 sm_project_default
(client/index.ts:21)。
6.4 图与文件上传:两个带 UI 的能力
memory-graph(tools/memory-graph.ts:10)不再是"返回一大段数据":它拉当前空间 200 条文档,返回view: "graph"的视图消息(structuredContent带 documents/计数/truncated), UI 由 widget 资源渲染(§8 与 05)。翻页用fetch-graph-data(tools/fetch-graph-data.ts:10,_meta.ui.visibility: ["app"]仅 App 内可见)。upload-file(tools/upload-file.ts:9)弹浏览器的文件选择器(文档/表格/图片/音视频);prepare-file-upload(tools/prepare-file-upload.ts:7)则创建一个直传会话: 生成uploadId+ 一次性uploadToken,2 分钟 TTL,存进SpaceStateDO (server.ts:102-117、space-state.ts:30-40);浏览器随后POST /upload/:uploadId带 token,DO 在事务里校验 token 哈希并一次性消费(consumeUploadSession,space-state.ts:42-66),Worker 把流原样代理到主 API/v3/documents/file(server/index.ts:244-253)。用户的 JWT 永不暴露给浏览器——上传会话只持有一个 短命的一次性 token。
6.5 工具注解与视图元数据
每个工具都带 MCP annotations(tools/annotations.ts):READ_ONLY_TOOL_ANNOTATIONS /
MEMORY_TOOL_ANNOTATIONS(destructiveHint)/ ADDITIVE / SETTINGS 四组,让 ChatGPT 这类
宿主能在 UI 上正确标注工具安全性。App 类工具还带 _meta.ui.resourceUri(widget HTML 资源,
server/app-metadata.ts:14-27)和结果上的 openai/widgetSessionId(ChatGPT 的 widget 会话键,
server/app-metadata.ts:26-29)。
6.6 context prompt:把画像注入系统上下文
context 仍是 prompt(不是 tool,server/prompts/context.ts:20),给客户端拿去当系统消息
注入。它现在还会带上活跃空间的元信息(名字/emoji/描述,最多 8 条事实 + 3 个最近空间,
prompts/context.ts:13-14),并刻意不带参数 schema(不给用户增加摩擦)。
7. RBAC:会话权限怎么裁剪空间访问
whoAmI、select-space、guided-save 都会拉 /v3/session(fetchSession)拿到
accessType(full/restricted)、scope(scoped 到某 tag、只读?)、containerTags
(成员权限表)。effectiveContainerTagAccess(server/auth/rbac.ts:4-31)把规则收敛成
每空间一个 read/write:
restricted会话:默认 read,成员表里有则用成员权限;scoped会话:scope 只读、或不在此 tag 集合内 → 一律 read。
于是选择器只展示可写空间、模型保存到只读空间会被后端 403——客户端错误映射里那句
"This connection may be read-only or scoped to specific spaces"
(client/index.ts:461-465)正是为它准备的。
8. 埋点(PostHog)与 App Widget
埋点换成了"包装器"模式。 createTrackedToolServer(server/analytics.ts:160)把
registerTool 包一层:每次调用自动记录工具名、面(model_tool/app_launcher/…)、结果、耗时、
是否显式指定空间、客户端名/版本;createPosthogAnalytics(server/analytics.ts:105)负责
经 waitUntil fire-and-forget 地发给 PostHog,失败静默。没配 POSTHOG_API_KEY 时空转。
App UI 是一个打包进来的 React widget。 registerWidgetResource
(server/resources/widget.ts:14)把构建期产物 dist/src/widget/index.html
(scripts/build-widget.ts 打包)作为 MCP 资源暴露(MIME text/html;profile=mcp-app),
兼容 URI 模板 ui://supermemory/app-{version}.html。widget(src/widget/)是完整 React 应用:
视图 picker/save/upload/graph/confirmation 由工具返回的 ViewMessage
(shared/types.ts:192-204 的 discriminatedUnion)驱动;graph 视图直接 import
@supermemory/memory-graph 包(src/widget/views/Graph.tsx:1-7)——见 05。
9. 巧妙之处(可带走的技术)
- 无状态请求 + 状态最小化。 每请求新建 McpServer(注册极廉价),把"必须有记忆"的状态压缩到
一个 DO 的两个 key(活跃空间/上传会话),部署、扩缩、回滚都简单(
server/index.ts:198-213)。 - JWKS 本地验签替代网络自省。 信任锚仍是主 API,但鉴权从"每请求一次上游往返"变成
"每请求一次本地
jwtVerify",公钥按 URL 缓存(server/auth/index.ts:21-28)。 - 一次性上传会话。 浏览器直传拿到的不是用户 JWT,而是 2 分钟 TTL、SHA-256 哈希存储、
事务内单次消费的 token(
server/space-state.ts:25-66)——最小暴露面。 - 工具面(annotations + surfaces)显式建模。 同一个 server 上的工具按"模型用 / App 启动 /
App 动作 / App 内部"四类标注,宿主和埋点都能按面统计(
server/analytics.ts:46-62)。 - 视图驱动的交互工具。
select-space/guided-save/upload-file返回的不是数据而是ViewMessage,把"复杂表单交互"从模型 prompt 里挪进真正的 UI(shared/types.ts:124-204)。 - RBAC 在客户端先算一遍。
effectiveContainerTagAccess让选择器只给可写空间、 表单预选合法目标,把一部分 403 拦在发请求之前(server/auth/rbac.ts)。
10. 边界与局限
- 服务器不做检索/嵌入/存储: 所有实际读写都转发给主 API(
SupermemoryClient),这里只做 鉴权 + 协议翻译 + 排版。它坏在哪、慢在哪,取决于主 API。 - search 是最终一致的: save 后要等主 API 摄取流水线跑完才搜得到;forget 更慢。
- 活跃空间按
org+user全局一份: 同一用户换客户端/换 MCP 会话共享活跃空间;并发切换 以后写者为准。 - 鉴权强依赖 JWKS 可达: 主 API 的
/api/auth/jwks拉不到时新 worker 冷启会验签失败 (公钥有缓存,但首次/轮换后需要网络)。 - 上传会话只有 2 分钟、单次消费: 大文件或用户犹豫太久会话就过期,需要重新
prepare。 - 埋点默认可能不开: 无
POSTHOG_API_KEY时全静默(server/analytics.ts:105-115)。 - 不覆盖框架集成路径: 「一行
withSupermemory给 agent 挂记忆」是另一条分发路径, 见 03-framework-middleware。
11. 横向对比(同库其它章)
| 你想了解 | 去哪章 |
|---|---|
| 文档 / 记忆 / 画像 / 空间到底是什么数据 | 01-data-model |
| 不经 MCP,直接在 agent 代码里挂记忆 | 03-framework-middleware |
| Claude 的文件式记忆工具怎么桥到远端 | 04-claude-memory-tool |
memory-graph 那张图怎么画出来的 | 05-memory-graph |
| 全景与阅读顺序 | index |
一句话定位本章: MCP 服务器是「装进任意助手」的标准插座,鉴权用 JWKS 本地验签、 状态只剩一个空间 DO;框架中间件(03)是「装进你自己 agent」的代码内挂载,更轻、无鉴权发现。 二者共享同一套 Supermemory 后端与数据模型(01)。
12. 代码地图(导航索引)
| 主题 | 文件路径 | 关键符号 |
|---|---|---|
| HTTP 入口 / 路由 | apps/mcp/src/server/index.ts | app、handleMcpRequest |
| MCP 转交(无状态) | apps/mcp/src/server/index.ts:198 | createMcpHandler(legacy: "stateless") |
| 401 质询 / 鉴权发现 | apps/mcp/src/server/index.ts:131、:58 | unauthorizedResponse、resourceMetadata |
| 授权服务器元数据代理 | apps/mcp/src/server/index.ts:83 | /.well-known/oauth-authorization-server |
| 上传端点 | apps/mcp/src/server/index.ts:220 | POST /upload/:uploadId |
| JWT 验签 | apps/mcp/src/server/auth/index.ts:100 | validateOAuthToken |
| JWKS 缓存 | apps/mcp/src/server/auth/index.ts:15 | getRemoteJwks |
| 会话拉取(业务) | apps/mcp/src/server/auth/index.ts:30 | fetchSession |
| RBAC 空间权限 | apps/mcp/src/server/auth/rbac.ts:4 | effectiveContainerTagAccess |
| 每请求建 server / 工具注册 | apps/mcp/src/server/server.ts:64 | createSupermemoryServer |
| 空间解析优先级 | apps/mcp/src/server/space.ts:11 | resolveContainerTag |
| 空间状态 DO | apps/mcp/src/server/space-state.ts:17 | SpaceState(活跃空间 / 上传会话) |
| 旧协议 DO(空壳) | apps/mcp/src/server/legacy-protocol-state.ts | SupermemoryMCP(仅回滚保险) |
| 工具批量注册 | apps/mcp/src/server/tools/index.ts:33 | registerAllTools |
| add_memory(save/forget) | apps/mcp/src/server/tools/add-memory.ts | add_memory |
| search_memory | apps/mcp/src/server/tools/search-memory.ts | search_memory |
| listSpaces | apps/mcp/src/server/tools/list-container-tags.ts | listSpaces |
| 空间选择器/提交 | apps/mcp/src/server/tools/select-space.ts、set-active-tag.ts | select-space / set-active-tag |
| 图工具 / 翻页 | apps/mcp/src/server/tools/memory-graph.ts、fetch-graph-data.ts | memory-graph / fetch-graph-data |
| 文件上传(选择器/直传会话) | apps/mcp/src/server/tools/upload-file.ts、prepare-file-upload.ts | upload-file / prepare-file-upload |
| 表单保存视图 | apps/mcp/src/server/tools/guided-save.ts、save-memory.ts | guided-save / save-memory |
| 会话/权限自查 | apps/mcp/src/server/tools/who-am-i.ts | whoAmI |
| 工具注解 | apps/mcp/src/server/tools/annotations.ts | READ_ONLY_TOOL_ANNOTATIONS 等 |
| App 视图元数据 | apps/mcp/src/server/app-metadata.ts | appToolMeta / appResultMeta |
| 视图消息类型 | apps/mcp/src/shared/types.ts:236 | viewMessageSchema / ViewMessage |
| profile 资源 | apps/mcp/src/server/resources/profile.ts:17 | supermemory://profile |
| spaces 资源 | apps/mcp/src/server/resources/container-tags.ts:14 | supermemory://spaces |
| widget 资源 | apps/mcp/src/server/resources/widget.ts:14 | registerWidgetResource |
| context prompt | apps/mcp/src/server/prompts/context.ts:20 | registerContextPrompt |
| 后端调用封装 | apps/mcp/src/server/client/index.ts:135 | SupermemoryClient(详见 01 章代码地图) |
| 埋点 | apps/mcp/src/server/analytics.ts:105、:160 | createPosthogAnalytics / createTrackedToolServer |
| 部署配置 | apps/mcp/wrangler.jsonc:25 | durable_objects(MCP_SERVER + SPACE_STATE) |
| 运行时模型说明 | apps/mcp/README.md:6 | "Runtime Model" 一节 |