语义至关重要:如何将 OpenAPI 规范转化为 MCP 工具

点击查看目录

最近我在 The API Experience Podcast 上和 Matt McLarty 以及 Mike Amundsen 聊了聊我最近写的一篇博客,主题是 如何用“能力”来描述 API。其中一个被提到的观点是,是否可以在 OpenAPI 规范中直接嵌入语义信息。我当时的一个评论是:“理想情况下,你应该可以从 OpenAPI 规范直接生成一个 MCP(Model-Computable Proxy)服务端,从而向 Agent 或 AI 模型暴露你的能力。”这个观点与 Kevin Swiber 的一个深刻观察不谋而合,即 MCP 将成为终极的 API 使用者,而不是所谓的 API 杀手。我想借此机会展开讲讲,因为这个思路非常值得深入探讨。

我首先想到的是,确实,如今大家普遍用 OpenAPI 规范文档来描述自己的 API。但正如 Mike Amundsen 指出的那样,这种描述在“语义信息”以及“以能力为中心的 API 表达”方面仍存在明显不足。当人类开发者直接使用 API 时,他们可以自行填补“语义上下文”的空白,选择合适的 API 并构建逻辑。但 AI agent 或工具并不具备这种人类主观判断力,LLM 需要尽可能多的上下文信息,才能做出正确的工具选择决策。

然而,我们并不希望由此产生“语义描述分裂”的问题:一套面向 MCP 的 API 语义描述,另一套则用于给开发者直接阅读和使用。我们更希望有一个统一的“单一真相来源(single source of truth)”,那就是 OpenAPI 规范。但要做到这一点,就需要我们在 OpenAPI 描述中投入更多精力,将 API 的“语义意义”以及“能力描述”表达得更加清晰、丰富。

从 API 到能力

在过去十几年中,许多企业投入大量精力,将内部和外部的业务能力通过 API 对外暴露。这一趋势不会消失。虽然 MCP(Model-Computable Protocol)非常令人兴奋,但归根结底,它只是一个供 AI 模型调用工具的协议适配层。但如果我们希望正确地向模型暴露工具,就必须以“能力”而非单纯的 API 合约结构来描述

  • 工具名称应具有唯一性,且具备动词导向的动作意义(例如使用 “listAllTodoTasks” 而非简单的 “list”);
  • 提供详细的用途说明
  • 展示在什么场景下可以调用,并提供请求/响应示例;
  • 明确使用工具的前置条件

使用 OpenAPI 规范

OpenAPI 规范(OpenAPI Specification)本身包含了许多字段与结构,支持我们为 API 添加丰富的语义含义:

  • 利用 info 部分添加全局信息;
  • 多个部分支持链接至 externalDocs,提供外部文档支持;
  • 大多数部分都支持 titlesummarydescription 字段;
  • 借助 JSON-LD 可将字段链接到行业通用或企业专属的数据语义模型,提供更深层的语义描述;
  • 如果上述方式都不满足需求,还可以使用自定义的扩展属性 x-* 扩展规范。

下面是一个具体示例:

info 字段中添加丰富语义的 Todo API 描述:

openapi: 3.0.3
info:
  title: Enhanced Todo API
  description: >
    本 API 提供了管理个人或团队待办事项(todos)的能力,包括创建、更新、组织和检索任务,任务附带丰富的元数据,如截止日期、优先级和标签。
    该 API 专为系统和 AI Agent 设计,支持动态任务协调、进度追踪和工作流规划。
    特别适用于目标跟踪、工作助手或生产力工具等需要任务编排和上下文决策的场景。
  version: 1.0.0
  termsOfService: https://example.com/terms/
  contact:
    name: API Support Team
    url: https://example.com/support
    email: [email protected]
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html

我们还应该链接该 API 的使用文档:

externalDocs:
  description: 查看该 API 所有使用场景的详细文档
  url: https://example.com/docs

在具体 API 路径中,加入更详细的语义描述:

  /todos:
    get:
      summary: 获取现有待办事项,用于上下文任务感知与规划
      description: >
        客户端或 AI Agent 可调用该接口,检索现有的待办事项列表,支持按完成状态过滤、分页控制。
        该能力可帮助理解当前任务状态、识别待办任务、规划下一步行动。
        特别适用于依赖实时上下文的工作流,如生产力跟踪、个人助手、自动化规划系统。
      operationId: listAllTodoTasks
      tags:
        - todos
      parameters:
        - name: limit
          in: query
          description: 返回的最大条目数
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 100
            default: 20
        - name: completed
          in: query
          description: 按任务完成状态进行筛选
          schema:
            type: boolean
      responses:
        '200':
          description: JSON 格式的待办事项数组
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Todo'
                  pagination:
                    $ref: '#/components/schemas/Pagination'

使用 JSON-LD(JSON 语义链接数据),我们可以为请求或响应中的数据模型赋予确切的语义含义。通过链接到行业标准(如 schema.orgw3.org)或企业自定义语义本体,可以让 API 的数据结构具备强语义。以下是一个添加 JSON-LD 语义结构的示例:

openapi: 3.0.3
info:
  # 为简洁省略部分内容
  x-linkedData:
    "@context":
      schema: "https://schema.org/"
      hydra: "http://www.w3.org/ns/hydra/core#"
      vocab: "https://api.example.com/vocab#"
    "@type": "schema:WebAPI"
    "@id": "https://api.example.com/v1"
    "schema:name": "Enhanced Todo API"
    "schema:description": "一个提供待办管理、元数据和语义注释的综合 API"
    "schema:provider":
      "@type": "schema:Organization"
      "schema:name": "Example Organization"
      "schema:url": "https://example.com"
    "schema:dateModified": "2025-04-15"

如果上述方法都无法满足你的需求,你还可以选择扩展 OpenAPI 规范,添加你自己的自定义属性。例如,当你对路径的 descriptionsummary 字段存在向后兼容性问题时,可以添加自定义字段以增强描述能力:

  /todos:
    get:
      summary: 获取现有待办事项,用于上下文任务感知与规划
      description: 简要描述在此
      tags:
        - todos
      x-company-mcp:
        name: very-descriptive-name-here
        description: 更详细的描述信息

转换为 MCP 工具

接下来我们要思考:如何将 OpenAPI 规范转换为 MCP 工具?我们可以用 operationId 作为工具的名称,但描述信息该如何处理?MCP 工具需要以“能力”为中心进行描述,并提供足够的上下文,让 AI 模型能够判断该使用哪个工具、在什么时机使用。

在将 OpenAPI 映射为 MCP 工具时,可以直接使用 operation 的描述信息和参数说明,也可以在映射过程中对这些内容进行增强。你甚至可以借助 JSON-LD 的 URI 来补全数据结构的语义信息。以下是一个典型的 MCP 工具响应示例:

{
  "jsonrpc": "2.0",
  "id": 123,
  "result": {
    "tools": [
      {
        "name": "listAllTodoTasks",
        "description": "允许客户端或 AI Agent 检索现有的待办事项列表,支持按完成状态过滤并支持分页参数限制。
        该能力有助于理解当前任务状态、识别未完成事项以及规划后续行动。适用于生产力追踪、个人助手或依赖实时上下文的自动化规划系统。",
        "inputSchema": {
          "type": "object",
          "properties": {
            "limit": {
              "type": "integer",
              "description": "返回的最大项数(1-100)",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "completed": {
              "type": "boolean",
              "description": "按完成状态筛选"
            }
          }
        },
        "annotations": {
          "title": "增强版 Todo API",
          "readOnlyHint": true,
          "openWorldHint": false
        }
      }
    ]
  }
}

将 OpenAPI 规范作为 API 的“单一事实来源”(Single Source of Truth)——包括其衍生物如 MCP shim——至关重要。如果忽视 OpenAPI 的质量和一致性,会在后续流程中造成严重问题,尤其是在与 AI Agent、LLM 或基于 MCP 的工具集成时。描述不清或结构不一致的规范可能导致服务间不匹配、MCP 工具生成困难、版本或后端兼容性问题,甚至会破坏 AI Agent 的工作流。

而对于 AI 模型而言,如果工具描述模糊或不完整,可能会导致错误的理解:选错工具、使用无效参数,或者误解意图(如应当查询却去创建数据)。这些问题不仅会降低 Agent 的行为质量,还可能导致“幻觉式”响应、偏离目标的操作,甚至彻底失败。

我们可以总结如下对照表:

MCP 工具字段 OpenAPI 对应字段 说明
工具名称 operationId 唯一、便于机器识别;如无,可退回至 HTTP 方法+路径
工具描述 summary / description 简洁用 summary,详细说明用 description
输入结构(参数) parametersdescription 包括类型、约束的结构化输入
输出结构(响应) responses 包括成功与错误响应的结构化输出
调用细节 servers, path, method 包括 URL、HTTP 方法、服务器信息
安全性 security, components.securitySchemes 用于描述需要鉴权的接口

关于安全的补充说明

LLM 提示注入(prompt injection) 是当前 AI 安全的一个重大风险(参见 OWASP Top 10 for LLM 应用)。当工具的 description 或参数说明被恶意注入指令时,就可能发生所谓的 工具投毒攻击(tool poisoning)(详见 Invariant Labs 的安全通告)。因此,务必要对 OpenAPI 规范进行审核和“清洗”。理想情况下,这应当在 API 治理流程中完成;但作为兜底方案,也可以在 OpenAPI 转换为 MCP 工具的过程中加入清洗流程。我将会在后续博客中深入探讨这个问题。

这种映射应当发生在哪里?

正如前文所述,虽然未来可能出现原生支持 MCP 的实现方案,但企业最终仍是要基于已有的 API 投资来暴露 MCP 工具。那么这种 OpenAPI 到 MCP 的映射 应该在哪里发生呢?

  • 有可能会出现“AI 原生工具”来完成这类转换,它们会考虑到上面提到的语义因素;
  • 有可能你会使用支持将 REST API 暴露为 MCP 端点的 API Gateway;
  • 也可能你需要自行构建一些映射逻辑工具。

编辑本页