mcpField
W
writing-openapi-specs

writing-openapi-specs

github.com/speakeasy-api開発18176 回インストール37 週間前に更新
リポジトリ

writing-openapi-specs について

writing-openapi-specs は、OpenAPI 仕様の作成と改善に使うリファレンススキルです。命名規約、複雑なスキーマ、再利用可能なコンポーネント、SDK 生成を意識した記述を扱います。

主な機能

  1. 01命名と構成の規約
  2. 02スキーマと多態性のパターン
  3. 03リクエスト・レスポンス・ストリーミングの指針
  4. 04再利用可能なコンポーネントの推奨事項
  5. 05例とドキュメントの作成方法
  6. 06SDK 生成時の考慮事項

活用シーン

  1. 01新しい OpenAPI 仕様の作成
  2. 02操作名や説明の改善
  3. 03nullable 型や多態データの定義
  4. 04SDK 生成に向けた仕様の準備

インストール

コマンドをコピーしてターミナルで実行します。

$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 仕様を作成する
  • オペレーションの命名や構成を改善する
  • 複雑なデータ型(列挙型、多相性、null 許容)を表現する
  • ファイルのアップロード、ストリーミング、サーバー送信イベントを扱う
  • 仕様をコード生成に適したものにする
  • 再利用パターン(コンポーネントとインライン)の理解を深める

基本原則

命名規則

オペレーション ID:resource_action パターンに従い、小文字とアンダースコアを使用します。

# Good
operationId: users_list
operationId: users_get
operationId: users_create

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

コンポーネント名:スキーマ、パラメーター、その他の再利用可能なコンポーネントには 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

example より examples を使用する:複数形の 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 を参照してください。

再利用性

次の項目にはコンポーネントを作成します:

  • 複数のオペレーションで使用されるスキーマ
  • 共通のパラメーター(ページネーション、フィルタリング)
  • 共通のレスポンス(エラー、成功パターン)
  • セキュリティスキーム

次の項目はインラインのままにします:

  • オペレーション固有のリクエストボディ
  • 固有のレスポンス形式
  • 一度しか使用しないパラメーター
# 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:値がちょうど 1 つのスキーマに一致します(型の判別)。

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:値がすべてのスキーマに一致します(合成/継承)。

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

anyOf:値が 1 つ以上のスキーマに一致します(柔軟なユニオン)。

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 を参照してください。

null 許容型

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})

よくある落とし穴

避けること:

  • 「データを取得します」や「オブジェクトを返します」のような一般的な説明を使う
  • 命名規則を混在させる(スタイルを1つ選び、一貫して使用してください)
  • operationId を忘れる(自動生成された名前が使われます)
  • examples(複数形)のつもりで example を使う(複数形のほうが適切です)
  • すべてを必須にする(オプションフィールドを慎重に検討してください)
  • すべてをインラインにする(再利用性のためにコンポーネントを使ってください)
  • すべてを参照する(単純で一度しか使わないスキーマはインラインにしてください)
  • エラーレスポンスの記述を忘れる
  • 説明なしにマジックナンバーを使う
  • コンテンツタイプを省略する(明示してください)

推奨事項:

  • 実行可能で具体的な説明を用意する
  • 全体で一貫した命名パターンを使う
  • すべてのオペレーションに明確な operationId を定義する
  • 名前付きの例を使い、examples(複数形)を指定する
  • 必須フィールドとオプションフィールドを慎重に検討する
  • 再利用性と明確さのバランスを取る
  • 想定されるすべてのレスポンス(成功とエラー)を記述する
  • 制約と検証ルールを説明する
  • コンテンツタイプとフォーマットを明示する

コメント