- 知识库
- 知识管理
- 协同办公
- 后端
- 前端
【免费下载链接】outline
The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible.
导读
Outline 是面向成长型团队的开源知识库(knowledge base),其服务端内置了一个完整的 Model Context Protocol(MCP)服务器,让 Claude 等 AI 客户端能够通过统一的工具接口检索、创建和更新知识库中的文档、集合、评论、模板与附件。本文以仓库内 server/mcp/README.md 为骨架,结合server/mcp/tools/与server/mcp/skills/下的源码实现,系统讲解 MCP 服务器的目录结构、工具注册机制、权限过滤模型、每个工具的输入参数与返回值,以及本地开发联调时的证书配置。读完本文,你将掌握 Outline MCP 服务器的完整工具清单、每个工具的调用方式与适用场景,并能据此在 Claude 等 MCP 客户端中安全地操作 Outline 工作区。
一、目录结构与核心定位
server/mcp/目录是 Outline 的 MCP 服务器实现所在,其中 HTTP 入口位于 server/routes/mcp。整个目录分为两个核心子模块:
tools/—— MCP 客户端可直接调用的工具集合,每个工具是一个自包含的功能单元,负责执行一项具体任务;skills/—— 通过 skills 扩展(skills/list、skills/get)对外提供的技能包,本质上是给 Agent 的"操作手册"。
每个工具都被设计为自包含(self-contained):它独立完成参数校验、权限校验、业务执行与结果格式化,不依赖其他工具的中间状态。这种设计使得 AI 客户端可以按需调用任意工具,而无需维护复杂的调用顺序。
从源码结构看,工具按领域划分为 7 个注册函数,统一在 server/mcp/index.ts 中被装配到同一个McpServer实例上:
attachmentTools(server, scopes); collectionTools(server, scopes); commentTools(server, scopes); documentTools(server, scopes); fetchTool(server, scopes); templateTools(server, scopes); userTools(server, scopes);服务器元信息与能力声明
createMcpServer 负责创建服务器实例,声明了:
name: "outline"、title: "Outline"、version(取自 package.json 的版本号);websiteUrl:当前部署的 origin,用于生成绝对资源地址;icons:192×192 与 512×512 两种尺寸的服务器图标(指向public/images/icon-192.png与icon-512.png);capabilities:声明支持tools、resources以及extensions(注册了io.modelcontextprotocol/skills扩展);instructions:一段默认的"使用说明书",告诉 AI 客户端如何正确操作文档(详见下文"内置指令"一节)。
二、HTTP 入口与认证链路
MCP 服务通过 server/routes/mcp/index.ts 暴露为单端点 POST/mcp:
- 限流:应用了
RateLimiterStrategy.OneThousandPerHour策略(每小时 1000 次请求); - 认证:允许
MCP、OAuth、API三种认证类型,由auth中间件解析出user、token与scope; - 团队开关:若当前团队未开启
TeamPreference.MCP偏好,直接返回 404,拒绝服务; - 标记用户:为调用用户设置
UserFlag.MCP标志并持久化; - 按 token 的 OAuth scope 创建服务器实例:将
scope数组传入createMcpServer,工具注册时据此过滤(见下一节); - 传输层:使用 SDK 的
StreamableHTTPServerTransport(流式 HTTP 传输),并把手请求上下文中的认证信息注入为extra.authInfo,供工具处理器通过getActorFromContext取回当前用户。
值得注意的是,RFC 9728 / MCP auth 规范要求/mcp端点在返回 401 时必须附带WWW-Authenticate头,指向 OAuth 受保护资源元数据文档并声明所需 scope,以便客户端自主启动授权流程——该中间件已完整实现这一行为。
三、权限模型:按 OAuth Scope 动态过滤工具
Outline MCP 服务器最核心的设计是工具按 OAuth scope 动态注册。每个注册函数(如documentTools、collectionTools)内部都通过 AuthenticationHelper.canAccess 判断当前 token 是否拥有对应 scope,只有授权后才调用server.registerTool:
if (AuthenticationHelper.canAccess("documents.list", scopes)) { server.registerTool("list_documents", { ... }); }这意味着:
- 同一部署、不同 token 看到不同的工具清单。例如只有
documents.createscope 的 token 不会在tools/list中看到create_document; - 统一入口工具
fetch采用"至少具备一类信息 scope 才注册"的规则(见 fetch.ts),并据此动态拼装resource枚举,只暴露当前 token 能读取的资源类型。
在授权之上,每个工具内部还会再执行一层行级权限校验(policy check),例如list_documents在按 collection 过滤时会先authorize(user, "readDocument", collection)(documents.ts),delete_document会区分archive与delete两种动作分别授权。因此即便 token 拥有对应 scope,也仍受团队/集合/文档级别的成员权限约束,形成"scope 管功能、policy 管数据"的双层防护。
四、内置指令:AI 客户端的行为准则
createMcpServer会把一段defaultInstructions注入到服务器配置(index.ts),MCP 客户端(如 Claude)会将其作为系统提示的一部分。这段指令定义了四条关键约定,理解它有助于推断工具的预期用法:
- 文档正文不允许以 H1 开头——标题作为独立字段存储,应通过
title参数设置,正文从段落或更低层级标题开始; - @提及语法——文档与集合的 Markdown 支持
@Display Name形式,可通过list_users工具查询用户 ID; - 附件读取方式——图片与附件用
fetch工具,设resource: "attachment"并传入附件 ID 或/api/attachments.redirect?id=...URL,将返回用于下载的签名 URL; - HTML 与图片导入——从包含图片/视频的 HTML 创建文档时,应以
format: "html"传入标记,远程 URL 与 base64 媒体会自动导入为附件;不要先把 HTML 转成 Markdown,也不要把 HTML 文件本身作为附件上传。
此外,创建文档时若用户要求"按模板创建",应先用list_templates找到匹配模板(结果已包含模板 Markdown 正文),原样使用则把其 ID 作为templateId传给create_document,需改造则修改返回正文后作为text传入——两种方式都无需额外的 fetch 调用。
五、Tools 工具集全览
5.1 文档工具(documentTools)
文档工具是最核心的一组,定义于 server/mcp/tools/documents.ts,覆盖文档生命周期:
| 工具名 | 对应 scope | 功能 | 关键参数 |
|---|---|---|---|
list_documents | documents.list | 全文搜索文档,无 query 时列出最近文档;可选按集合过滤、包含已归档 | query,collectionId,includeArchived,offset(默认 0),limit(默认 25,最大 100) |
list_collection_documents | collections.documents | 返回集合内完整层级文档树(含嵌套子文档,不含草稿与归档) | collectionId |
create_document | documents.create | 从 Markdown 或 HTML 创建文档;可用模板预填充 | title,text,format(markdown/html),sourceFileName,collectionId/parentDocumentId,templateId,icon,color,publish(默认 true),fullWidth |
move_document | documents.move | 移动文档或调整同级顺序 | id,collectionId或parentDocumentId,index(零基) |
update_document | documents.update | 更新标题/正文/图标/颜色等;支持四种编辑模式 | id,title,text,editMode,findText,icon,color,publish,fullWidth |
delete_document | documents.delete | 移入回收站(可恢复),或归档 | id,archive,reason |
restore_document | documents.restore | 恢复归档/删除的文档,可指定新集合 | id,collectionId |
几个值得展开的实现细节:
搜索与精确匹配。list_documents在提供 query 时走全文搜索提供商(SearchProviderManager.getProvider(),即 PostgreSQL 全文搜索或插件实现的搜索服务)。若 query 形似文档 ID 或 urlId(UrlHelper.SLUG_URL_REGEX),会先做精确查找并置于结果顶部,避免 AI 按 ID 查找时结果被埋没(documents.ts)。搜索请求还会被记录为SearchQuerySource.MCP类型的搜索历史,且只在首页(offset === 0)记录,避免翻页产生重复记录(documents.ts)。
四种编辑模式(editMode)。update_document的editMode取自 shared/types 的TextEditMode:
replace(默认):整体替换文档内容;append/prepend:在文末/文首追加;patch:按findText精确匹配 Markdown 子串,只替换该部分,保留文档其余部分无法用 Markdown 表达的富格式(高亮、评论、表格宽度等)。工具描述明确建议:编辑既有文档内容时优先用patch模式。
patch模式成功后会把更新后的完整 Markdown 正文作为第二个 content 块回传,供调用方核对实际应用结果(documents.ts)。
空更新失败校验。update_document通过比对revisionCount判断是否真的发生了持久化——每次保存都会递增该计数,若计数未变则返回错误而不是伪造成功(documents.ts)。
HTML 导入走任务队列。create_document在format: "html"时不会在主进程解析 DOM(会阻塞事件循环),而是交给DocumentImportTask.scheduleAndWait异步处理(documents.ts)。
5.2 集合工具(collectionTools)
定义于 server/mcp/tools/collections.ts,对应collections.list/collections.create/collections.update/collections.delete四个 scope:
| 工具名 | 功能 | 关键参数 |
|---|---|---|
list_collections | 列出当前用户可访问的集合,可按名称搜索、分页 | query,offset,limit |
create_collection | 创建集合(用于组织文档) | name,description(Markdown),icon,color |
update_collection | 按 ID 更新集合,仅更新提供的字段 | id,name,description,icon(可传 null 移除),color |
delete_collection | 删除集合(其中未归档文档一并删除)或归档 | id,archive,reason |
实现要点:
list_collections会同时过滤deletedAt与archivedAt均为空,且集合 ID 必须在用户可见集合内(user.collectionIds()),排序采用index collate "C"加updatedAt DESC(collections.ts);- 与文档搜索一致,query 形似集合 ID/urlId 时也会做精确匹配并置顶;
- 返回的集合对象包含Markdown 格式的 description,而非 ProseMirror JSON,方便 AI 客户端直接阅读(
presentCollection使用includeText: true); update_collection与update_document一样有"无变化即报错"的防护(collection.changed()为空时返回错误)。
5.3 评论工具(commentTools)
定义于 server/mcp/tools/comments.ts,覆盖评论的增删改查:
| 工具名 | 功能 | 关键参数 |
|---|---|---|
list_comments | 按文档或集合列出评论,可按父评论/解决状态过滤 | documentId或collectionId(至少其一),parentCommentId,statusFilter,offset,limit |
create_comment | 在文档上创建评论(Markdown 正文),可回复他人或锚定到文档片段 | documentId,text,parentCommentId,anchorText,anchorPrefix,anchorSuffix |
update_comment | 更新评论正文,或解决/取消解决整个线程 | id,text,status(resolved/unresolved) |
delete_comment | 删除评论(需为作者或团队管理员) | id |
最值得注意的能力是行内评论锚定(inline comment anchoring):create_comment支持传入anchorText(文档中的纯文本子串),服务端会通过ProsemirrorHelper.applyCommentMarkByText在 ProseMirror 文档状态中定位该文本并应用评论标记(comments.ts)。当anchorText在文档中出现多次时,可用anchorPrefix/anchorSuffix锁定特定一次出现。锚定过程会先对文档行加Transaction.LOCK.UPDATE锁,防止并发评论标记覆盖状态更新。若无法匹配,返回ValidationError。
评论响应中的text字段由comment.toMarkdown()生成,同样避免了 AI 解析 ProseMirror JSON 的负担。
5.4 附件工具(attachmentTools)
定义于 server/mcp/tools/attachments.ts,目前只有一个工具:
create_attachment(scope:attachments.create)——为上传请求预签名 URL。参数为contentType(MIME 类型)、name(含扩展名的文件名)、size(字节数)。服务端会:
- 校验文件大小不超过
AttachmentPreset.DocumentAttachment预设的上限(超限返回人类可读的错误信息); - 生成附件记录与存储 key;
- 根据环境变量
AWS_S3_UPLOAD_METHOD分支:put:返回预签名 PUT URL 及 headers,并附带可直接执行的curlCommand;post(默认):返回uploadUrl与 multipart 表单字段,附带 POST 形式的curlCommand。
返回值中的attachment.url即文档中可直接引用的附件地址。工具描述明确提示:用返回的uploadUrl/表单字段通过 multipart POST(例如 curl)直传文件,无需经过 Outline 服务器中转。若存储后端不支持 PUT 上传,会返回InvalidRequestError提示改用post。
5.5 模板工具(templateTools)
定义于 server/mcp/tools/templates.ts:
list_templates(scope:templates.list)——列出用户可访问的文档模板,包括工作区级模板与可访问集合内的模板。参数:collectionId(可选过滤)、offset、limit。每个结果都包含模板正文的 Markdown(text字段,由DocumentHelper.toMarkdown渲染,不含标题),因此可以直接把id作为templateId传给create_document原样套用,或先修改正文再作为text传入——无需额外 fetch(templates.ts)。
查询逻辑上,草稿模板仅对创建者可见(publishedAt为空且createdById非当前用户时排除);未传collectionId时返回工作区级模板(collectionId为空)加上用户可见集合内的模板(templates.ts)。
5.6 用户工具(userTools)
定义于 server/mcp/tools/users.ts:
list_users(scope:users.list)——列出工作区用户,用于解析 @提及所需的用户 ID。参数:query(按姓名/邮箱搜索)、role(admin/member/viewer/guest)、filter(active/suspended/invited/all,默认 active)、offset、limit。
权限细节:
- 非管理员默认无法看到被暂停用户(
suspendedAt非空即排除),filter: "suspended"仅对管理员生效; - 姓名/邮箱搜索使用 PostgreSQL
unaccent函数做不区分重音与大小写的模糊匹配(users.ts); - 返回结果按姓名升序,邮箱与详细字段是否返回取决于当前用户对目标用户的
readEmail/readDetails策略。
5.7 统一资源读取工具(fetchTool)
定义于 server/mcp/tools/fetch.ts,是唯一一个覆盖多资源类型的"瑞士军刀":
fetch——按resource类型读取单个实体,resource枚举(document/collection/user/attachment/template)由当前 token 的 info scope 动态拼装。id参数既接受纯 ID,也接受完整 URL——extractId 会从 URL 中提取id查询参数或最后一段路径作为 slug。
各资源返回差异:
document:返回文档元信息(JSON content 块)+完整 Markdown 正文(第二个 content 块),并附带breadcrumb、公开分享shareUrl、评论数;collection:返回集合信息 + 完整层级文档树(presentNavigationNode数组);user:id为"self"/"me"/"current_user"(不区分大小写)时返回当前认证用户;attachment:返回name、contentType、size与短期有效的签名下载 URL(signedUrl);附件属于工作区(团队)而非单个文档,因此同一团队任何成员均可读取,跨团队访问抛出AuthorizationError;template:返回模板元信息 + Markdown 正文。
六、Skills 扩展:给 Agent 的操作手册
除了可调用的工具,MCP 服务器还通过 skills 扩展(io.modelcontextprotocol/skills,SEP-2640)对外暴露一组技能。实现位于 server/mcp/skills/index.ts:
- 每个技能目录必须包含
SKILL.md,以 YAML frontmatter 声明name(须匹配目录名)与description; - 启动时从
server/mcp/skills读取全部目录并缓存(含各文件的 sha256 digest 与字节数); - 每个文件注册为
skill://outline/<dir>/<file>资源;skills/list返回全部技能清单,skills/get按 URI 返回单个技能; - 文本文件按 UTF-8 文本返回,二进制文件按 base64 blob 返回。
仓库内置 4 个技能(server/mcp/skills):
find-and-cite:从知识库检索答案并引用源文档——示范了list_documents+fetch+list_collection_documents的组合用法与引用规则;collection-digest:生成集合内容摘要;meeting-notes:整理会议纪要;capture-conversation:把对话沉淀为文档。
以find-and-cite为例(SKILL.md),它的"快速开始"五步法本质上是工具编排的最佳实践:先用list_documents的context片段挑选候选,再用fetch读取全文,回答时引用原文并附文档 URL,文档冲突时展示各自的updatedAt让用户判断时效。这类技能让 AI 客户端在不额外编写代码的情况下获得领域化的使用范式。
七、工具响应与错误约定
所有工具统一使用 server/mcp/util.ts 中的两个辅助函数格式化结果:
success(data):将结果包装为 JSON 文本 content 块;空数组返回单个[]文本块,避免部分 MCP 客户端拒绝content: []导致"零结果"与"响应异常"无法区分(util.ts);error(err):返回isError: true的文本块,内容为错误消息字符串(util.ts)。
两个重要的入参约定:
optionalString():对可选字符串字段(ID、query 等)做""→undefined的转换,兼容 MCP 客户端对"想省略的字段"发送空字符串的行为;而正文/描述类字段(空字符串是合法值,如清空描述)应使用z.string().optional()直接声明(util.ts);- 分页参数
offset/limit统一使用z.coerce.number()以兼容字符串形式的数字入参,limit上界为 100。
所有处理器都被withTracing包裹(util.ts):每次调用在 Datadog 追踪中生成一个outline-mcp服务下的 span,资源名为工具名,并打上mcp.tool、request.userId、request.teamId标签,便于按用户/团队排查问题。
八、本地开发:用 Claude 联调 MCP
server/mcp/README.md 给出了本地联调的关键前提:开发环境使用 mkcert 签发本地 HTTPS 证书,Claude 桌面客户端默认不信任 mkcert 的根 CA,因此启动时必须注入根证书路径,否则 MCP 连接会因 TLS 校验失败而中断:
NODE_EXTRA_CA_CERTS=$(mkcert -CAROOT)/rootCA.pem claude$(mkcert -CAROOT)会展开为 mkcert 根 CA 目录,rootCA.pem即其中的根证书。该命令适用于在开发环境直接用 Claude 客户端连接本地 Outline 的 MCP 端点做端到端调试。
九、测试与验证
MCP 工具均有配套的集成测试,例如 server/mcp/tools/documents.test.ts(1113 行)通过buildOAuthUser+callMcpTool的组合模拟 OAuth token 调用各工具,验证了:
list_documents返回最近文档且 URL 为绝对地址、不包含模板文档、可按集合过滤;- 权限边界(不同 scope/角色下工具可见性与数据可见性);
- 分页、搜索上下文、精确匹配置顶等行为。
fetch.test.ts、collections.test.ts、comments.test.ts、attachments.test.ts、util.test.ts以及路由层的 server/routes/mcp/index.test.ts 覆盖了其余工具与认证链路。需要本地跑测试时,可参照 package.json 中定义的测试脚本在仓库内执行。
十、小结:安全、一致、可组合的工具设计
回顾整个 Outline MCP 工具子系统,可以提炼出三个贯穿始终的设计原则:
- 安全默认:OAuth scope 决定"能调什么工具",policy 决定"能读哪些数据",双层校验确保 AI 客户端只能在其权限范围内操作;未开启 MCP 偏好的团队直接 404。
- 一致性约定:所有工具统一走
success/error响应封装、统一的分页参数(offset/limit、上限 100)、统一的optionalString空值处理、统一的 Datadog 追踪,AI 客户端几乎不需要为不同工具适配不同协议细节。 - 面向 Agent 的可组合性:
fetch提供统一读取入口,list_templates直接返回模板正文,update_document的patch模式保护富格式,而skills/进一步把常用工具编排固化为可复用的操作手册——三者结合,使 AI 能在 Outline 知识库上完成从"检索 → 阅读 → 引用 → 新建/更新 → 评论协作"的完整工作流。
- 知识库
- 知识管理
- 协同办公
- 后端
- 前端
【免费下载链接】outline
The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible.
相关推荐
browser-use 集成指南:MCP 服务器、Skills 与文档 MCP 全配置详解
browser use 集成指南:MCP 服务器、Skills 与文档 MCP 全配置详解 导读 本文围绕 browser use 开源项目的集成能力展开,系统
人工智能AI Agent浏览器控制GUI 自动化MCP 服务如何在移动设备上部署高性能AI模型:MiniCPM-V Redmi K70端侧优化实战指南
如何在移动设备上部署高性能AI模型:MiniCPM V Redmi K70端侧优化实战指南 你是否曾因为GPU内存不足而无法运行大型多模态AI模型?是否渴望在移
人工智能大模型多模态计算机视觉NLP微调openBMB如何通过Mods与MCP服务器集成:扩展AI命令行工具能力的完整指南
如何通过Mods与MCP服务器集成:扩展AI命令行工具能力的完整指南 在命令行环境中使用AI工具时,你是否遇到过功能受限、资源不足的问题? Mods 作为一款轻
AI 应用CLI大模型
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考