mcpField
W
writing-openapi-specs

writing-openapi-specs

github.com/speakeasy-api开发18176 次安装37 周前更新
代码仓库

关于 writing-openapi-specs

writing-openapi-specs 是编写和改进 OpenAPI 规范的参考技能,面向 API 设计与文档工作。它汇总命名约定、复杂模式、可复用组件及面向 SDK 生成的编写建议。

主要功能

  1. 01命名与组织约定
  2. 02模式和多态结构示例
  3. 03请求、响应及流式传输指南
  4. 04可复用组件建议
  5. 05示例与文档编写规范
  6. 06SDK 生成注意事项

适用场景

  1. 01起草新的 OpenAPI 规范
  2. 02改进操作名称和描述
  3. 03建模可空或多态数据
  4. 04为 SDK 生成准备规范

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/speakeasy-api/sdk-generation-skills --skill writing-openapi-specs

安装后在 Claude Code 中输入/writing-openapi-specs确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

reference/
components.md
examples.md
operations.md
parameters.md
request-bodies.md
responses.md
schemas.md
security.md

详细介绍

编写 OpenAPI 规范

OpenAPI 最佳实践和约定参考。本技能为 OpenAPI 规范本身未涵盖的风格、约定和灰色地带提供指导。

何时使用此技能

  • 编写新的 OpenAPI 规范
  • 改进操作命名和组织方式
  • 表达复杂数据类型(枚举、多态、可空)
  • 处理文件上传、流式传输或服务器发送事件
  • 让规范更适合代码生成
  • 了解可复用模式(components 与内联定义)

核心原则

命名约定

操作 ID:使用小写字母和下划线,遵循 resource_action 模式:

# Good
operationId: users_list
operationId: users_get
operationId: users_create

# Avoid
operationId: GetApiV1Users    # Auto-generated, not semantic

组件名称:对 schemas、parameters 和其他可复用组件使用 PascalCase:

components:
  schemas:
    UserProfile:      # PascalCase
    OrderHistory:     # PascalCase
  parameters:
    PageLimit:        # PascalCase

标签:使用小写字母和连字符,创建便于机器处理的标签:

tags:
  - name: user-management
    description: Operations for managing users
  - name: order-processing
    description: Operations for processing orders

更多详情,请参阅 reference/operations.md 和 reference/components.md。

文档标准

使用 CommonMark:所有 description 字段均支持 CommonMark 语法,以实现丰富格式:

description: |
  Retrieves a user by ID.

  ## Authorization
  Requires `users:read` scope.

  ## Rate Limits
  - 100 requests per minute per API key
  - 1000 requests per hour per IP

具体明确:提供可执行的信息,而非泛泛的描述:

# Good
description: Returns a paginated list of active users, ordered by creation date (newest first)

# Avoid
description: Gets users

优先使用 examples 而非 example:复数形式的 examples 字段更有利于生成 SDK:

# Good
examples:
  basic_user:
    value:
      id: 123
      name: "John Doe"
  admin_user:
    value:
      id: 456
      name: "Jane Admin"
      role: admin

# Avoid single example
example:
  id: 123
  name: "John Doe"

更多详情,请参阅 reference/examples.md。

可复用性

适合创建 components 的内容:

  • 多个操作中使用的 schemas
  • 通用参数(分页、筛选)
  • 通用响应(错误、成功模式)
  • 安全方案

适合内联定义的内容:

  • 特定操作的请求体
  • 独特的响应结构
  • 一次性参数
# Reusable schema
components:
  schemas:
    User:
      type: object
      properties:
        id: {type: integer}
        name: {type: string}

# Reference it
paths:
  /users/{id}:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

更多详情,请参阅 reference/components.md。

复杂模式速查

以下模式通常较难处理。下面提供简要示例,并附有详细指南的链接。

枚举

使用字符串枚举,并选择清晰且有语义的值:

type: string
enum:
  - pending
  - approved
  - rejected
  - cancelled

避免使用:

  • 数字字符串("0"、"1"、"2")
  • 通用值("value1"、"value2")
  • 含义不明的缩写("pnd"、"appr")

更多内容,请参阅 reference/schemas.md#enums。

多态(oneOf/allOf/anyOf)

oneOf:值恰好匹配一个 schema(类型判别)

PaymentMethod:
  oneOf:
    - $ref: '#/components/schemas/CreditCard'
    - $ref: '#/components/schemas/BankAccount'
    - $ref: '#/components/schemas/PayPal'
  discriminator:
    propertyName: type
    mapping:
      credit_card: '#/components/schemas/CreditCard'
      bank_account: '#/components/schemas/BankAccount'
      paypal: '#/components/schemas/PayPal'

allOf:值匹配所有 schemas(组合/继承)

AdminUser:
  allOf:
    - $ref: '#/components/schemas/User'
    - type: object
      properties:
        permissions:
          type: array
          items: {type: string}

anyOf:值匹配一个或多个 schemas(灵活的联合)

SearchFilter:
  anyOf:
    - $ref: '#/components/schemas/TextFilter'
    - $ref: '#/components/schemas/DateFilter'
    - $ref: '#/components/schemas/NumericFilter'

详细指导,请参阅 reference/schemas.md#polymorphism。

判别器

将判别器与 oneOf 配合使用,以高效识别类型:

Pet:
  oneOf:
    - $ref: '#/components/schemas/Dog'
    - $ref: '#/components/schemas/Cat'
  discriminator:
    propertyName: petType
    mapping:
      dog: '#/components/schemas/Dog'
      cat: '#/components/schemas/Cat'

Dog:
  type: object
  required: [petType, bark]
  properties:
    petType:
      type: string
      enum: [dog]
    bark:
      type: string

Cat:
  type: object
  required: [petType, meow]
  properties:
    petType:
      type: string
      enum: [cat]
    meow:
      type: string

更多内容,请参阅 reference/schemas.md#discriminators。

可空类型

根据 OpenAPI 版本采用不同方式处理 null 值:

OpenAPI 3.1(符合 JSON Schema 2020-12):

type: [string, "null"]
# or
type: string
nullable: true  # Still supported for compatibility

OpenAPI 3.0:

type: string
nullable: true

对于可选字段,请使用 required 数组:

type: object
properties:
  name: {type: string}      # Can be omitted
  email: {type: string}     # Can be omitted
required: [name]            # email is optional

更多内容,请参阅 reference/schemas.md#nullable。

文件上传

使用 multipart/form-data 上传文件:

requestBody:
  required: true
  content:
    multipart/form-data:
      schema:
        type: object
        properties:
          file:
            type: string
            format: binary
          metadata:
            type: object
            properties:
              description: {type: string}
              tags:
                type: array
                items: {type: string}
        required: [file]

在 JSON 中使用 Base64 编码文件:

requestBody:
  content:
    application/json:
      schema:
        type: object
        properties:
          filename: {type: string}
          content:
            type: string
            format: byte  # base64-encoded

更多内容,请参阅 reference/request-bodies.md#file-uploads。

服务器发送事件(SSE)

使用 text/event-stream 描述流式响应:

responses:
  '200':
    description: Stream of events
    content:
      text/event-stream:
        schema:
          type: string
          description: |
            Server-sent events stream. Each event follows the format:

            ```
            event: message
            data: {"type": "update", "content": "..."}

            ```
        examples:
          notification_stream:
            value: |
              event: message
              data: {"type": "notification", "message": "New order received"}

              event: message
              data: {"type": "notification", "message": "Order processing complete"}

更多模式,请参阅 reference/responses.md#streaming。

字段参考

各主要 OpenAPI 字段的详细指南:

SDK 生成注意事项

编写用于生成 SDK 的规范时:

  1. 始终定义 operationId:这是生成有意义的方法名所必需的
  2. 提供丰富的示例:有助于生成更好的文档和测试
  3. 明确说明必需字段:这会影响 SDK 方法签名
  4. 在 oneOf 中使用判别器:可生成类型安全的联合类型
  5. 记录错误响应:可生成更好的错误处理代码

适用于 SDK 的操作示例:

paths:
  /users:
    get:
      operationId: users_list
      summary: List all users
      description: Returns a paginated list of users
      parameters:
        - name: limit
          in: query
          schema: {type: integer, default: 20}
        - name: offset
          in: query
          schema: {type: integer, default: 0}
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                required: [data, pagination]
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/PaginationInfo'
              examples:
                success:
                  value:
                    data: [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]
                    pagination: {total: 100, limit: 20, offset: 0}

这会生成:sdk.users.list({limit: 20, offset: 0})

常见陷阱

不要:

  • 使用“获取数据”或“返回对象”这类泛泛的描述
  • 混用命名约定(选定一种风格并坚持使用)
  • 忘记 operationId(会导致自动生成名称)
  • 需要 examples 时使用 example(复数形式更好)
  • 将所有字段都设为必需(谨慎考虑可选字段)
  • 将所有内容都内联(使用组件以便复用)
  • 对所有内容都使用引用(简单且只用一次的架构应内联)
  • 忘记记录错误响应
  • 使用没有说明的魔法数字
  • 遗漏内容类型(应明确指定)

应该:

  • 提供可操作且具体的描述
  • 在全文使用一致的命名模式
  • 为每个操作定义清晰的 operationId
  • 使用带命名示例的 examples(复数形式)
  • 仔细考虑必需字段与可选字段
  • 在可复用性与清晰度之间取得平衡
  • 记录所有预期响应(成功和错误)
  • 说明约束和验证规则
  • 明确指定内容类型和格式

评论

支持 Markdown