mcpField
R
Roam Research MCP Server

Roam Research MCP Server

本地服务
github.com/2b3pro记忆与知识1005 天前更新

关于 Roam Research MCP Server

Roam Research MCP 与 CLI 是一个 MCP 服务兼命令行工具,用于通过 Roam 后端 REST API 管理 Roam 图谱。它无需 Roam 桌面应用即可运行,适合服务器、容器或脚本环境,也可作为独立 CLI 使用。

主要功能

  1. 01读取、搜索和保存页面及块内容
  2. 02通过 roam_update_page_markdown 差异更新并保留 UID
  3. 03支持 stdin 管道输入的 roam 命令行工具
  4. 04可选的共享 HTTP 守护进程与 Bearer 认证
  5. 05通过 ROAM_GRAPHS 管理多个图谱并设置写入密钥

适用场景

  1. 01在 Claude Code 等客户端中读写 Roam 图谱笔记
  2. 02在定时任务或 CI 中将内容自动保存到 Roam
  3. 03通过脚本批量创建、移动或更新块结构

MCP 相关

该项目作为 MCP 服务运行,向 AI 助手暴露页面读取、搜索、写入、批量操作和记忆等工具,并提供结构化的写入结果。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"roam-research": {
"command": "npx",
"args": [
"-y",
"roam-research-mcp"
]
}
}
}
启动命令npx -y roam-research-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmroam-research-mcp

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Roam Research MCP + CLI

Roam Research MCP + CLI

npm version Project Status: Active License: MIT GitHub

Roam Research MCP 服务 MseeP.ai 安全评估徽章

简介

我创建这个项目是为了解决一个个人问题:我想直接从 Claude Code(以及其他大模型)管理我的 Roam Research 图谱。在构建 Model Context Protocol (MCP) 服务以便 AI Agent 访问我的笔记时,我意识到这些底层工具本身就足够强大,可以独立使用。

这个项目最初是 AI Agent 的后端,后来发展成了功能齐全的独立命令行工具。现在,你可以直接在终端中使用同样强大的 API 功能——将内容写入 Roam、搜索图谱和管理任务——完全不需要大模型。

无论你是想让 Claude 更强大地使用你的知识库,还是只想为自己的脚本配备可靠的命令行工具,这个项目都能满足你的需求。

前后对比:手动将笔记复制粘贴到 Roam,与 Claude 和终端直接读取和写入图谱——使用 npm i -g roam-research-mcp 安装,然后运行 roam save "idea" 或通过 echo "Buy milk" | roam save --todo 管道传入

v5.0 新增内容

一句话概括:roam save 现在为每种指定父级块的方式提供了一个标志,而且两者都不会猜测。--parent-uid 始终表示 UID;--parent 始终表示文本。

在 4.1.0 之前,--parent 接受块 UID 或标题文本,并通过检查值中是否包含数字来判断类型。大约五分之一的 Roam UID 不含数字,因此这些保存操作会被悄悄地路由到错误位置。4.1.0 新增了 --parent-uid,并弃用了向 --parent 传入 UID 的用法。5.0 完成了这项拆分。

  • --parent-uid <uid> 将内容嵌套到具有该 UID 的块下。它接受 uid 或 ((uid));如果不存在这样的块,命令会以非零状态码退出,且不会写入任何内容。
  • --parent "<text>" 将内容嵌套到目标页面上具有该文本的块下;如果该块不存在,则会创建它。它绝不会被视为 UID。--parent "((uid))" 会查找或创建一个内容为该引用的块,而此前无法可靠地实现这一点。
  • 创建父级块时会在 stderr 上提示,并附上其 UID。如果你传给 --parent 的文本看起来像 UID,第二行会说明实际发生的情况,并给出应使用的 --parent-uid 命令。Stdout 保持不变。
  • roam save --help 会优先说明如何选择。“选择父级块”一节位于示例上方,因此你首先会看到这两个标志的区别。

为何升为主版本。roam save --parent "((uid))" 和 roam save --parent <uid> 以前会嵌套到该块下,现在则会嵌套到包含该文本的块下。**如果脚本向 --parent 传入 UID,请将标志改为 --parent-uid。**这只影响命令行工具:MCP 工具将 parent-uid 作为类型化字段接收,行为与之前完全相同,因此如果你通过 AI 助手使用该服务,无需做任何更改。

详情请参阅更新日志。

v4.0 新增内容

一句话概括: 包含软换行(Shift+Enter)的块现在可以在页面重写后保持原样。读取页面,再写回去,内容不会发生变动。

此前,多行块会渲染为两行物理行,第二行从第 0 列开始。这会重置解析器的缩进基准,因此后续所有块都会向根节点收缩,roam_update_page_markdown 也会尽职尽责地生成移动操作,让实际页面与之匹配。仅仅读取页面并写回一个修订版,就足以触发这种情况,而这正是该工具文档中所述的用途。Callout 正文和围栏代码块恰好是包含软换行的块。

  • 软换行渲染为 ⏎。 包含软换行的页面会多出一行开头的 `` 标记;如果要把 Markdown 写回去,请保留它。没有多行块的页面渲染结果与 3.x 字节完全一致,不会出现标记或编码。
  • 反斜杠不再具有特殊含义。 早期设计会将换行符转义为 \n,但这也是作者文本中常见的前缀,例如 \nabla、\neq、C:\newdir。哨兵符不需要这样的规则,因此这些内容在任何地方都会按输入原样写入。
  • 原样往返不会产生操作。 将渲染器的输出不作改动地提交回去(包括标题行),不会产生任何操作。CLI 也共享此修复:将 roam get 的输出传入 roam save --update 后,页面会保持原样。
  • 页面重写增加了两项防护。 现在,解析后不包含任何块的非空 Markdown 会被拒绝,而不是删除页面上的所有块(真正为空的 Markdown 仍会清空页面,如文档所述)。此外,手写的首个块即使恰好是与页面标题相同的 H1,在普通更新时也不会再被剥除。
  • 链接引用也会编码。 roam_fetch_page_full_view 会转义引用块和面包屑中的软换行,而不仅仅是页面自身的内容。
  • 浏览器客户端可以通过 CORS 预检。 HTTP 传输现在允许 MCP-Protocol-Version 和 Last-Event-ID,客户端在初始化后必须发送这两个标头。非浏览器客户端此前不受影响。
  • MCP SDK 已固定版本,与测试套件使用的版本一致,因此全新安装会获得经过测试的协议接口,而不是 npm 当天提供的任意版本。

为什么是主版本更新。 对于任何包含多行块的页面,四种读取方式都会返回不同的字节:roam_fetch_page_by_title(format: "markdown")、roam_fetch_page_full_view、roam_get_subpages 和 roam get。如果你通过 AI 助手使用该服务,无需做任何操作。解析多行页面 Markdown 输出的脚本会看到新的编码。如果你固定使用 roam-research-mcp@3,则会继续使用 3.2.0 的修复,并保留其文档中说明的多行限制,直到你重新固定版本。

完整详情(包括边缘情况,以及如何针对先前状态验证每项修复)请参阅变更日志。

与 Roam 官方 MCP 服务的区别

Roam Research 提供了自己的 MCP 服务和 CLI(@roam-research/roam-mcp)。它是一个很好的工具,本项目并不打算取代它。两者连接的是不同的 Roam API,其他所有区别都由此而来。

本项目官方 @roam-research/roam-mcp
连接目标Roam 的后端 REST API(图谱令牌 + 图谱名称)Roam Desktop 的本地 HTTP API
是否需要运行 Roam不需要 — 可无界面运行需要,桌面应用必须处于打开状态(会通过深层链接启动它)
可运行的位置任何地方:笔记本电脑、服务端、容器、CI运行 Roam Desktop 的机器
共享守护进程是 — roam server 为所有客户端运行一个 HTTP 守护进程每个客户端使用 stdio
多图谱ROAM_GRAPHS 环境变量,并通过 write_key 保护指定图谱~/.roam-tools.json,每个图谱一个令牌
仅 Web 图谱支持仅限 Desktop

**适合使用官方服务的情况:**你希望采用 Roam 自己支持的方式,或者需要只有正在运行的应用才能完成的操作:控制 Desktop UI(打开页面、读取当前选区、操作侧边栏)、语义/嵌入搜索、链接建议、文件上传、评论,或调用 Roam 扩展注册的工具。

**适合使用本服务的情况:**Roam 未运行或未安装 — 例如在服务端、容器、cron 任务或 CI 步骤中使用。或者你想使用本项目新增的功能:支持从 stdin 管道输入的完整独立 CLI、带可选 bearer 身份验证的共享 HTTP 守护进程、保留块 UID 的智能页面差异处理(从而保留块引用)、使用 UID 占位符在一次调用中构建嵌套结构的批量操作,以及 Agent 记忆工具。

有一项刻意省略的功能:**这里没有删除页面的工具。**Roam 没有撤销功能,无法还原通过 API 批量删除的内容。官方服务提供 delete_page;本项目选择采取更谨慎的做法。

两者可协同工作

这两个服务有意采用相同的约定,因此同时运行不会带来任何问题:

  • [[roam/agent guidelines]] — 两者都会读取同一页面中的约定。只需编写一次,两者都会遵循。参见Agent 指南。
  • #.rm-hide / #.rm-private — 两者都会从面向 AI 的内容中排除带有这些标签的块。添加一次标签,即可同时隐藏。参见对 AI 隐藏内容。

独立 CLI:roam

roam CLI 可让你直接在终端中与图谱交互。所有内容创建和检索命令都支持通过 标准输入(stdin)管道传入内容,非常适合自动化工作流。

快速示例
# Save a quick thought to your daily page
roam save "Idea: A CLI for Roam would be cool"

# Pipe content from a file to a new page
cat meeting_notes.md | roam save --title "Meeting: Project Alpha"

# Create a TODO item on today's daily page
echo "Buy milk" | roam save --todo

# Prepend to top of page (newest-first ordering)
roam save -p "Changelog" --order first "v2.18.0 release"

# Search your graph and pipe results to another tool
roam search "important" --json | jq .

# Search for pages by namespace prefix
roam search --namespace "Convention"    # Finds all Convention/* pages

# Fetch a page by title
roam get "Roam Research"

# Fetch daily pages using any date format (auto-normalized)
roam get today                          # Today's daily page
roam get 2026-03-21                     # ISO date → "March 21st, 2026"
roam get "03/21/2026"                   # US date → "March 21st, 2026"
roam get "March 21"                     # Named (assumes current year)

# Fetch a block with ancestors (parent chain to page root)
roam get abc123def -a              # Block + children + ancestors
roam get abc123def -a -d 0         # Ancestors only, no children

# Fetch page by UID or Roam URL
roam get page abc123def
roam get page "https://roamresearch.com/#/app/my-graph/page/abc123def"

# Sort and group results
roam get --tag Project --sort created --group-by tag

# Find references (backlinks) to a page
roam refs "Project Alpha"

# Update a block (e.g., toggle TODO status)
roam update ((block-uid)) --todo

# Multi-graph: read from a specific graph
roam get "Page Title" -g work

# Multi-graph: write to a protected graph
roam save "Note" -g work --write-key "$ROAM_SYSTEM_WRITE_KEY"

可用命令: get、search、save、refs、update、batch、rename、status、server。 运行 roam <command> --help 可查看任意命令的详细信息。

安装
npm install -g roam-research-mcp
# The 'roam' command is now available globally

MCP 服务工具

MCP 服务向 AI 助手(如 Claude)提供这些工具,使其能够智能地读取、写入和整理你的 Roam 图谱。

多图谱支持: 所有工具都接受可选的 graph 和 write_key 参数。使用 graph 可指定 ROAM_GRAPHS 配置中的某个图谱;对受保护的图谱执行写入操作时,使用 write_key。

工具名称描述
roam_fetch_page_by_title根据标题获取页面内容。
roam_fetch_page_full_view获取页面内容,以及所有链接引用(包含面包屑上下文和子项)。
roam_fetch_block根据 UID 获取块,可选获取子项(深度)和/或祖先项(直至页面根节点)。
roam_create_page创建新页面,可选包含混合文本和表格内容。
roam_update_page_markdown使用智能差异更新页面(保留块 UID)。
roam_get_subpages列出命名空间前缀(例如 "Project/")下的子页面,可选按标签筛选。
roam_search_by_text在整个图谱或指定页面中进行全文搜索。支持按命名空间前缀搜索页面标题。
roam_search_block_refs查找引用某个页面、标签或块 UID 的块。
roam_search_by_status查找 TODO 或 DONE 项。
roam_search_for_tag查找包含特定标签的块(支持排除标签)。
roam_search_by_date按创建或修改日期查找块/页面。
roam_find_pages_modified_today列出自午夜以来修改过的页面。
roam_add_todo将 TODO 项添加到今天的每日页面。
roam_create_table创建格式规范的 Roam 表格。
roam_create_outline创建分层大纲。
roam_process_batch_actions在一个批次中执行多个底层操作(创建、移动、更新、删除)。
roam_move_block将块移动到新的父级或位置。
roam_remember / roam_recall用于在 Roam 中管理 AI 记忆的专用工具。
roam_datomic_query执行原始 Datalog 查询,以进行高级筛选。
roam_markdown_cheatsheet获取 Roam 风格的 Markdown 参考指南。
roam_get_guidelines获取此图谱中用户定义的 Agent 约定。
写入工具的结构化结果(v3.0.0+)

这十个写入工具声明了 outputSchema,并在通常的文本之外返回 structuredContent——一个经过验证的对象。客户端可以直接读取 page_uid、uid_map 或 success,无需在字符串中查找 JSON,从而让调用链更加可靠:

// roam_process_batch_actions
{ "success": true, "uid_map": { "parent1": "Xk7mN2pQ9" },
  "validation_passed": true, "actions_attempted": 4 }

有三点值得了解:

  • 没有任何内容被移除。 文本通道保持不变,因此忽略 structuredContent 的客户端,其行为与以往完全相同。
  • 读取工具有意不包含这两项。 它们已经将完整结果序列化到文本通道中,因此加入模式只会让载荷翻倍。
  • 这些字段只会新增。 有些客户端会根据缓存的工具列表验证实时响应,因此字段只会新增或弃用——绝不会在主版本更新之外重命名或移除。

升级到 5.0.0: 仅限 CLI。roam save --parent 现在始终按文本处理,因此向其传递块 UID 的脚本(--parent "((uid))" 或 --parent <uid>)必须改用 --parent-uid。如果不修改,这类调用会以状态码 0 退出,并将内容嵌套在一个包含该引用的新块下;除非指定 -p,否则该块会位于每日页面中。MCP 工具不受影响。请参阅更新日志。

升级到 4.0.0: 读取包含软换行(Shift+Enter)的页面时,现在会将换行渲染为 ⏎,并附带一个前导 `` 标记,以确保页面写回后保持完整。不含多行块的页面与 3.x 版本逐字节相同。AI 助手用户无需进行任何操作;解析多行页面 Markdown 输出的脚本会遇到新的编码方式。请参阅更新日志。

从 2.x 升级: 三个写入结果字段已重命名——uid → page_uid(roam_create_page)、created_uids → created_blocks(roam_create_outline、roam_import_markdown),以及 preservedUids → preserved_uids(roam_update_page_markdown)。这只会影响读取这些名称的代码;如果你通过 AI 助手使用该服务,则不会有任何变化。请参阅更新日志,了解原因。


Agent 指南(按图谱区分)

roam_get_guidelines 会读取图谱内的一个页面——默认为 [[roam/agent guidelines]]——其中包含你自己的约定:如何添加标签、如何为页面命名空间,以及 Agent 绝不能做什么。Roam 官方 MCP 服务也会读取同名页面,因此一个页面即可同时供双方使用。

这与 CUSTOM_INSTRUCTIONS_PATH 不同,两者可以组合使用:

CUSTOM_INSTRUCTIONS_PATH[[roam/agent guidelines]]
所在位置磁盘上的文件图谱中的页面
作用范围全服务,适用于所有图谱按图谱区分
修改方式编辑文件,重启服务编辑页面
用途如何编写 Roam Markdown当前用户希望如何处理此图谱

只需创建该页面。 无需任何配置,roam_get_guidelines 就会读取 [[roam/agent guidelines]]——这与 Roam 自有服务读取的标题相同,因此创建一次,双方都会遵循。创建具有该精确命名空间标题的页面即表示选择启用;除非 Agent 显式调用该工具,否则不会从图谱中读取任何内容。

如果页面不存在,该工具会返回 exists: false,而不会报错,因此始终可以安全调用。

它还会返回那些不由你设定的规则

除了你的约定之外,每个 roam_get_guidelines 响应都会携带一个 roamSyntax 字段:一份简短的注意事项清单,列出会破坏内容的操作——roam_update_page_markdown 会删除 Markdown 中省略的所有块,将截断的 structure 预览写回并当作内容,以及把块引用重新输入为纯文本——还会提醒,读取时会静默排除 #.rm-hide 子树,并列出 Roam Markdown 与标准 Markdown 规则相反的少数情况。

之所以把它放在这里,而不是放进速查表,有两个原因。它会触达每个客户端,包括从未调用 roam_markdown_cheatsheet 的客户端;即使图谱中没有指南页面,它也会返回——而这正是 Agent 最缺乏上下文的情况。这样的分层是有意为之:你的约定决定风格,roamSyntax 保障数据安全。 任何约定都无法让截断的预览变得完整。

完整的语法参考——组件、查询、嵌入内容、工具选择——仍在 roam_markdown_cheatsheet 中。roamSyntax 约 800 个 token,并刻意限制了长度。

每个图谱都可以指向不同的页面,也可以将其关闭:

ROAM_GRAPHS='{
  "personal": {"token": "...", "graph": "..."},
  "work":     {"token": "...", "graph": "...", "guidelinesPage": "work/agent rules"},
  "private":  {"token": "...", "graph": "...", "guidelinesPage": false}
}'
ROAM_GUIDELINES_PAGE='team/agent guidelines'   # change the default for every graph

解析顺序为每个图谱的 guidelinesPage → ROAM_GUIDELINES_PAGE → roam/agent guidelines。上例中,personal 使用环境变量覆盖值,work 使用自己的页面,而 private 则完全关闭了指南。只有显式设置为 false 才会禁用指南——未设置值不会禁用。

结果会缓存 30 秒——编辑页面后无需重启即可生效。入门模板位于 .roam/agent-guidelines.template.md。

请注意,指南通过常规页面路径读取,因此标记为 #.rm-hide / #.rm-private 的块也会被隐藏——见下文。

读取包含软换行符的页面时,会将其渲染为 ⏎,让每个块 保持在一行中——未转义的换行符会落在第 0 列,并在写回时将 其后的所有内容重新设为子级。此类负载会带有前导的 `` 标记;如果要将 Markdown 写回,请保留它。你编写的 Markdown 永远不会被解码:反斜杠没有特殊含义,且只有带标记的负载中的 ⏎ 才会被解释。roam_get_guidelines 的输出是纯文本——不含哨兵,也不含标记。


对 AI 隐藏内容

带有 #.rm-hide 或 #.rm-private 标签的区块及其所有嵌套内容,都不会包含在这些工具返回的内容中。井号标签形式(#.rm-hide、#[[.rm-hide]])和链接形式([[.rm-hide]])均可使用。.rm-private 是 Roam 现有的“对其他用户隐藏”标签;.rm-hide 则专门用于对 AI 隐藏内容。

这遵循与 Roam 官方 MCP 服务相同的约定,因此为其中一个服务添加标签的区块,也会对另一个服务隐藏。

适用工具:roam_fetch_page_by_title、roam_fetch_block、roam_fetch_page_full_view、roam_get_subpages、roam_search_by_text、roam_search_for_tag、roam_search_by_status、roam_search_block_refs、roam_search_hierarchy、roam_search_by_date。

隐藏的区块也会从页面重写差异中排除,这样就不会因为 Agent 无法写出的 Markdown 中缺少这些区块而将其删除。roam_update_page_markdown(以及 roam save --update)会用你提供的内容替换整个页面,并删除 Markdown 中省略的所有内容。因此,它的基线也会使用相同的过滤规则进行裁剪,遵循的原则是:差异操作会删除内容的基线,必须与调用方获准读取的页面一致。 如果有内容受到保护,它会报告 preserved_hidden。内容会得到保留;但相对于可见同级区块的确切顺序可能会改变。这是修复前一个真实的数据丢失漏洞,详情请参阅更新日志。

这是一个便利过滤器,不是安全保障。 roam_datomic_query 会直接读取数据库,并有意不应用此过滤器,因此能力足够强的 Agent 仍可通过原始 Datalog 显示隐藏区块。请将这些标签视为“避免让 AI 接触这些内容”,而非“对内容保密”。

标签匹配不区分大小写,且只匹配完全一致的标签——#.rm-hidden 和 #.rm-highlight 不受影响。隐藏 UID 集会缓存 30 秒,因此刚添加标签的区块可能会在这段时间内继续显示。


配置

环境变量
单图谱模式

对于单个 Roam 图谱,请在环境变量或 .env 文件中设置以下内容:

ROAM_API_TOKEN=your-api-token
ROAM_GRAPH_NAME=your-graph-name
多图谱模式(v2.0+)

通过单个服务实例连接多个 Roam 图谱:

ROAM_GRAPHS='{
  "personal": {"token": "token-1", "graph": "personal-db", "memoriesTag": "#[[Personal Memories]]"},
  "work": {"token": "token-2", "graph": "work-db", "protected": true, "memoriesTag": "#[[Work Memories]]"},
  "research": {"token": "token-3", "graph": "research-db"}
}'
ROAM_DEFAULT_GRAPH=personal
ROAM_SYSTEM_WRITE_KEY=your-secret-key

图谱配置选项:

属性必填说明
token是此图谱的 Roam API 令牌
graph是图谱名称/数据库标识符
protected否如果为 true,写入操作需要通过 ROAM_SYSTEM_WRITE_KEY 确认——默认图谱除外,见下文
memoriesTag否roam_remember/roam_recall 使用的标签(覆盖全局默认值)

两种访问控制及其区别

服务有两道相互独立的锁。它们很容易混淆,因为两者都是“密钥”——简单来说如下(两者均为可选,默认关闭):

Bearer 令牌——HTTP_AUTH_TOKEN写入密钥——ROAM_SYSTEM_WRITE_KEY
简单来说前门的钥匙保险箱内部的门闩
控制内容谁可以访问服务是否允许写入标记为 protected 的图谱
适用范围所有内容——所有图谱的读取和写入仅限写入,且只适用于标记为 protected 的图谱
是否保护读取?是否
何时需要仅当服务可从你自己的机器之外访问时(例如,使用 -H 0.0.0.0)只要你希望防止意外修改重要图谱,就需要设置
发送方式HTTP 标头:Authorization: Bearer <token>写入工具/CLI 命令中的 write_key 参数
可以把它想象成一栋房子:持有者令牌锁住前门(彻底把陌生人挡在门外),而写入密钥锁住里面的保险箱(即使已经进入房子,也需要它才能更改保险箱里的东西)。在你自己的机器上绑定到 127.0.0.1 时,前门面对的是一堵墙;没有令牌的服务也会拒绝试图通过 DNS 重绑定访问它的网页(见下文的 HTTP_ALLOWED_HOSTS),因此在那里不需要持有者令牌。写入密钥在本地仍然很有用,可以作为一道“确定吗?”的保护,因为Roam 没有撤销功能。

所以:若要将某个图谱设为需要写入密钥,请在该图谱上设置 protected: true,并配置 ROAM_SYSTEM_WRITE_KEY;之后,调用方对该图谱进行任何写入时,都必须传入匹配的 write_key。

⚠️ protected 对默认图谱不起作用。 无论 protected 的设置如何,在检查该标记之前,都会始终允许写入 ROAM_DEFAULT_GRAPH 指定的图谱;此标记保护的是那些必须按名称主动指定的图谱,因为访问非默认图谱本身就是值得确认的有意操作。如果你希望对某个图谱的写入进行保护,它就不能是你的默认图谱。

可选:

  • ROAM_MEMORIES_TAG:roam_remember/roam_recall 的默认标签(当未设置每个图谱的 memoriesTag 时作为后备值)。
  • HTTP_STREAM_PORT:HTTP Stream 传输的端口(默认为 8088)。仅限 --server 模式——stdio 模式不会打开套接字,因此此设置在该模式下会被忽略。
  • HTTP_STREAM_HOST:HTTP 传输要绑定的主机(默认为 127.0.0.1,仅限环回地址)。仅限 --server 模式。 设置为 0.0.0.0 可在局域网中开放服务;这样做时,请设置 HTTP_AUTH_TOKEN。
  • HTTP_AUTH_TOKEN:用于锁定整个 HTTP 端点的可选持有者令牌。未设置时,不使用令牌:服务只会响应发往 localhost、IP 地址或 HTTP_ALLOWED_HOSTS 中某个名称的请求,并且只会响应来自 CORS_ORIGIN 中某个源的浏览器请求。设置后,每个 MCP 请求都必须发送 Authorization: Bearer <token>(GET /health 仍然开放)。绑定到 127.0.0.1 以外的地址时,请务必使用。它与 ROAM_SYSTEM_WRITE_KEY 不同——请参见两种访问控制及其区别。
  • HTTP_ALLOWED_HOSTS:未设置 HTTP_AUTH_TOKEN 时,服务会响应的主机名,除 localhost 和 IP 地址外还可包含其他主机名(以逗号分隔;端口会被忽略),例如 Docker 服务名称 roam-mcp 或 mybox.local。发往任何其他名称的请求都会收到 403。这可以阻止网页将自己的主机名指向 127.0.0.1 后访问服务(DNS 重绑定)。设置了 HTTP_AUTH_TOKEN 时会忽略此项。
  • CORS_ORIGIN:允许调用 HTTP 服务的浏览器源(以逗号分隔;默认为 http://localhost:5678,https://roamresearch.com;* 表示允许任何源)。未设置 HTTP_AUTH_TOKEN 时,来自其他任何源的请求都会收到 403。
运行服务

1. 默认模式(stdio) 最适合本地集成(例如 Claude Desktop、IDE 扩展)。MCP 客户端会在每个会话启动一个进程,并通过 stdin/stdout 与其通信。不会打开端口——stdio 模式下的 MCP 无需端口。

在 3.1.0 之前,此模式也会打开 HTTP 监听器,并将其绑定到所有网络接口。如果你正在使用该端点,请改为运行 --server 守护进程;详见下文。

npx roam-research-mcp

2. 共享服务模式(--server) 最适合运行单个长期驻留、仅使用 HTTP 的守护进程,供多个 MCP 客户端共享,而不是让每个会话都启动自己的子进程。这样可以节省内存,并为客户端提供稳定的 URL。

HTTP_STREAM_PORT=8088 npx roam-research-mcp --server

或者通过 roam CLI 管理,它提供启动、停止、状态和日志功能:

roam server start            # start the shared daemon in the background
roam server start -H 0.0.0.0 # expose on the LAN (no transport auth!)
roam server status           # is it up? version, graphs, active sessions
roam server logs -f          # follow the log
roam server stop             # stop a CLI-started daemon

无论守护进程通过何种方式启动,roam server status 都可以正常工作(它会探测 /health),因此也能报告由 LaunchAgent/systemd 单元启动的守护进程。状态文件(pidfile + 日志)位于 ~/.roam/(可通过 ROAM_HOME 覆盖)。

这两种模式互斥,且各自只启用一种传输方式:stdio 模式使用 stdio,不绑定任何端口;--server 使用 HTTP,不读取 stdin。在 --server 模式下,服务:

  • 仅运行 HTTP(不使用 stdio 传输),
  • 将 准确的 HTTP_STREAM_PORT 绑定到 HTTP_STREAM_HOST,如果端口已被占用则以非零状态退出(不会静默切换端口——共享守护进程必须保持 URL 稳定),
  • 提供 GET /health → {"status":"ok", ...},用于存活检查。

通过 HTTP 传输配置将 MCP 客户端指向该服务:

{
  "mcpServers": {
    "roam-research-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8088/mcp"
    }
  }
}

环境变量(令牌、图谱)配置在服务进程中,而不是客户端配置中。

保护对外开放的服务(两层): 如果绑定范围超出回环地址(-H 0.0.0.0),请添加边界防护:

HTTP_AUTH_TOKEN=$(openssl rand -hex 32) roam server start -H 0.0.0.0

然后,客户端通过请求头发送令牌:

{
  "mcpServers": {
    "roam-research-mcp": {
      "type": "http",
      "url": "http://<host>:8088/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

两者都要保留——它们的作用不同(参见上文两种访问控制及其区别):Bearer 令牌控制谁可以连接,写入密钥只保护对受保护图谱的写入操作。

⚠️ 写入密钥不能替代 Bearer 令牌。在未设置 HTTP_AUTH_TOKEN 的对外开放服务上,网络中的任何人仍可读取所有图谱(并写入未受保护的图谱)。只要服务绑定范围超出回环地址,就应设置 HTTP_AUTH_TOKEN。

保持服务运行(macOS LaunchAgent): 创建 ~/Library/LaunchAgents/com.example.roam-mcp.plist,设置 RunAtLoad 和 KeepAlive,在 EnvironmentVariables 中配置环境变量,并将 --server 作为最后一项 ProgramArguments。将 StandardOutPath/StandardErrorPath 设置为本地路径(例如 ~/Library/Logs/),然后:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.roam-mcp.plist
curl -s http://127.0.0.1:8088/health   # verify

3. Docker

docker build -t roam-research-mcp .
docker run --init -p 127.0.0.1:8088:8088 \
  -e HTTP_STREAM_HOST=0.0.0.0 -e HTTP_STREAM_PORT=8088 \
  --env-file .env roam-research-mcp --server

运行前,在 .env 中将 HTTP_AUTH_TOKEN 设置为随机密钥;MCP 请求必须包含 Authorization: Bearer <token>。默认情况下,发布的端口仅绑定到回环地址。如需远程访问,请遵循保护对外开放的服务,并明确将端口发布到所需的主机地址。

-e 的值优先于 --env-file,因此无论 .env 中设置了什么,服务都会监听发布的端口。--init 可让 docker stop 立即结束服务,而不是等待 10 秒后再将其强制终止。

在 LLM 中配置

Claude Desktop / Cline:

添加到 MCP 设置文件中(例如,~/Library/Application Support/Claude/claude_desktop_config.json):

固定版本。 npx -y roam-research-mcp 会在客户端每次启动服务时获取最新版本,因此新主版本发布时不会有任何提示。固定主版本号,何时升级由你决定:

args获取的版本
["-y", "roam-research-mcp"]始终获取最新版本——包括下一个主版本
["-y", "roam-research-mcp@3"]仅限 3.x;升级主版本时需要在此处修改
["-y", "[email protected]"]精确指定此版本

固定主版本是明智的默认选择:你仍然能获得修复和新工具,但是否接受破坏性变更由你决定。以下示例不固定版本,以符合大多数人首次粘贴配置时的习惯。

单个图谱:

{
  "mcpServers": {
    "roam-research": {
      "command": "npx",
      "args": ["-y", "roam-research-mcp"],
      "env": {
        "ROAM_API_TOKEN": "your-token",
        "ROAM_GRAPH_NAME": "your-graph"
      }
    }
  }
}

多个图谱:

{
  "mcpServers": {
    "roam-research": {
      "command": "npx",
      "args": ["-y", "roam-research-mcp"],
      "env": {
        "ROAM_GRAPHS": "{\"personal\":{\"token\":\"token-1\",\"graph\":\"personal-db\",\"memoriesTag\":\"#[[Memories]]\"},\"work\":{\"token\":\"token-2\",\"graph\":\"work-db\",\"protected\":true}}",
        "ROAM_DEFAULT_GRAPH": "personal",
        "ROAM_SYSTEM_WRITE_KEY": "your-secret-key"
      }
    }
  }
}

查询块解析器(v2.11.0+)

用于以编程方式解析和执行 Roam 查询块的实用工具。将 {{[[query]]: ...}} 语法转换为 Datalog 查询。

支持的子句
子句语法说明
页面引用[[page]]引用了某个页面的块
块引用((uid))引用了某个块的块
and{and: [[a]] [[b]]}必须匹配所有条件
or{or: [[a]] [[b]]}匹配任意条件
not{not: [[tag]]}排除匹配项
between{between: [[date1]] [[date2]]}日期范围筛选
search{search: text}全文搜索
daily notes{daily notes: }仅限每日笔记页面
by{by: [[User]]}由用户创建或编辑
created by{created by: [[User]]}由用户创建
edited by{edited by: User}由用户编辑
相对日期

between 子句支持相对日期:today、yesterday、last week、last month、this year、7 days ago、2 months ago 等。

用法
import { QueryExecutor } from 'roam-research-mcp/query';

const executor = new QueryExecutor(graph);

// Execute a query
const results = await executor.execute(
  '{{[[query]]: "My Query" {and: [[Project]] {between: [[last month]] [[today]]}}}}'
);

// Parse without executing (for debugging)
const { name, query } = QueryParser.parseWithName(queryBlock);
实用函数
import { isQueryBlock, extractQueryBlocks } from 'roam-research-mcp/query';

// Detect if text is a query block
isQueryBlock('{{[[query]]: [[tag]]}}'); // true

// Extract all query blocks from a string
extractQueryBlocks(pageContent); // ['{{[[query]]: ...}}', ...]

支持

如果这个项目帮助你管理知识库或构建有趣的 Agent,不妨请我喝杯咖啡!这有助于持续推出更新。

通过 PayPal 捐赠

https://paypal.me/2b3/5


许可证

MIT 许可证 - 由 Ian Shen 创建。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。