跳到主要内容

数据截至 (上游 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 的无状态模式,唯一的 持久状态是 SpaceState DO 里的「活跃空间」与「上传会话」;④ 工具面从 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 appHTTP 入口、CORS、.well-known 鉴权发现、/mcp 验签转交、/upload/*apps/mcp/src/server/index.ts
validateOAuthToken/fetchSessionJWT 验签(远程 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
effectiveContainerTagAccessRBAC:会话权限 → 每个空间的读/写apps/mcp/src/server/auth/rbac.ts
analyticsPostHog 埋点(工具面/耗时/客户端),包装 registerToolapps/mcp/src/server/analytics.ts

主线走一遍(高层): 客户端发 tools/call add_memory → Hono /mcp 处理器取 Authorization 头 → validateOAuthToken 用 JWKS 验签得 AuthUser → 构造 ActorContextcreateMcpHandler 现场建 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 /服务器名/版本/文档链接的自我介绍 JSONserver/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_memorylistDocumentsgetDocumentlistMemorieslistSpaceswhoAmIadd_memory检索 / 浏览 / 存忘
app_launcher(打开一个交互视图)select-spacememory-graphguided-saveupload-file弹空间选择器 / 图 / 表单 / 文件选择器
app_action(视图内部回填)set-active-tagsave-memoryprepare-file-upload视图提交后的落库动作
app_internal(仅 App 内部)fetch-graph-data图 UI 翻页取数

另有 1 个 prompt(context)和 3 个资源(supermemory://profilesupermemory://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)是选择器的提交动作:校验用户确有该空间 访问权后,把活跃空间写进 SpaceState DO(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,存进 SpaceState DO (server.ts:102-117space-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:会话权限怎么裁剪空间访问

whoAmIselect-spaceguided-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.tsapphandleMcpRequest
MCP 转交(无状态)apps/mcp/src/server/index.ts:198createMcpHandler(legacy: "stateless")
401 质询 / 鉴权发现apps/mcp/src/server/index.ts:131:58unauthorizedResponseresourceMetadata
授权服务器元数据代理apps/mcp/src/server/index.ts:83/.well-known/oauth-authorization-server
上传端点apps/mcp/src/server/index.ts:220POST /upload/:uploadId
JWT 验签apps/mcp/src/server/auth/index.ts:100validateOAuthToken
JWKS 缓存apps/mcp/src/server/auth/index.ts:15getRemoteJwks
会话拉取(业务)apps/mcp/src/server/auth/index.ts:30fetchSession
RBAC 空间权限apps/mcp/src/server/auth/rbac.ts:4effectiveContainerTagAccess
每请求建 server / 工具注册apps/mcp/src/server/server.ts:64createSupermemoryServer
空间解析优先级apps/mcp/src/server/space.ts:11resolveContainerTag
空间状态 DOapps/mcp/src/server/space-state.ts:17SpaceState(活跃空间 / 上传会话)
旧协议 DO(空壳)apps/mcp/src/server/legacy-protocol-state.tsSupermemoryMCP(仅回滚保险)
工具批量注册apps/mcp/src/server/tools/index.ts:33registerAllTools
add_memory(save/forget)apps/mcp/src/server/tools/add-memory.tsadd_memory
search_memoryapps/mcp/src/server/tools/search-memory.tssearch_memory
listSpacesapps/mcp/src/server/tools/list-container-tags.tslistSpaces
空间选择器/提交apps/mcp/src/server/tools/select-space.tsset-active-tag.tsselect-space / set-active-tag
图工具 / 翻页apps/mcp/src/server/tools/memory-graph.tsfetch-graph-data.tsmemory-graph / fetch-graph-data
文件上传(选择器/直传会话)apps/mcp/src/server/tools/upload-file.tsprepare-file-upload.tsupload-file / prepare-file-upload
表单保存视图apps/mcp/src/server/tools/guided-save.tssave-memory.tsguided-save / save-memory
会话/权限自查apps/mcp/src/server/tools/who-am-i.tswhoAmI
工具注解apps/mcp/src/server/tools/annotations.tsREAD_ONLY_TOOL_ANNOTATIONS
App 视图元数据apps/mcp/src/server/app-metadata.tsappToolMeta / appResultMeta
视图消息类型apps/mcp/src/shared/types.ts:236viewMessageSchema / ViewMessage
profile 资源apps/mcp/src/server/resources/profile.ts:17supermemory://profile
spaces 资源apps/mcp/src/server/resources/container-tags.ts:14supermemory://spaces
widget 资源apps/mcp/src/server/resources/widget.ts:14registerWidgetResource
context promptapps/mcp/src/server/prompts/context.ts:20registerContextPrompt
后端调用封装apps/mcp/src/server/client/index.ts:135SupermemoryClient(详见 01 章代码地图)
埋点apps/mcp/src/server/analytics.ts:105:160createPosthogAnalytics / createTrackedToolServer
部署配置apps/mcp/wrangler.jsonc:25durable_objects(MCP_SERVER + SPACE_STATE)
运行时模型说明apps/mcp/README.md:6"Runtime Model" 一节