mcpField
S
stitch-sdk-development

stitch-sdk-development

github.com/google-labs-code開発1.8k206 回インストール4 週間前に更新
リポジトリ

stitch-sdk-development について

`@google/stitch-sdk` の開発者向けスキルです。SDK の生成パイプライン、アーキテクチャ上の境界、実装手順を解説します。

主な機能

  1. 013段階のSDK生成パイプライン
  2. 02MCPツールとドメインのバインディング指針
  3. 03生成コードの整合性チェック
  4. 04副作用を伴う機能の実装パターン
  5. 05レッド・グリーン・イエローのテスト手順

活用シーン

  1. 01Stitchの新しいツールをSDKに追加
  2. 02ドメインクラスとメソッドの設計
  3. 03ファイルシステムやネットワーク拡張の実装
  4. 04SDK変更のテストと検証

MCP 対応

Stitch MCP サーバーからツールスキーマを取得し、生成SDKクラスへ対応付ける方法を説明します。`StitchToolClient`の通信機能と、`StitchProxy` MCPプロキシサーバーも扱います。

インストール

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

$npx skills add https://github.com/google-labs-code/stitch-sdk --skill stitch-sdk-development

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

詳細

Stitch SDK の開発

このスキルでは、@google/stitch-sdk の開発に必要な専門知識、つまり中核となるシステム、パターン、設計思想を説明します。すべてのメソッドを列挙するものではありません(信頼できる情報源はコードベースです)。システムの考え方を学ぶためのものです。


生成パイプライン

ドメインレイヤーはすべて生成されます。手書きのドメインクラスはありません。パイプラインは3つのステージで構成されます。

Stage 1: Capture            Stage 2: Domain Design       Stage 3: Generate
┌──────────────────┐       ┌──────────────────┐        ┌──────────────────────────┐
│ capture-tools.ts │──────▶│  domain-map.json │───────▶│ generate-sdk.ts          │
│                  │       │  (the IR)        │        │                          │
│ Connects to MCP  │       │ Classes, bindings│        │ Deterministic            │
│ server, calls    │       │ arg routing,     │        │ codegen into             │
│ tools/list       │       │ cache, extraction│        │ packages/sdk/generated/  │
└──────────────────┘       └──────────────────┘        └──────────────────────────┘
        │                          │                           │
        ▼                          ▼                           ▼
 tools-manifest.json        domain-map.json          packages/sdk/generated/src/*.ts
 (raw MCP tool schemas)     (tool→class mapping)     (Stitch, Project, Screen)

ステージ1(bun scripts/capture-tools.ts):稼働中の Stitch MCP サーバーに接続してtools/listを呼び出し、tools-manifest.jsonに書き込みます。どのツールが存在するかを示す信頼できる情報源です。

ステージ2(エージェント/人間):マニフェストを読み込み、中間表現であるdomain-map.jsonを作成します。ここで判断が必要になります。どのツールをどのクラスに対応付けるか、どの引数をself、param、computedから取得するか、戻り値をどう抽出するか、どのデータをキャッシュするかを決めます。

ステージ3(bun scripts/generate-sdk.ts):決定論的なコード生成を行います。マニフェストと domain-map を読み込み、packages/sdk/generated/src/に TypeScript クラスを出力します。LLM は関与せず、テンプレート展開のみで生成されます。

整合性:stitch-sdk.lockには、すべての入力と出力の SHA-256 ハッシュが記録されます。bun scripts/validate-generated.tsで整合性を検証します。古いコードの公開を防ぐため、CI で実行してください。

新しいツールへの対応

Stitch MCP サーバーに新しいツールが追加された場合:

  1. ステージ1を実行し、更新されたマニフェストを取得します
  2. ステージ2を実行し、新しいツールのバインディングをdomain-map.jsonに追加します
  3. ステージ3を実行し、SDK クラスを再生成します
  4. validate-generated.tsを実行して、整合性を確認します
  5. 必要に応じてテストを更新します
Domain Map IR

domain-map.jsonでは、次の2つを表現します。

クラス:存在するドメインオブジェクトとその構築方法。

{
  "Screen": {
    "constructorParams": ["projectId", "screenId"],
    "parentField": "projectId",
    "reference": { "keys": ["projectId", "screenId"] }
  }
}

バインディング:MCP ツールをクラスメソッドに対応付ける方法。

{
  "tool": "generate_screen_from_text",
  "class": "Project",
  "method": "generate",
  "args": {
    "projectId": { "from": "self" },
    "prompt": { "from": "param" },
    "name": {
      "from": "computed",
      "template": "projects/{projectId}/screens/{screenId}"
    }
  },
  "returns": {
    "class": "Screen",
    "projection": [
      { "prop": "outputComponents", "index": 0 },
      { "prop": "design" },
      { "prop": "screens", "index": 0 }
    ]
  }
}

引数の振り分け:self=thisから注入、param=呼び出し元から渡される、computed=呼び出し時にテンプレートから構築、selfArray=[this.field]を配列でラップ。

レスポンスの射影:outputSchemaに照らして検証される、構造化されたProjectionStep[]配列です。単一の項目にはindex、配列にはeachを使用します。空の[]は直接返すことを意味します。

キャッシュ:メソッドでは、API 呼び出し前にthis.dataを確認するため、構造化されたprojectionを含むcacheを指定できます。

{
  "cache": {
    "projection": [{ "prop": "htmlCode" }, { "prop": "downloadUrl" }],
    "description": "Use cached download URL from generation response"
  }
}

2つの利用形態

SDK は、ニーズの異なる2種類の利用者に対応します。

エージェント向け — StitchToolClient

AI エージェントやオーケストレーションスクリプト向けです。ツールとのやり取りをそのまま行います。エージェントはツールスキーマを受け取り、JSON を構築して送信し、JSON を受け取ります。ドメイン知識は必要ありません。

クイックスタート(シングルトン)

stitchシングルトンは、Proxyを介してドメインメソッドとツールメソッドの両方を提供します。インスタンス化は不要です。初めてアクセスした際に、環境変数からStitchToolClientを遅延生成します。

import { stitch } from "@google/stitch-sdk";

// Discover available tools
const { tools } = await stitch.listTools();

// Call any tool by name with a JSON payload
const result = await stitch.callTool("generate_screen_from_text", {
  projectId: "123",
  prompt: "A login page",
});

// Clean up when done
await stitch.close();

シングルトンは、環境変数からSTITCH_API_KEY(またはSTITCH_ACCESS_TOKENとGOOGLE_CLOUD_PROJECT)を読み込みます。サーバー URL を上書きするには、STITCH_BASE_URLを設定します。(STITCH_HOSTは非推奨の別名で、2.0で削除されます。)

直接インスタンス化

明示的な制御(複数のクライアント、カスタム設定、テスト)が必要な場合は、StitchToolClientを直接インスタンス化します。

import { StitchToolClient } from "@google/stitch-sdk";

const client = new StitchToolClient({ apiKey: "my-key" });
const tools = await client.listTools();
const result = await client.callTool("create_project", { title: "My App" });
await client.close();

設定の解決順序:コンストラクターのパラメーター → 環境変数 → デフォルト値。認証には、apiKeyまたはaccessTokenとprojectIdの組み合わせが必要です(インスタンス生成時に Zod で検証されます)。

接続:callToolとlistToolsは、初回呼び出し時に自動接続します。並行する呼び出しは、Promise ベースのロックを介して安全に接続を共有します。

AI SDK アダプター — stitchTools()

Vercel AI SDK で構築されたエージェント向けです。MCP ツールスキーマを AI SDK 互換のツール定義に変換し、generateText() とのプラグアンドプレイを可能にします。

import { stitchTools } from "@google/stitch-sdk/ai";
import { generateText } from "ai";
import { google } from "@ai-sdk/google";

const result = await generateText({
  model: google("gemini-2.0-flash"),
  tools: stitchTools(), // all tools
  // or: stitchTools({ include: ["create_project"] })  // filtered
  prompt: "Create a project called My App",
});

stitchTools() は ai 依存をオプションに保つため、/ai サブパスからエクスポートされています。内部的には同じ共有 StitchToolClient シングルトンを使用します。

/tools サブパスは、事前パース済みパラメータによる O(1) のツールルックアップを提供します — 静的、認証不要、ネットワーク呼び出しなし:

import { toolMap } from "@google/stitch-sdk/tools";
const tool = toolMap.get("create_project");
tool.params; // ToolParam[] — flat, pre-parsed
tool.params.filter((p) => p.required); // required params only
tool.inputSchema; // raw ToolInputSchema still available

toolDefinitions と toolMap はどちらも @google/stitch-sdk/tools サブパスからエクスポートされています (ルートエントリには含めず、スリムに保たれています)。

SDK モダリティ — 生成されたドメインクラス

正確でプログラム的なスクリプトを書く人間向けです。callTool 上の生成されたドメインファサードです。型付きパラメータ、ドメインオブジェクトが返され、失敗時には StitchError がスローされます。

const project = await stitch.createProject({ title: "My App" });
const generation = await project.generate("A login page");
const html = await generation.first.getHtml();

両方のモダリティは、内部的に StitchToolClient を共有しています。ドメインクラスは callTool 上の型付きレイヤーです。

エラーハンドリング — 境界でスローする

生成されたすべてのメソッドは、エラーハンドリングに throw StitchError を使用します。Result<T> パターンはありません。

// Generated method pattern (inside each method):
try {
  const raw = await this.client.callTool<any>("tool_name", args);
  return /* extracted result */;
} catch (error) {
  throw StitchError.fromUnknown(error);
}

StitchError.fromUnknown() は、すべてのエラーがコード、メッセージ、回復可能性のヒントを持つ StitchError に正規化されることを保証します。

インフラストラクチャ (手書き)

これらのコンポーネントは基盤となる配管を提供するため、手書きのままです:

  • StitchToolClient — MCP トランスポート、認証、ツール呼び出し
  • StitchError — コード、メッセージ、回復のヒントを持つ型付きエラークラス
  • StitchProxy — Stitch を他のエージェントに再公開するための MCP プロキシサーバー
  • singleton.ts — 環境変数設定を伴う stitch エクスポート用の遅延プロキシ
副作用の膜

SDK には、正式な境界によって分離された 2 つの半球があります:

  • 生成された半球 — すべての MCP ツール呼び出し、レスポンス投影、引数ルーティング、クラスコンストラクタ。JSON を送信して JSON を受け取る場合、それは生成されなければなりません (MUST)。
  • 手書きの半球 — 実世界に触れる操作: ファイルシステム I/O、バイナリストリーム、非 MCP REST エンドポイント。ディスクに触れる、またはプライベート API を使用する場合、それは手書きでなければなりません (MUST)。

膜は、extensionPath を持つ任意のクラスの sideEffects を介して domain-map.json で宣言されます:

{
  "Project": {
    "extensionPath": "../../src/project-ext.js",
    "sideEffects": [
      {
        "method": "upload",
        "reason": "private_rest",
        "specPath": "src/spec/upload.ts"
      },
      {
        "method": "downloadAssets",
        "reason": "filesystem_io",
        "specPath": "src/spec/download.ts"
      }
    ]
  }
}

有効な reason の値: filesystem_io、binary_data、private_rest、complex_orchestration。

ジェネレーターはステージ 3 で検証します:

  1. どの sideEffect.method も、生成されたバインディングメソッド名と衝突しないこと
  2. 各 specPath が既存のファイルを指していること
新しい副作用メソッドの追加

Spec → Handler → Extension パターンに従ってください:

  1. Spec を作成する (src/spec/my-operation.ts): 入力スキーマ (Zod)、エラーコード、Result 型、インターフェースを定義します。Handler はこのインターフェースを実装し、決してスローしてはなりません。

  2. Handler を作成する (src/my-operation-handler.ts): Spec インターフェースを実装します。すべての失敗は Result<T> を返し、決して throw しません。ここに副作用ロジック (ディスク、ネットワーク、バイナリ) が置かれます。

  3. Extension に追加する (src/project-ext.ts): 入力をパースし、Handler を呼び出し、失敗時に Result を throw StitchError にマッピングする薄いアダプター (メソッド本体ごとに 15 行未満)。

  4. domain-map.json で宣言する: method、reason、specPath を持つ sideEffect エントリを追加します。

  5. 再生成する: bun scripts/generate-sdk.ts を実行します — ジェネレーターが宣言を検証します。

ルール
ルール根拠
Extension メソッドは生成されたメソッドをオーバーライドしてはならない暗黙のシャドーイングを防ぐ
Extension メソッドは Handler に委譲しなければならないインラインビジネスロジックを防ぐ
Handler は Spec インターフェースを実装しなければならない型付きサービスコントラクト
Handler は Result を返し、決してスローしてはならない一貫したエラーサーフェス
Extension は singleton.ts からインポートしてはならない循環依存を防ぐ

トラフィックライト方式(赤 → 緑 → 黄)

新機能を実装するときやバグを修正するときは、トラフィックライト方式に従ってください。

🔴 赤 — 失敗するテストを書く

まずテストを書きます。テストは失敗する必要があります。これにより、実装に着手する前に契約を定義します。

# Unit tests for generated classes
npx vitest run test/unit/sdk.test.ts
# → FAIL (new method doesn't exist yet)

# E2E test for the public API
bun scripts/e2e-test.ts
# → FAIL (method doesn't exist yet)
🟢 緑 — 実装する
  1. domain-map.json にバインディングを追加します(ステージ 2)
  2. bun scripts/generate-sdk.ts を実行します(ステージ 3)
  3. 正しい動作を検証するようにテストを更新します
npx vitest run  # All tests pass
bun scripts/e2e-test.ts  # E2E passes
🟡 黄 — リファクタリング/改善/見直し

テストが合格する状態を安全網として、次の作業を行います。

  • 明瞭さを高めるためにリファクタリングします(ヘルパーの抽出、引数の簡素化など)
  • エッジケースのテストを追加します
  • npx tsc を実行して型安全性を検証します
  • bun scripts/validate-generated.ts を実行してパイプラインの整合性を検証します

コードベースの把握

コードベースを直接読んで、現在の状態を確認してください。主なエントリーポイントは次のとおりです。

  • 公開インターフェース:packages/sdk/src/index.ts から始めます。すべての公開エクスポートが一覧表示されています
  • 生成されたクラス:packages/sdk/generated/src/ — Stitch、Project、Screen、DesignSystem
  • パイプラインの生成物:packages/sdk/generated/domain-map.json、packages/sdk/generated/tools-manifest.json
  • インフラストラクチャ:packages/sdk/src/client.ts、packages/sdk/src/spec/errors.ts、packages/sdk/src/singleton.ts
  • テスト構成:ユニットテストは packages/sdk/test/unit/、ライブテストは packages/sdk/test/integration/ にあります
  • 利用可能なコマンド:package.json の scripts フィールドを確認してください

ファイルやディレクトリツリーについて、キャッシュされた説明に頼らないでください。ソースを読んでください。

インポート規約

ESM との互換性のため、.js 拡張子を使用します。

import { StitchError } from "../../src/spec/errors.js"; // ✓
import { StitchError } from "../../src/spec/errors"; // ✗

コメント