Skip to content

12.3 官方扩展体系

🎯 学习目标:理解 MCP 扩展的协商机制,知道何时该用 Tasks / Apps / Skills ⏱️ 预计时间:45 分钟 📊 难度等级:⭐⭐⭐(概念为主,配有协议示例)

📌 一句话结论:2026-07-28 把一批"实验特性"正式移出核心协议,改为官方扩展。扩展是可选、可组合、独立演进的,一律默认关闭,必须由开发者显式开启并做能力协商。

🧩 什么是 MCP 扩展

扩展是对规范的可选补充,定义了核心协议之外的能力。 它们可以是:

  • 模块化的(如独立的认证机制)
  • 专业化的(如某行业特有逻辑)
  • 实验性的(正在孵化、未来可能进核心)

扩展标识符

每个扩展用一个唯一标识符命名,格式为:

{vendor-prefix}/{extension-name}
  • 官方扩展用 io.modelcontextprotocol 前缀,例如 io.modelcontextprotocol/tasks
  • 第三方扩展请用你拥有的域名倒写做前缀,避免冲突(类似 Java 包命名)。拥有 example.com 的公司用 com.example/,例如 com.example/my-extension

💡 标识符规则与 _meta一致,只是强制要求前缀

📦 官方扩展清单

官方扩展放在 MCP GitHub 组织下、以 ext- 为前缀的仓库里。

🔐 Authorization 扩展(ext-auth

核心授权之外的补充机制。

扩展说明
OAuth Client Credentials机器对机器(M2M)认证的 OAuth 2.0 客户端凭据流
Enterprise-Managed Authorization需要集中访问控制的企业环境框架

核心授权流程见 12.1 OAuth 2.1 授权体系

📊 Tasks 扩展(ext-tasks

扩展说明
MCP Tasks长时操作的异步执行:轮询、途中请求输入、持久化句柄

🖼️ MCP Apps 扩展(ext-apps

扩展说明
MCP Apps允许服务器在对话里内嵌交互式 UI(图表、表单、视频播放器)

📚 Skills over MCP 扩展(ext-skills

扩展说明
Skills over MCP通过 MCP 资源发现工作流指令并读取配套文件

📌 Tasks 为什么是扩展? 它在 2025-11-25 是实验特性,2026-07-28 被正式移出核心、变成 io.modelcontextprotocol/tasks 扩展(SEP-2663)。这是"实验特性 → 官方扩展"的标准路径。

🧪 实验性扩展

官方给工作组/兴趣组提供了一条孵化通道:在正式提 SEP 之前,先用实验仓库原型验证想法。

  • 实验仓库以 experimental-ext- 为前缀(如 experimental-ext-interceptors
  • 每个实验扩展必须挂靠一个工作组或兴趣组
  • 仓库与已发布包必须明确标注实验状态(README、包名)
  • 核心维护者保留监督权,包括归档或移除

转正路径:走标准 SEP 流程(Extensions Track),可以把孵化期的实验仓库与参考实现作为"该扩展切实可行"的证据。

🔄 创建一个官方扩展的五步

要求:

  • 扩展规范必须使用 RFC 2119 语言(MUST / SHOULD / MAY)
  • 扩展必须有对应的 WG 或 IG
  • 实现是硬门槛:SEP 进入评审前,至少要有一个官方 SDK 的参考实现

SDK 支持:SDK 可以实现扩展,但不是协议一致性所必需的;SDK 维护者自主决定支持哪些扩展,支持的话应在文档里列出。

⚠️ 扩展默认关闭,必须由开发者显式开启。

🤝 能力协商(Negotiation)

双方通过各自能力声明里的 extensions 字段表明支持的扩展。

客户端:在每个请求的 _meta 里声明

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "New York" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {
        "extensions": {
          "io.modelcontextprotocol/ui": {
            "mimeTypes": ["text/html;profile=mcp-app"]
          }
        }
      },
      "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }
    }
  }
}

注意:这是无状态模型的体现——扩展声明随每个请求携带,而不是靠一次握手协商后记住。

服务器:在 server/discover 响应里声明

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "supportedVersions": ["2026-07-28"],
    "capabilities": {
      "tools": {},
      "extensions": { "io.modelcontextprotocol/ui": {} }
    },
    "_meta": {
      "io.modelcontextprotocol/serverInfo": { "name": "ExampleServer", "version": "1.0.0" }
    },
    "ttlMs": 3600000,
    "cacheScope": "public"
  }
}

每个扩展自己定义其设置对象的 schema;空对象表示无设置。

优雅降级(Graceful Degradation)

若一方支持某扩展、另一方不支持,支持方必须二选一:

  • 回退到核心协议行为,或
  • 若该扩展是强制的,用合适的错误拒绝请求

💡 好的扩展文档会写明预期回退行为。例如:提供 UI 增强的服务器,对不支持 UI 扩展的客户端仍应返回有意义的文本内容;而依赖某认证扩展的服务器,则可以拒绝不支持它的客户端。

演进规则

  • 扩展独立于核心协议演进,由扩展仓库维护者管理,不需核心维护者复审
  • 需要改动时优先用能力标志或扩展设置对象内的版本号,而不是新建标识符
  • 无法避免破坏性变更时,才用新标识符(如 io.modelcontextprotocol/my-extension-v2
  • 破坏性变更包括:删除/重命名字段、改字段类型、改既有语义、新增必填字段

⏳ 深入一:Tasks(长任务)

不是每次工具调用都立刻返回。CI 流水线、批处理、人工审批可能耗时数秒到数小时。Tasks 让服务器返回一个持久化句柄而不是阻塞

为什么不能"直接阻塞"

阻塞的问题Tasks 如何解决
长期占用连接,中间层超时撑不住不长期占用连接
客户端崩溃/重启就丢了task ID 是持久句柄,可用同一 ID 恢复轮询
看不到进度携带状态元数据与可选进度消息
需要用户输入时没法交互input_required 并浮出请求,客户端用 tasks/update
每工具都要预热/传参开关服务器按请求决定是否建任务,客户端一次性 opt-in

生命周期

状态含义
working进行中
input_required需要客户端输入(见 inputRequests
completed完成,result 含最终输出
failed执行中发生 JSON-RPC 错误,error 含细节
cancelled已取消(不保证被遵守)

completed / failed / cancelled终态,一旦到达状态不再改变。

主流程

要点:

  • 服务器返回 CreateTaskResultresultType: "task"),含 taskId、初始状态、TTL、建议轮询间隔;任务必须在响应发出前持久化创建
  • 客户端用 tasks/get 轮询;终态时 result(completed)或 error(failed)落位
  • 没有 tasks/list;用 tasks/get 轮询客户端已知的句柄
  • tasks/cancel协作式取消——服务器确认意图,但不保证停下
  • 服务器可以通过 notifications/tasks 推送(客户端经 subscriptions/listen opt-in),省掉轮询往返

何时该用 Tasks:长时操作(CI、批处理、模型训练)、人在环流程(审批门)、已用 job ID 的外部系统、不可靠连接、需要进度可见的批量处理。

🖼️ 深入二:MCP Apps(对话内 UI)

文本响应有极限。有时用户需要与数据交互,而不只是读它。MCP Apps 让服务器返回交互式 HTML 界面(可视化、表单、看板),直接渲染在聊天里。

相比独立 Web 应用的优势:

优势说明
上下文保留应用就在对话里,用户不必切标签页、丢位置
双向数据流应用可调服务器上任意工具,宿主能把新结果推给应用
宿主能力整合应用可把动作委托给宿主,由宿主走用户已连接的既有能力(经用户同意)
安全保证运行在宿主控制的沙箱 iframe 里,无法访问父页、偷 cookie、逃逸容器

核心模式:一个在描述里声明了 UI 资源的工具 + 一个把数据渲染成交互式 HTML 的 ui:// 资源

安全模型:所有通信走 postMessage;宿主决定应用能访问哪些能力(如限制可调工具、禁用 sendOpenLink)。资源可带 _meta.ui.csp(允许的外部源)与 _meta.ui.permissions(麦克风/摄像头等)。

何时该用:探索复杂数据(可钻取的地图)、多选项配置(一次性表单)、富媒体查看(PDF/3D/视频)、实时监控、多步工作流。

框架无关:是标准 Web 原语,React / Vue / Svelte / Preact / Solid / 原生 JS 都行;@modelcontextprotocol/ext-appsApp 类只是便利封装,不是必需。

📚 深入三:Skills over MCP(工作流指令分发)

Skills 扩展让服务器把工作流指令与配套文件暴露给客户端,客户端用既有的 Resources 原语发现元数据、读取内容。

一个 skill 就是一个目录:含一个 SKILL.md 与可选配套文件,遵循 Agent Skills 规范。这个扩展定义的是通过 MCP 发现与读取的方式。

能力声明:服务器必须同时声明 resources 能力和 io.modelcontextprotocol/skills 扩展,并必须实现 skills/listskills/get;技能文件经 resources/read 提供。

json
{
  "capabilities": {
    "resources": {},
    "extensions": {
      "io.modelcontextprotocol/skills": { "directoryRead": true }
    }
  }
}

三种操作:

操作作用
skills/list发现可用技能,返回 frontmatter 与完整文件清单(含每个文件的 URI、SHA-256 摘要、字节大小)
skills/get按 URI 取单个技能条目(也用于刷新已缓存条目)
resources/read读取 SKILL.md 或配套文件内容;可选 resources/directory/read 列目录(需 directoryRead: true

完整性校验(关键):宿主在技能"在用"期间保留其条目,并必须

  1. 把文件读取限制在清单内的 URI
  2. 每次使用前校验原始字节大小与 SHA-256 摘要
  3. 解析 SKILL.md frontmatter 并逐字段与条目里的 frontmatter 比对

校验失败的内容不得使用;持久化的授权绑定到完整的文件 URI + 摘要集合——文件有增删改,授权即失效,需重新获批。

⚠️ 读取 SKILL.md 本身不会激活技能。宿主需经其"技能加载路径"处理,校验内容并在需要时获得用户批准后才载入模型上下文。技能内容按不可信输入对待。

上限建议:单个技能不超过 512 个文件 / 16 MiB(含 SKILL.md)。

🧭 我该用哪个扩展

你的需求选它
工具跑很久,不能阻塞连接Tasks
想在对话里展示图表 / 表单 / 播放器MCP Apps
有一整套工作流指令 + 参考文件要随服务分发Skills over MCP
机器对机器、或企业集中管控授权Auth 扩展ext-auth

📖 官方资料


👉 下一小节:12.4 官方注册表 Registry

内容依据 MCP 官方规范整理 · 规范以 官方文档 为准