关于 outline-mcp
outline-mcp 是一个基于 Postgres 的树状知识库 MCP 服务,供希望在 LLM 会话间维护可编辑知识的个人使用。节点可浏览、标注属性并持续整理;标记为 inject 的节点会自动加入会话上下文。
主要功能
- 01以书籍和节点组织知识树
- 02浏览目录并查询节点
- 03编辑、移动和批量更新节点
- 04按属性筛选并自动注入上下文
- 05支持链接、验证和待审修订
- 06提供历史记录、快照与健康检查
适用场景
- 01跨会话保存和整理项目知识
- 02将选定节点自动加入会话上下文
- 03审核并追踪知识内容的修改
- 04查询、导出或恢复书籍内容
MCP 相关
服务通过 MCP 工具提供知识树管理、查询、导入导出、修订和快照操作。支持 stdio 与 Streamable HTTP;HTTP 模式还提供只读浏览器界面。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e OUTLINE_MCP_DATABASE_URL ghcr.io/ynishi/outline-mcp:0.15.2OUTLINE_MCP_DATABASE_URL密钥Postgres connection URL. Run `outline-mcp migrate` against it once before starting the server.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/ynishi/outline-mcp:0.15.2stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
outline-mcp
以树形结构组织的知识库,作为 MCP 服务运行。
大模型会话是临时的。outline-mcp 为其提供持久、可编辑的知识树——由章节和内容节点组成,可供浏览(toc)、添加属性,并在不同会话间持续演进。inject=true 的节点会自动纳入会话上下文。
快速开始
书籍存储在由你自行运行的 Postgres 数据库中。outline-mcp 是一个按原样发布的个人项目:没有托管实例,也不附带数据库。
cargo install --path crates/outline-mcp
export OUTLINE_MCP_DATABASE_URL=postgres://user:pass@host:5432/outline
outline-mcp migrate # create / update the schema; run once per upgrade
outline-mcp # stdio
未配置数据库、无法连接数据库(提示会说明是主机无法访问、登录被拒绝,还是数据库不存在),或尚未对数据库运行 migrate 时,服务器会拒绝启动。--database-url <url> 会在每个子命令中覆盖环境变量。
Claude Code(~/.claude.json)
{
"mcpServers": {
"outline": {
"command": "outline-mcp",
"env": { "OUTLINE_MCP_DATABASE_URL": "postgres://user:pass@host:5432/outline" }
}
}
}
共享服务器(多台设备)
--mcp-http 通过 MCP 的可流式 HTTP 传输提供相同的工具。每次写入都是一个数据库事务,并执行按书籍进行的版本检查,因此多个服务器进程或设备可以共用一个数据库。
outline-mcp --mcp-http # 127.0.0.1:8486
outline-mcp --mcp-http --bind 127.0.0.1:9000
将客户端指向该地址上的 /mcp:
{
"mcpServers": {
"outline": {
"type": "http",
"url": "http://127.0.0.1:8486/mcp"
}
}
}
绑定到环回地址以外的地址时必须提供令牌。否则启动会被拒绝,且不会打开任何监听器:
OUTLINE_MCP_HTTP_TOKEN=<token> outline-mcp --mcp-http --bind 0.0.0.0:8486
之后,每个请求都必须携带 Authorization: Bearer <token>——在 MCP 客户端配置请求头的位置设置此项。TLS 终止由反向代理负责。两种传输方式的日志都输出到 stderr;stdout 保留给 stdio 协议通道。
浏览器视图
--mcp-http 还会在 /ui/ 提供只读浏览器视图:书架、每本书的目录(显示 inject / 状态 / 验证 / 待处理修订 / 链接标记;除非主动查看,否则隐藏已归档的子树)、节点页面(渲染后的正文、属性、双向链接、含差异内容的待处理修订、历史记录)、文本搜索(也会匹配长度至少为 8 位的 UUID 十六进制前缀,输入 #<toc number>(例如 #2-3)可打开对应节点;书架上的搜索框会一次搜索所有书籍,节点页面会将其 #n 和 8 位 ID 分别显示为可点击选择的片段),以及书籍历史记录。此视图不会写入数据、不运行脚本,也不会从其他主机加载任何内容。
设置 OUTLINE_MCP_HTTP_TOKEN 后,浏览器会要求提供 HTTP Basic 凭据:用户名任意,密码为该令牌。未设置令牌时(仅绑定环回地址),此视图只响应 Host 为 localhost、127.0.0.1 或 [::1] 的请求。stdio 传输不提供浏览器视图。
用于将其作为守护进程运行的服务模板位于 contrib/systemd/ 和 contrib/launchd/(两者都从各自的环境配置块中读取数据库 URL)。docs/runbooks/ 介绍了如何通过非托管 Fly Postgres 应用在 Fly.io 上托管(fly-io-deploy.md,配置见 contrib/fly/fly.toml)、导入迁移到 Postgres 之前的书架(data-migration.md),以及端到端冒烟测试清单(multi-device-smoke.md)。
工作流
shelf → select_book → toc → node_create / node_update / node_move
node_batch_move / node_batch_update / node_query
checklist / import / init / book_update / book_delete / gen_routing
snapshot_create / snapshot_list / snapshot_restore / snapshot_delete
node_history / dump
book_lint / book_stats (read-only health)
node_verify (curation: verification dates)
link_add / link_remove / links (curation: typed links)
revision_propose / revision_show / revision_approve /
revision_reject / revisions_pending (curation: review)
init— 创建一本新的空书node_create— 添加章节和内容节点(可选填写properties);结果包含新节点的 UUID,可直接用于批量工具toc— 查看带编号 ID 的目录(例如1、2-3)。支持按属性筛选(filter)、设置max_depth(从书籍根节点开始计算的深度;1= 仅根级别)和limit;最后一行会统计未显示的节点。除非设置include_archived: true,否则归档节点及其子树会被隐藏(并在最后一行计数);设置后则会显示并标记为[archived]select_book— 选择一本书。带有inject=true属性的节点会自动追加到正文中(排除草稿和归档节点,以及归档章节下的所有内容;打印的目录会像toc一样隐藏归档子树)checklist— 将一个章节(或整本书)导出为带复选框的 Markdown 清单。除非设置include_archived: true(或subtree_root本身已归档),否则会略去归档子树node_update— 编辑节点的标题、正文、类型、占位内容、属性或状态。状态可以是active、draft(尚未撰写)或archived(已退役:仍可读取,但不会注入,也不会显示在toc/node_query中,除非明确要求)node_move— 移动或删除节点;后代节点会一并移动,并列在结果中。dry_run: true会显示所有将被移动或删除的节点(旧位置 → 新位置),但不会更改任何内容。删除操作会在该节点及每个后代节点的历史记录中记下一条删除记录node_batch_move— 在一次原子调用中移动多个节点(需要 UUID 或 UUID 前缀 ID;要删除节点,请使用node_move并设置action: "remove");也支持dry_runnode_batch_update— 以原子方式更新多个节点的标题、正文、类型、属性或状态node_query— 按属性值、状态(active/draft/archived)、类型(section/content)、text(标题或正文中不区分大小写的子字符串,包含中日韩字符,并附带正文首次匹配位置的片段),或verified_before(从未验证过,或上次验证时间早于某个日期 / 日期时间 / 毫秒数)搜索节点;可选择在结果中包含正文。只有设置status: "archived"或include_archived: true时才会返回归档节点import— 从之前导出的 JSON 文件导入一本书,并恢复状态、验证记录、链接和待处理修订。文件中的节点 ID 会保留,因此重新导入某本书自身的导出文件时,只会更改不同之处;设置new_ids: true可导入带全新 ID 的副本(导入节点之间的链接会重新映射)。指向文件中不存在节点的链接,以及违反修订规则的待处理修订会被丢弃并报告。结果会统计创建、更新和删除的节点数量(书中不在文件内的节点会被删除)。如果文件是从某个章节导出的(文件中有标记,或对于早于该标记的导出文件,根据节点 ID 识别),则会拒绝导入,除非设置force: true,因为此操作会替换整本书gen_routing— 根据所有书籍中带有routing属性的节点生成 Markdown 路由表snapshot_create/snapshot_list/snapshot_restore/snapshot_delete— 完整的书籍版本管理(创建、列出、恢复、删除快照;删除带标签的快照需要设置force: true)node_history— 查看单个节点的更改日志,包含前后差异dump— 将整本书导出为 JSON 文件book_delete— 删除一本书及其节点、历史记录和快照(无法撤销)。必须提供 slug;如果书中存在任何节点、历史记录或快照,则需要设置force: true;dry_run: true只会报告将删除的内容。在检查与删除之间,如果书籍有写入操作,删除将失败,且不会删除任何内容book_update— 更改书籍标题和 / 或max_depth(必须提供 slug)。如果将max_depth降低到已有节点的深度以下,则会拒绝操作并指出该节点;此更改会作为book_update条目显示在book_history中book_lint— 对书籍执行只读结构检查(slug默认为当前选中的书籍):根级别的内容节点、相似标题(标题词语的 Jaccard 相似度;中日韩字符按字符对计算;threshold默认值为 0.6;如果两个标题均为单个词元,除非标题完全相同,否则会跳过)、仅大小写 /_/-/ 空格不同的属性键、没有子节点的章节、超过stale_days(默认值为 90)未更新的草稿,以及目标不在该书中的链接(dangling_links)。所有检查都会忽略归档节点及归档章节下的所有内容。checks可指定要运行的检查子集;limit(默认值为 50)限制每项检查报告的问题数量,并统计其余问题;供程序使用时设置format: "json"book_stats— 以只读方式统计书籍数据:节点数量、最大 / 平均深度、每个章节的子节点数量(最大值、平均值、直方图)、各状态的数量、已注入节点、更新时效性、不同属性键数量和链接;供程序使用时设置format: "json"node_verify— 记录节点已确认仍与实际情况相符(node_ids,可选的by):将其验证时间设为当前时间,不触及内容或最后编辑时间;每个节点记一条历史记录,并提交一次。可与node_query的verified_before配合使用,以列出近期无人确认的内容link_add/link_remove/links— 在一本书的节点之间建立类型化链接(rel可为supersedes、superseded_by、see_also、merged_from等,支持任意 1–40 个a-z 0-9 _ -字符)。链接跟随目标节点的 ID,因此移动目标节点后链接仍然有效;删除节点时会删除指向该节点的链接(每个持有链接的节点都会在同一次提交中更新历史记录,结果会说明删除了多少条链接)。links会列出外链和反向链接;node_query支持linked_to(以及link_rel),其 JSON 会包含links/backlinks(并包含各端点的状态,包括archived)。链接更改会记入历史记录,但与node_verify一样,不会更改节点的updated_atrevision_propose/revision_show/revision_approve/revision_reject/revisions_pending— 管理待审核的更改。revision_propose会将拟议的标题 / 正文 / 属性更改(可选提供by、note)附加到节点,但不会更改节点本身:在批准之前,注入、toc、dump和所有读取操作都会保留当前内容。每个节点只能有一个待处理修订(replace: true会替换现有修订);归档节点不能接收修订。revision_show会显示相对于当前内容的差异(标题、统一格式的正文差异、新增 / 更改 / 删除的属性),并在节点自提议后发生更改时发出警告;revision_approve会应用修订(按与node_update相同的规则验证),并记为一条历史记录;如果修订已过时则会拒绝操作,除非设置force: true;revision_reject会删除修订;revisions_pending会列出待处理修订。提出和拒绝修订会记入历史记录,但不会触及updated_at。node_query会显示待处理修订的摘要,book_lint会报告stale_proposals(超过stale_days、已过时,或留在后来归档的节点上的修订——这些修订只能被拒绝),book_stats会统计待处理修订的数量
节点 ID
toc 会分配易于识别的编号 ID:
1. Coding Standards
1-1. Naming Conventions
1-2. Error Handling
2. Testing
2-1. Unit Tests
2-2. Integration Tests
这些 ID(1、1-2、2-1 等)适用于大多数工具。完整 UUID 和标题子串匹配也可作为备用方式。
注意:
node_batch_move和node_batch_update要求使用 UUID 或 UUID 前缀 ID。为避免在批量操作期间修改树时发生位置漂移,层级tocID 会被刻意拒绝。
节点属性
节点可以包含键值属性,用于存储元数据:
node_create title="My Rule" properties={"inject": "true", "scope": "rust"}
inject=true— 节点正文会自动包含在select_book输出中(上下文注入)routing=<scene>— 将节点标记为包含在gen_routing输出中。使用|分配多个场景(例如routing="testing|TDD")routing_ref=<text>— 覆盖路由表中的默认§ID Title引用(例如routing_ref="select_book で全体参照")- 值为
"true"的属性会在toc中显示为标签:1. My Rule [inject] toc支持筛选:filter={"inject": "true"}仅显示匹配的节点- 属性会在 JSON 导出/导入时保留
架构
此仓库是一个 Cargo 工作区,包含三个 crate:独立于 rmcp 的 SDK(outline-mcp-core)、MCP 协议层(outline-mcp-rmcp)以及服务端二进制文件(outline-mcp)。
crates/
├── outline-mcp-core/ # SDK crate (library, no rmcp dependency)
│ └── src/
│ ├── domain/ # Core model (TemplateBook, TemplateNode, NodeId)
│ │ ├── model/ # Aggregate root + value objects
│ │ ├── error.rs # Domain errors
│ │ └── store.rs # BookStore / SnapshotStore ports
│ ├── application/ # Use cases
│ │ ├── service.rs # BookService (one commit per write)
│ │ └── eject.rs # EjectService (Markdown/JSON export & import)
│ └── infra/ # Persistence
│ ├── pg_store.rs # Postgres adapter (sqlx); migrations/ holds the schema
│ ├── memory_store.rs # In-memory adapter (tests)
│ └── shelf_import.rs # Reader for pre-Postgres shelves (import-shelf)
├── outline-mcp-rmcp/ # MCP layer (rmcp; stdio + streamable HTTP)
│ └── src/
│ ├── server.rs # Transports (run / run_http) + server type
│ ├── tools.rs # Tool handlers
│ └── resources.rs # Resource handlers
└── outline-mcp/ # Binary crate (CLI entry point)
└── src/
├── main.rs # Flag parsing (--database-url / --mcp-http / --bind), transport dispatch
├── db.rs # Database URL resolution and connection errors
├── migrate_db.rs # `migrate` subcommand
└── import_shelf.rs # `import-shelf` subcommand
如果下游应用想要嵌入树 / 快照 / 变更日志逻辑,而不引入 rmcp,可以直接依赖 outline-mcp-core:
[dependencies]
outline-mcp-core = "0.12"
导出格式
Markdown(默认)
# My Runbook
## Design
- [ ] Define requirements
> requirements list: ___
- [ ] API design
REST endpoints
JSON
可重新通过 import 导入的树结构格式:
{
"title": "My Runbook",
"max_depth": 4,
"nodes": [
{
"id": "0b8c…-uuid",
"title": "Design",
"node_type": "section",
"updated_at": "2026-10-19T08:00:00.000Z",
"children": [...]
},
{
"id": "5d1e…-uuid",
"title": "Old design",
"node_type": "content",
"status": "archived",
"verified_at": "2026-09-01T00:00:00.000Z",
"verified_by": "alice",
"links": [{ "rel": "superseded_by", "target": "0b8c…-uuid" }]
}
]
}
除了标题、类型、正文、占位符、子节点和属性外,每个节点还包含其 status(处于活动状态时会省略)、updated_at、verified_at / verified_by、links(目标是同一文件中的 id)以及待处理的 proposal;这些字段为空时都会省略,因此早期版本的文件仍可导入。要完整往返,请使用 dump 导出(或使用 include_archived: true 的 checklist):checklist 默认不包含已归档节点,而导入此类文件会将其从书中删除(导入结果会显示删除数量)。导出单个章节时,会将其记录为 subtree_root;除非设置 force: true,否则 import 会拒绝此类文件。
升级
从书架目录升级(0.14 或更早版本)
早期版本会将每本书保存为书架目录中的 {slug}.json,历史记录保存在 {slug}.changelog.json / {slug}.events.db 中,快照保存在 {slug}.snap.*.json 中。服务端不再读取该目录;请将其导入数据库一次:
outline-mcp migrate
outline-mcp import-shelf --shelf <shelf-dir> # every book
outline-mcp import-shelf --shelf <shelf-dir> --slug rust # one book
对于每本书,导入器会复制树、变更历史和快照,并保留其原始时间戳;随后从数据库中重新读取该书,并为每本书打印一行,对比源数据和数据库:节点数、对所有节点内容和位置计算的哈希、历史记录条目以及快照。如果任何一本书导入失败或存在差异,程序会以非零状态码退出。历史记录会逐条读取,而不是通过重放事件日志读取,因此事件日志已无法重放的书(#2 中所述的警告)仍会连同完整历史记录一起导入。
数据库中已存在的 slug 会被拒绝;--replace 会覆盖它。书架目录只会被读取,不会被修改——请在检查报告之前保留该目录。
许可证
可任选以下许可证之一:
由你选择。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。