mcpField
O
openapi-contract

openapi-contract

github.com/claude-dev-suiteテスト・品質4638 回インストール2 日前に更新
リポジトリ

openapi-contract について

フロントエンドとバックエンドの API 利用が OpenAPI 契約に準拠しているか確認するリファレンススキルです。エンドポイント、型、リクエスト、レスポンスの不一致を見つけ、契約優先の開発と自動テストを案内します。

主な機能

  1. 01エンドポイントとメソッドの確認
  2. 02リクエストとレスポンスのスキーマ検証
  3. 03一般的な契約不一致の診断
  4. 04契約優先開発のガイド
  5. 05自動テストと CI の例

活用シーン

  1. 01API 仕様と異なるフロントエンドのパスの発見
  2. 02リクエストフィールドとレスポンス型の確認
  3. 03CI パイプラインへの契約テストの追加

MCP 対応

api-explorer MCP ツールで API パスを検索し、特定のエンドポイントの詳細を取得する方法を説明します。スキーマ全体ではなく、対象を絞ったエンドポイント検索を推奨しています。

インストール

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

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill openapi-contract

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

詳細

OpenAPI コントラクト検証 - クイックリファレンス

このスキルを使用しない場合

  • GraphQL API - graphql-contract スキルを使用してください
  • 認証フロー - auth-flow-validation スキルを使用してください
  • API のバージョニング戦略 - api-versioning スキルを使用してください
  • 型生成のセットアップ - type-generation スキルを使用してください

詳細な知識: 特定のエンドポイントを検証するには、mcp__api-explorer__get_api_endpoint_details を使用してください。

コントラクト検証の概要

┌─────────────────────────────────────────────────────────────┐
│                    CONTRACT VALIDATION                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   Frontend Code          OpenAPI Spec           Backend      │
│   ┌──────────────┐      ┌────────────┐     ┌──────────────┐ │
│   │ fetch('/api/ │ ←──→ │ paths:     │ ←──→│ @Controller  │ │
│   │   users')    │      │  /users:   │     │ @GetMapping  │ │
│   │              │      │    get:    │     │              │ │
│   │ type User {  │ ←──→ │ schemas:   │ ←──→│ class UserDto│ │
│   │   id: number │      │  User:     │     │   Long id    │ │
│   │ }            │      │    id:int  │     │              │ │
│   └──────────────┘      └────────────┘     └──────────────┘ │
│                                                              │
│        MUST MATCH          SOURCE OF           MUST MATCH   │
│                            TRUTH                             │
└─────────────────────────────────────────────────────────────┘

よくある不一致の種類

1. パスの不一致
# OpenAPI Spec
paths:
  /users/{userId}:     # Backend path
    get: ...

# Frontend Code
fetch('/api/users/${id}')  # Frontend uses different path!

検出方法:

# Find API calls in frontend
grep -r "fetch\|axios\|http\." src/

# Compare with OpenAPI paths
# Use api-explorer to list paths

修正方法: フロントエンドを更新して正しいパスを使用するか、ベース URL を設定します。

2. 型の不一致
# OpenAPI Spec
components:
  schemas:
    User:
      properties:
        age:
          type: string    # Backend uses string

# Frontend Code
interface User {
  age: number;            # Frontend expects number!
}

検出方法:

// Frontend type
interface CreateUserDto {
  age: number;  // MISMATCH
}

// Should be
interface CreateUserDto {
  age: string;  // Match OpenAPI spec
}
3. 必須フィールドの欠落
# OpenAPI Spec
components:
  schemas:
    CreateUserRequest:
      required:
        - email
        - name
        - role          # Required!
      properties:
        email: { type: string }
        name: { type: string }
        role: { type: string }

# Frontend Code
const payload = {
  email: user.email,
  name: user.name,
  // role is missing!  <-- Will fail validation
};
4. レスポンス構造の不一致
# OpenAPI Spec - Paginated response
paths:
  /users:
    get:
      responses:
        200:
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

# Frontend Code - Expects array directly
const users: User[] = await response.json();  // WRONG!
// Should be
const { data, meta } = await response.json();
const users: User[] = data;

検証チェックリスト

エンドポイントごとの検証
チェック項目フロントエンドバックエンド(OpenAPI)状態
パス/api/users/users不一致
メソッドPOSTPOSTOK
Content-Typeapplication/jsonapplication/jsonOK
リクエストボディスキーマに一致CreateUserRequest確認
レスポンス型スキーマに一致User確認
ステータスコード400、401 を処理200、400、401、500一部対応
リクエストボディの検証
// OpenAPI Schema
interface CreateUserRequest {
  email: string;      // required
  name: string;       // required
  age?: number;       // optional
  role: UserRole;     // required, enum
}

// Validate frontend matches
interface FrontendPayload {
  email: string;      // OK - required
  name: string;       // OK - required
  age?: number;       // OK - optional
  role: 'admin' | 'user';  // CHECK - enum values match?
}
レスポンス処理の検証
// OpenAPI Response
interface ApiResponse<T> {
  data: T;
  meta?: {
    page: number;
    total: number;
  };
  error?: {
    code: string;
    message: string;
  };
}

// Frontend should handle all cases
async function fetchUsers(): Promise<User[]> {
  const response = await fetch('/api/users');

  if (!response.ok) {
    const error = await response.json();
    throw new ApiError(error.error.code, error.error.message);
  }

  const result: ApiResponse<User[]> = await response.json();
  return result.data;
}

コントラクトファースト開発

1. 最初に OpenAPI 仕様を定義する
# openapi.yaml
openapi: 3.0.3
info:
  title: User API
  version: 1.0.0

paths:
  /users:
    post:
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

components:
  schemas:
    CreateUserRequest:
      type: object
      required: [email, name]
      properties:
        email:
          type: string
          format: email
        name:
          type: string
          minLength: 2
          maxLength: 100

    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
        name:
          type: string
        createdAt:
          type: string
          format: date-time
2. 両方の側で型を生成する
# Frontend (TypeScript)
npx openapi-typescript openapi.yaml -o src/api/types.ts

# Backend (Java/Spring)
npx @openapitools/openapi-generator-cli generate \
  -i openapi.yaml \
  -g spring \
  -o generated/
3. 生成された型を使用して実装する
// Frontend - uses generated types
import type { CreateUserRequest, User } from './api/types';

async function createUser(data: CreateUserRequest): Promise<User> {
  const response = await fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  return response.json();
}
// Backend - uses generated DTOs
@PostMapping("/users")
public ResponseEntity<User> createUser(
    @Valid @RequestBody CreateUserRequest request) {
    // Implementation uses generated types
}

MCP api-explorer の使用方法

効率的な検証クエリ
// 1. Search for endpoint
await mcp__api_explorer__search_api({
  query: "users",
  searchIn: ["paths"],
  limit: 10
});

// 2. Get specific endpoint details
await mcp__api_explorer__get_api_endpoint_details({
  path: "/users",
  method: "POST"
});

// 3. Get request/response schemas
await mcp__api_explorer__get_api_models({
  model: "CreateUserRequest",
  compact: true
});
トークンの無駄を避ける
// DON'T - Loads entire spec
await mcp__api_explorer__get_api_schema({ format: "full" });

// DO - Query specific endpoints
await mcp__api_explorer__get_api_endpoint_details({
  path: "/users/{id}",
  method: "GET"
});

自動コントラクトテスト

Prism(モックサーバー)
# Start mock server from OpenAPI spec
npx @stoplight/prism-cli mock openapi.yaml

# Run frontend tests against mock
npm test -- --api-url=http://localhost:4010
Schemathesis(API ファジング)
# Test backend against OpenAPI spec
schemathesis run openapi.yaml --base-url=http://localhost:8080

# Validate all endpoints
schemathesis run openapi.yaml \
  --checks all \
  --validate-schema
Dredd(コントラクトテスト)
# Test implementation matches spec
dredd openapi.yaml http://localhost:8080

CI/CD への統合

GitHub Actions
name: Contract Validation
on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Validate OpenAPI spec
        run: npx @redocly/cli lint openapi.yaml

      - name: Generate types
        run: npx openapi-typescript openapi.yaml -o src/api/types.ts

      - name: Check types unchanged
        run: git diff --exit-code src/api/types.ts

      - name: Run contract tests
        run: npm run test:contract

アンチパターン

アンチパターン問題点正しい方法
型を手動で同期する時間とともにずれが生じる仕様から生成する
OpenAPI 仕様を無視する信頼できる唯一の情報源がないコントラクトファースト開発
URL をハードコードする環境に関する問題が発生するベース URL を設定する
CI で検証しない問題の発見が遅れるコントラクトテストを自動化する
API に Any 型を使う型安全性がない適切な型を生成する

トラブルシューティング早見表

問題考えられる原因解決方法
型が同期されていない手動更新仕様から再生成する
404 エラーパスの不一致OpenAPI のパスを確認する
400 Bad Request必須フィールドの欠落スキーマに照らして検証する
想定外のレスポンスレスポンス構造の変更フロントエンドの型を更新する
CORS エラーバックエンドの設定許可されたオリジンを確認する

関連スキル

コメント