mcpField
D
design-api

design-api

github.com/paraskakis開発4337 回インストール2 週間前に更新
リポジトリ

design-api について

要件からユーザーストーリー、OpenAPI 生成、任意の lint までを扱う API 設計スキルです。LLM を使って API を設計する人を対象とし、必須の入力資料と任意のストーリーを区別します。

主な機能

  1. 01要件から仕様へのワークフロー
  2. 02レビュー確認付きストーリー生成
  3. 03OpenAPI 3.1.0 の生成
  4. 04スキーマと参照の検証
  5. 05任意の自動 lint

活用シーン

  1. 01API 要件をレビュー用ストーリーに整理
  2. 02承認済みストーリーから仕様を生成
  3. 03OpenAPI 文書の構造上の問題を確認
  4. 04Node.js がある環境で仕様をローカルプレビュー

インストール

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

$npx skills add https://github.com/paraskakis/skills --skill design-api

インストール後、Claude Code で/design-apiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/examples/
API-standards.md
conference-domain.md
conference-research.md
OpenAPI-best-practices.md

詳細

API の設計

API を要件 → ストーリー → OpenAPI 仕様 → リント → 反復の流れで、エンドツーエンドで設計します。これは、Emmanuel Paraskakis が LLM を使って API を設計するための手法です。

基盤となる 4 つのファイル(要件、ドメイン、標準、OpenAPI のベストプラクティス)は、常にすべて必要です。ストーリーは任意です。提供された場合は、人間による設計上の判断を表すものとして扱い、このスキルは仕様の生成に直接進みます。提供されない場合は、まずストーリーを生成し、確認のために一時停止します。

対象範囲と振り分け

トリガー条件はフロントマターの説明で定義されています。対象範囲は、要件からリント済み仕様までの完全なパイプラインです。対象範囲外となるのは、ユーザーが単一の成果物だけを求めている場合です。その場合は、該当する単独のスキル(design-api-stories、design-api-spec、または design-api-review)に振り分けてください。

各フェーズはインラインで実行します。 以下の各フェーズでは、関連スキル(design-api-stories、design-api-spec)の内容を要約しています。これらのスキルを個別のスキル呼び出しとして再実行してはいけません。このスキル独自の入力収集で、それらの処理を置き換えます。関連する SKILL.md ファイルがインストールされている場合は、フェーズの概要だけでは不十分なときに詳細を参照してください。インストールされていない場合は、ここに記載されている内容だけで実行できます。

オプションの依存関係

コアスキル(ストーリーと仕様の生成)は、追加ツールなしで動作します。すべての機能を利用するには、以下が必要です。

  • RateMyOpenAPI API キー — 自動リントとスコアリングが可能になります。api.ratemyopenapi.com/docs から無料で登録できます。環境変数 RMOA_API_KEY に設定してください。
  • Node.js — npx http-server を使ったローカルの Swagger UI プレビューが可能になります。
  • curl + python3 — RMOA API 呼び出しに使用します。ほとんどの場合、あらかじめインストールされています。

これらがなくても、このスキルは完全な OpenAPI 仕様を生成します。ただし、リントとローカルプレビューは省略されます。

入力

ユーザーは、以下のファイルを提供するか、その場所を指定する必要があります。ファイル名は任意です。ファイル名ではなく、# Title 見出しまたは内容を確認して各ファイルを特定してください。

常に必要なもの:

  1. 要件 — ICP、ニーズ、課題、ユースケース、メリット。「なぜ」と「何を」を示します。# Requirements、# Research などの見出しを確認してください。
  2. ドメイン — データオブジェクト、プロパティ、列挙型、オブジェクト間の関係。スキーマの信頼できる情報源です。# Domain、# Domain Model などの見出しを確認してください。
  3. API 標準 — スタイルガイド、命名、パス、セキュリティ、エラー処理。規約の信頼できる情報源です。# API Standards、# Style Guide などの見出しを確認してください。
  4. OpenAPI のベストプラクティス — 書式ルール、DRY 原則、SDK 互換性、コンポーネント構成。OpenAPI ドキュメントの品質を保つための信頼できる情報源です。# OpenAPI Best Practices、# OAS Best Practices などの見出しを確認してください。

任意(開始フェーズを決定します): 5. ストーリー — メソッド、リソース、パラメーターを含む、API ユーザーのストーリー。人間による設計上の判断(リソースのネスト、エンドポイントのグループ化、パラメーターの選択など)を示します。# Stories、# User Stories などの見出しを確認してください。提供された場合 → フェーズ 2(仕様)に進みます。提供されない場合 → フェーズ 1 で確認用のストーリーを生成します。

必要なファイルが不足している場合は、作業を進める前にユーザーに提供を求めてください。

ユーザー自身のファイルがない場合は、references/examples/ に含まれているカンファレンスのサンプルを使用してください。新しいドメインを創作してはいけません。 ユーザーが希望を示さないことは、ドメインを勝手に作ってよいという意味ではありません。既知の良質な入力一式を使って手法の動作を確認できるよう、カンファレンスのスケジュール管理 API をエンドツーエンドで実行してください。ユーザーがドメインを指定した場合に限り、そのドメインを創作します。

同梱サンプル

references/examples/ には、入力一式のサンプルが含まれています。

  • conference-research.md — 要件
  • conference-domain.md — ドメインモデル
  • API-standards.md — API 標準
  • OpenAPI-best-practices.md — OpenAPI のベストプラクティス

フェーズ 1:ストーリー(ストーリーが提供されている場合はスキップ)

ステップ 1:入力を読む

要件、ドメイン、標準をすべて読みます。以下を把握してください。

  • API の利用者(要件から)
  • 存在するエンティティとその関係(ドメインから)
  • 従うべき規約(標準から)

ステップ 2:テーマを特定する

要件に含まれるユースケースを、論理的なテーマごとにグループ化します。各テーマは、関連する API 操作のまとまりに対応します。ここで一時停止せず、すぐにステップ 3 に進んでください。

例外:ユーザーが明示的に段階を追ってレビューするよう求めた場合は、まずテーマを提示して待ちます。

ステップ 3:ストーリーを生成する(デフォルト=シンプル)

デフォルトではシンプルなストーリーを生成します。API の形を確認し、設計の方向性を検証するのに必要な情報だけを含めます。

シンプルなストーリー形式(デフォルト)

各ストーリーについて、次の内容のみを出力します。

#### Story [Theme].[Number]: [Name]

**As a** [actor from requirements],
**I want** to [action],
**So that** [business value].

* **Method:** `GET` / `POST` / `PUT` / `PATCH` / `DELETE`
* **Resource:** `/path/{id}/subresource`
* **Parameters:**
  * `paramName` (type, required/optional): Brief description.

シンプルなストーリーのルール:

  • メソッドとリソースは、API 標準(命名、ネスト、複数形)に必ず従うこと
  • パラメーターには、パスパラメーター、クエリパラメーター、リクエストボディのフィールドを含めること
  • 各パラメーターを必須または任意として明示すること
  • ドメインオブジェクト名とプロパティ名は、定義どおりに正確に使用すること
  • レスポンススキーマ、エラーコード、ヘッダー、実装の詳細は含めないこと
  • 標準で特別な指定がない限り、認証の詳細は含めないこと
詳細なストーリー形式(リクエスト時)

ユーザーが詳細なストーリー(例:--detailed)を求めた場合は、次を追加します。

  • 成功レスポンスの概要(ステータスコードと返される内容)
  • エラーレスポンス(ステータスコードと発生条件)
  • ヘッダー(レート制限、ページネーションカーソル)
  • ページネーション方式に関する注記

ステップ 4:レビューチェックポイント

すべてのストーリーをまとめて提示してから、次のように尋ねます。

「ストーリーを提示しました。仕様書を生成する前に変更しますか?それとも、この内容で進めてよいですか?」

  • ユーザーから変更がある場合 → 変更を反映して再提示し、もう一度尋ねます。
  • ユーザーが進行を承認した場合 → 最終ストーリーを直ちにファイルに保存します(仕様書の生成について考える前に、独立した応答で行います)。その後、フェーズ 2 に進みます。
  • ユーザーが --no-pause を指定した場合 → チェックポイントを省略し、直接先に進みます。

**重要:仕様書を生成する前に、最終レビュー済みのストーリーを必ずファイルに保存してください。**保存したストーリーはフェーズ 2 の信頼できる情報源です。仕様書には、レビュー中にユーザーが加えた変更を反映する必要があります。

**ストーリーを先に保存し、仕様書は後で保存します。別々の応答で行ってください。**ユーザーがストーリーを承認したら、独立したツール呼び出しで、直ちにファイルに書き込みます。ストーリーの保存と仕様書の生成をまとめて行わないでください。仕様書の生成には十分な検討時間が必要であり、まとめるとストーリーの保存が不必要に遅れます。先にストーリーを保存することで、ユーザーに進捗を示せるうえ、仕様書の生成に失敗した場合の確認ポイントにもなります。

ユーザーが指定したファイルにストーリーを保存するか、保存先を尋ねてください。

**既存のファイルを事前に確認したり読み込んだりせず、直接書き込んでください。**名前の競合で Write ツールが失敗した場合は、末尾に番号を追加して再試行します。


フェーズ 2:仕様書

ステップ 5:すべての入力を読む

ストーリー、ドメイン、標準、OpenAPI のベストプラクティスをすべて読み込みます。以下の全体像を把握してください。

  • ストーリーに含まれるすべてのエンドポイント(メソッド+リソース+パラメーター)
  • ドメインに含まれるすべてのデータオブジェクトと列挙型
  • 標準に含まれるすべての規約
  • ベストプラクティスに含まれるすべての書式ルール

ステップ 6:OpenAPI ドキュメントを生成する

有効な JSON ファイルを 1 つ出力します。ユーザーが別のバージョンを指定しない限り、OpenAPI 3.1.0 をデフォルトとします。

構造

ドキュメントでは次の順序に従います。

  1. openapi — "3.1.0"(またはユーザー指定のバージョン)
  2. info — タイトル、説明、バージョン、連絡先、ライセンス(ベストプラクティスに準拠)
  3. servers — 説明を含むサーバーを 1 つ以上
  4. security — 標準で認証が必要な場合は、グローバルなセキュリティスキーム
  5. tags — ストーリーのテーマごとに 1 つのタグ
  6. paths — ストーリーに含まれるすべてのエンドポイント
  7. components — スキーマ、パラメーター、レスポンス、ヘッダー、securitySchemes
スキーマ生成ルール
  • すべてのドメインオブジェクトをコンポーネントスキーマにします。 ドメインファイルにあるプロパティ名をそのまま使用します。
  • すべての列挙型をコンポーネントスキーマにします。 列挙型をインラインで定義しないでください。
  • コレクションレスポンスには専用のスキーマを用意します。 例:InstrumentCollection は、data 配列とページネーション用フィールドを含みます。
  • エラーレスポンスには、標準で別途指定されていない限り、RFC 9457(Problem Details)を使用します。
  • インラインスキーマは使用しないでください。 すべてを components/schemas に抽出し、$ref で参照します。
  • 再利用可能なパラメーターは components/parameters に定義します。 ページネーション用パラメーター(cursor、limit)や共通フィルターは、一度定義してすべての箇所で参照します。
  • 再利用可能なレスポンスオブジェクトは components/responses に定義します。 エラーレスポンス(400、401、404、429、500)は、形状ごとに一度だけ定義します。
  • 再利用可能なヘッダーは components/headers に定義します。 レート制限ヘッダーなどが該当します。
コンテンツルール
  • すべてのオペレーション、パラメーター、スキーマ、プロパティ、レスポンス、ヘッダーに、空でない description を指定する必要があります。
  • すべてのスキーマとパラメーターに example 値を指定する必要があります。ドメインファイルにある現実的な例を使用してください。
  • すべてのオペレーションに summary と operationId を指定する必要があります。
  • エラーの例はエラーの種類と一致させてください(429 の例には、「不正なリクエスト」ではなく、レート制限について記述します)。
  • $ref を積極的に使用してください。ドキュメントは DRY に保ちます。
命名ルール
  • operationId:ストーリーのアクションに合致する camelCase の動詞(例:searchInstruments、getInstrumentByFigi)
  • タグ:ストーリーにあるテーマ名に合わせます
  • スキーマ:ドメインオブジェクト名に合わせた PascalCase
  • パラメーター:ドメインプロパティ名に合わせた camelCase
追加してはいけないもの
  • ストーリーにないエンドポイントを追加しないでください
  • ドメインにないプロパティを追加しないでください
  • 標準にないセキュリティスキームを追加しないでください
  • ストーリーがシンプルでエラーコードが記載されていない場合でも、標準のエラーレスポンスを追加してください(フィルター付きコレクションエンドポイントには 400、単一リソースのエンドポイントには 404、認証が必要な場合は 401、レート制限には 429、サーバーエラーには 500)

ステップ 7:JSON を検証する

ファイルを書き込む前に、次を確認します。

  1. 出力が有効な JSON であること(末尾のカンマや重複キーがないこと)
  2. すべての $ref が存在するコンポーネントを指していること
  3. すべてのコンポーネントが少なくとも一度参照されていること(未使用のものがないこと)
  4. nullable キーワードが使用されていないこと(3.1.0 に従い、代わりに "type": ["string", "null"] を使用します)

ステップ 8:仕様を保存する

ユーザーが指定した場所に JSON として保存するか、保存先を尋ねます。特定の命名規則は必要ありません。

そのまま書き込み、既存のファイルを事前に確認したり読み込んだりしないでください。 名前の競合により Write ツールが失敗した場合は、末尾に数字を付けて再試行します。

ステップ 9:RateMyOpenAPI でリンティングする(任意)

このステップでは、RateMyOpenAPI の API キーが必要です。api.ratemyopenapi.com/docs で無料アカウントを登録してください。ログインすると、Authentication セクションに API キーが表示されます。環境変数 RMOA_API_KEY に設定してください(または任意の名前を使用できます。その場合は、以下の curl コマンドも合わせて変更してください)。

RMOA_API_KEY が設定されていない場合は、まずユーザーのシェルプロファイルを読み込んでみてください(source ~/.zshrc、source ~/.bashrc、または同等のコマンド)。キーが定義されていても、現在のセッションにはまだ読み込まれていない可能性があります。それでも設定されていない場合は、ユーザーに次のように伝えてください:「RMOA API キーが見つかりません。自動リンティングをスキップします。ratemyopenapi.com で無料キーを取得し、RMOA_API_KEY に設定すると利用できます。」その後、ステップ 10 に進んでください。

RMOA_API_KEY が設定されている場合は、仕様をアップロードしてスコアと問題の全一覧を取得してください。

まずレスポンスをファイルに書き込んでください(curl の出力を python3 -c にパイプしないでください)。RMOA のレスポンスには JSON 文字列内にリテラルの制御文字が含まれる場合があり、標準入力から読み込むと Python の厳密な JSON パーサーが拒否します。ファイルに保存してから strict=False で解析すれば、この問題とシェルによるバイト列の変換をどちらも回避できます。

curl -s -X POST \
  -H "Authorization: Bearer $RMOA_API_KEY" \
  -F "apiFile=@[/absolute/path/to/spec.json]" \
  -o /tmp/rmoa-response.json \
  -w "HTTP:%{http_code} SIZE:%{size_download}\n" \
  "https://api.ratemyopenapi.com/sync-report"

解析する前に、curl の呼び出しが HTTP:200 を返し、サイズが 0 ではないことを確認してください。そうでない場合は RMOA 側に問題があります。再試行するか、リンティングをスキップしてください。

次に、保存したレスポンスを解析してください。

python3 -c "
import json
data = json.loads(open('/tmp/rmoa-response.json').read(), strict=False)
r = data['results']['simpleReport']
issues = data['results']['fullReport']['issues']
print(f'Score: {r[\"score\"]} | Docs: {r[\"docsScore\"]} | Completeness: {r[\"completenessScore\"]} | SDK: {r[\"sdkGenerationScore\"]} | Security: {r[\"securityScore\"]}')
print(f'Report: https://ratemyopenapi.com/report/{r.get(\"reportId\", \"\")}')
print(f'Total issues: {len(issues)}')
for i, issue in enumerate(issues, 1):
    path = ' > '.join(str(p) for p in issue.get('path', []))
    print(f'{i}. [{\"ERROR\" if issue[\"severity\"]==0 else \"WARN\"}] {issue[\"code\"]}')
    print(f'   {issue[\"message\"]}')
    print(f'   Path: {path}')
    print()
"

以下のすべての修正には、問題一覧を活用してください。

結果の解釈

次の 4 つのカテゴリが採点されます(各 0~100 点)。

  • ドキュメント — 説明、概要、例
  • 完全性 — 必須フィールド、レスポンスコード、スキーマ
  • SDK 生成 — operationId、インラインスキーマなし、適切な ref
  • セキュリティ — 認証方式、401/403 レスポンス

目標:すべてのカテゴリで 100/100 点。

問題への対処
  1. 書式や完全性に関する明らかな問題は、自動修正してください(説明の欠落、例の欠落、エラーレスポンスの欠落など)。

  2. 設計上の判断が必要な問題については、ユーザーに確認してください。よくある例:

    • 認証なし/401 の欠落:API が意図的に認証を必要としない場合(例:トレーニング用の演習)、RMOA が問題として報告したことを伝え、無視するか認証を追加するかを尋ねてください。
    • エラーコードの欠落:RMOA が 401/403 を求めていても、ストーリーに認証が含まれていない場合は、確認してください。
    • 命名規則:RMOA が標準ファイルの規則と矛盾する命名パターンを指摘した場合は、標準ファイルを優先してください。その旨をユーザーに伝えてください。
  3. 修正後に再実行してください。次のいずれかに該当するまで繰り返します。

    • スコアが 100/100 になる
    • 残りの問題が、ユーザーが無視することを承認した意図的な設計上の選択である
よくある注意点
  • 認証なしの API は、セキュリティで約 65 点になります。 RMOA は、401/403 の欠落に関する警告を 8 件以上報告します。API が意図的に認証を必要としない場合、これは想定どおりです。ユーザーに確認してから先に進んでください。
  • nullable キーワード。 OpenAPI 3.1.0 では nullable が廃止されました。代わりに "type": ["string", "null"] を使用してください。RMOA はこれを問題として報告します。
  • 説明や例の欠落。 最もよくある減点項目です。すべての操作、パラメーター、スキーマのプロパティ、レスポンスに、それぞれ説明と例が必要です。ヘッダーも忘れないでください。
  • 孤立したコンポーネント。 RMOA は、components に定義されているものの $ref で一度も参照されていないスキーマを指摘します。削除するか、参照先を追加してください。
  • インラインスキーマ。 パス内に直接定義されたスキーマ($ref を使っていないもの)は、SDK 生成スコアを下げます。components/schemas に切り出してください。

ステップ 10:レポート

ユーザーに次を表示します。

## OpenAPI Spec Complete

**File:** [path]
**Score:** [Overall] / 100
  - Docs: [score]
  - Completeness: [score]
  - SDK Generation: [score]
  - Security: [score]

**Report:** [RMOA report URL]

**Issues ignored (by design):**
- [list any intentional deviations the user approved]

次に、**「Swagger UI でプレビューしますか?」**と尋ねます。

(npx http-serverを実行するための)Node.js とインターネット接続が必要です(Swagger UI は unpkg.com CDN から読み込まれます)。Node がインストールされていない場合は、「Swagger UI のプレビューには Node.js が必要です。代わりに https://editor.swagger.io に仕様を貼り付けると、そこでプレビューできます。」と伝えてから、プレビューをスキップします。

「はい」で、Node が利用できる場合は、仕様と同じディレクトリにswagger-preview.htmlファイルを作成します。

<!DOCTYPE html>
<html>
<head>
  <title>[API Name] — Swagger UI</title>
  <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
</head>
<body>
  <div id="swagger-ui"></div>
  <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
  <script>
    fetch('./[spec-filename].json')
      .then(r => r.json())
      .then(spec => {
        SwaggerUIBundle({
          spec: spec,
          dom_id: '#swagger-ui',
          deepLinking: true,
          presets: [SwaggerUIBundle.presets.apis],
          layout: "BaseLayout"
        });
      });
  </script>
</body>
</html>

次に、ローカルでサーバーを起動し、ブラウザーで開きます。

cd [spec-directory] && npx -y http-server . -p 8090 -c-1 &
sleep 2 && open http://localhost:8090/swagger-preview.html

デフォルトではポート 8090 を使用します。使用中の場合は、8091、8092 の順に試します。

ユーザーの確認が終わったら、「プレビューは終わりましたか?サーバーとプレビューファイルを片付けます。」と尋ねます。

「はい」の場合:

  1. http-server プロセスを終了します:lsof -ti:8090 | xargs kill 2>/dev/null
  2. プレビュー HTML ファイルを削除します:仕様のディレクトリからswagger-preview.htmlを削除します
  3. 次のように確認します:「サーバーを停止し、プレビューファイルを削除しました。」

重要な原則

  1. **ストーリーは人によるレビュー用であり、エンジニアリング仕様ではありません。**ひと目で確認できるようにします。PM がメソッド、リソース、パラメーターを見て、「はい、これが適切な API です」または「いいえ、X が不足しています」と判断できるようにします。

  2. **標準に厳密に従います。**標準で camelCase が指定されている場合、すべてのパラメーターを camelCase にします。リソース名を複数形にする指定がある場合、すべてのリソースを複数形にします。ストーリーは標準を最初に適用するものです。

  3. **ドメイン用語をそのまま使用します。**ドメインでexchangeMicと定義されている場合、パラメーターはexchange_micやexchangeIdではなく、exchangeMicにします。命名の基準となるのはドメインです。

  4. **ドメインの関係に従ってリソースをネストします。**Quote が Instrument に属する場合、リソースは/quotes?instrumentId=Xではなく、/instruments/{id}/quotesです。標準で定められたネストの深さの上限に従います。

  5. **要件を勝手に作りません。**要件に削除操作や更新操作の記載がない場合、それらを追加しません。依頼された内容だけを設計します。不足があると思われる場合は、黙って追加せず、質問として提示します。

  6. **ページネーションは標準に従います。**標準でカーソルベースのページネーションが指定されている場合、すべてのコレクションエンドポイントにcursorとlimitパラメーターを設定します。ページネーションの方式を混在させないでください。

  7. **ドメインをスキーマの唯一の情報源とします。**プロパティ名、型、列挙値、関係などは、すべてドメインファイルに記載されたとおりにします。

  8. **OpenAPI の品質はベストプラクティスに従います。**DRY、説明、例、コンポーネントへの切り出しなどでは、ショートカットよりベストプラクティスのファイルを優先します。

  9. **Lint は検証であり、絶対的な基準ではありません。**RMOA は実際の問題を検出しますが、意図的な設計上の判断も指摘することがあります。修正するか無視するかはユーザーが決定します。

  10. **出力は JSON のみです。**OpenAPI は YAML ではなく JSON で出力します。これは RMOA が想定する入力形式に合わせ、LLM の出力における YAML の書式問題を避けるためです。

コメント