news 2026/10/10 1:47:03

Outline MCP 服务器详解:Tools 工具集与 Skills 扩展的架构与实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Outline MCP 服务器详解:Tools 工具集与 Skills 扩展的架构与实践
  • 知识库
  • 知识管理
  • 协同办公
  • 后端
  • 前端

【免费下载链接】outline

The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible.

项目地址:https://gitcode.com/GitHub_Trending/ou/outline
点击查看免费下载

导读

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:

  1. 限流:应用了RateLimiterStrategy.OneThousandPerHour策略(每小时 1000 次请求);
  2. 认证:允许MCP、OAuth、API三种认证类型,由auth中间件解析出user、token与scope;
  3. 团队开关:若当前团队未开启TeamPreference.MCP偏好,直接返回 404,拒绝服务;
  4. 标记用户:为调用用户设置UserFlag.MCP标志并持久化;
  5. 按 token 的 OAuth scope 创建服务器实例:将scope数组传入createMcpServer,工具注册时据此过滤(见下一节);
  6. 传输层:使用 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)会将其作为系统提示的一部分。这段指令定义了四条关键约定,理解它有助于推断工具的预期用法:

  1. 文档正文不允许以 H1 开头——标题作为独立字段存储,应通过title参数设置,正文从段落或更低层级标题开始;
  2. @提及语法——文档与集合的 Markdown 支持@Display Name形式,可通过list_users工具查询用户 ID;
  3. 附件读取方式——图片与附件用fetch工具,设resource: "attachment"并传入附件 ID 或/api/attachments.redirect?id=...URL,将返回用于下载的签名 URL;
  4. 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_documentsdocuments.list全文搜索文档,无 query 时列出最近文档;可选按集合过滤、包含已归档query,collectionId,includeArchived,offset(默认 0),limit(默认 25,最大 100)
list_collection_documentscollections.documents返回集合内完整层级文档树(含嵌套子文档,不含草稿与归档)collectionId
create_documentdocuments.create从 Markdown 或 HTML 创建文档;可用模板预填充title,text,format(markdown/html),sourceFileName,collectionId/parentDocumentId,templateId,icon,color,publish(默认 true),fullWidth
move_documentdocuments.move移动文档或调整同级顺序id,collectionId或parentDocumentId,index(零基)
update_documentdocuments.update更新标题/正文/图标/颜色等;支持四种编辑模式id,title,text,editMode,findText,icon,color,publish,fullWidth
delete_documentdocuments.delete移入回收站(可恢复),或归档id,archive,reason
restore_documentdocuments.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(字节数)。服务端会:

  1. 校验文件大小不超过AttachmentPreset.DocumentAttachment预设的上限(超限返回人类可读的错误信息);
  2. 生成附件记录与存储 key;
  3. 根据环境变量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"仅对管理员生效;
  • 姓名/邮箱搜索使用 PostgreSQLunaccent函数做不区分重音与大小写的模糊匹配(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 工具子系统,可以提炼出三个贯穿始终的设计原则:

  1. 安全默认:OAuth scope 决定"能调什么工具",policy 决定"能读哪些数据",双层校验确保 AI 客户端只能在其权限范围内操作;未开启 MCP 偏好的团队直接 404。
  2. 一致性约定:所有工具统一走success/error响应封装、统一的分页参数(offset/limit、上限 100)、统一的optionalString空值处理、统一的 Datadog 追踪,AI 客户端几乎不需要为不同工具适配不同协议细节。
  3. 面向 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.

项目地址:https://gitcode.com/GitHub_Trending/ou/outline
点击查看免费下载

相关推荐

上一篇:终极指南:jsPDF批量处理API如何一次生成多个PDF文档
下一篇:如何用jsPDF创建夜间阅读友好的PDF暗模式:完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 1:45:18

TonyPi人形机器人本地LLM语音交互系统实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 1:45:07

Apache Beam 中的 Avro 文件读写:AvroIO 连接器全解析

批处理流处理大数据 【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/beam15/beam 点击查看 免费下载 导读 Apache Avro 是一种面向行存储与数据交换的序列…

作者头像 李华
网站建设 2026/10/10 1:44:51

作物害虫识别实战:从数据集预处理到迁移学习模型训练全流程

简介&#xff1a;面向计算机、人工智能、数据科学及相关专业的同学和从业者&#xff0c;这套基于机器学习的作物害虫识别与分类项目包&#xff0c;覆盖从数据加载、模型训练到分类结果输出的完整流程&#xff0c;既可用来练手入门&#xff0c;也可作为大作业、课程设计或毕业设…

作者头像 李华
网站建设 2026/10/10 1:44:40

波士顿房价预测实战:线性回归从数据预处理到模型评估全流程

简介&#xff1a;一份以波士顿房价预测为主线、线性回归从原理到实战的代码合集&#xff0c;适合机器学习初学者与需要快速搭建回归预测流程的开发者。资源共20个文件&#xff0c;含11个Python脚本与9个CSV数据文件&#xff1a;脚本承担数据加载、特征工程、模型训练、评估与可…

作者头像 李华