mcpField
C
chatgpt-app-builder

chatgpt-app-builder

github.com/mcp-use開発2277 回インストール39 週間前に更新
リポジトリ

chatgpt-app-builder について

mcp-use と OpenAI Apps SDK を使い、インタラクティブな React ウィジェットを備えた ChatGPT アプリを開発するスキルです。ウィジェットを自動登録し、MCP Apps と ChatGPT の両プロトコルに対応します。

主な機能

  1. 01テンプレートからアプリを作成
  2. 02React ウィジェットの自動登録
  3. 03useWidget による状態管理とツール呼び出し
  4. 04自動バンドルとホットリロード
  5. 05CSP 設定と Inspector によるテスト
  6. 06MCP Apps と ChatGPT に対応

活用シーン

  1. 01インタラクティブな ChatGPT アプリの作成
  2. 02MCP ツールを呼び出すウィジェットの構築
  3. 03Inspector でのウィジェットテスト
  4. 04MCP Apps クライアントへの対応

MCP 対応

mcp-use を使った MCP サーバーの構築方法を案内し、ウィジェットを MCP ツールとリソースとして登録して MCP Apps クライアントに公開します。ChatGPT Apps SDK プロトコルにも対応します。

インストール

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

$npx skills add https://github.com/mcp-use/skills --skill chatgpt-app-builder

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

同梱ファイルLICENSE.txt

詳細

ChatGPT App Builder

mcp-use フレームワークと OpenAI Apps SDK を使用して、インタラクティブウィジェットを備えた本番環境向けの ChatGPT アプリを構築できます。このスキルでは、自動登録と React フックを標準で備えた、設定不要のウィジェット開発を実現します。

クイックスタート

必ず MCP Apps テンプレートでブートストラップしてください:

npx create-mcp-use-app my-chatgpt-app --template mcp-apps
cd my-chatgpt-app
yarn install
yarn dev

これにより、次のプロジェクト構成が作成されます:

my-chatgpt-app/
├── resources/              # React widgets (auto-registered!)
│   ├── display-weather.tsx # Example widget
│   └── product-card.tsx    # Another widget
├── public/                 # Static assets
│   └── images/
├── index.ts               # MCP server entry
├── package.json
├── tsconfig.json
└── README.md

ChatGPT Apps に mcp-use を使う理由

従来の OpenAI Apps SDK では、かなりの手動設定が必要です:

  • プロジェクト構成の分離(server/ と web/ フォルダー)
  • esbuild/webpack の手動設定
  • カスタムの useWidgetState フックの実装
  • React のマウントコードの手動作成
  • CSP の手動設定
  • ウィジェットの手動登録

mcp-use なら、すべてを簡素化できます:

  • ✅ コマンド 1 つでセットアップ
  • ✅ resources/ フォルダーにウィジェットを配置するだけで自動登録
  • ✅ state、props、ツール呼び出しに対応した useWidget() フックを標準搭載
  • ✅ ホットリロード対応の自動バンドル
  • ✅ CSP の自動設定
  • ✅ テスト用の Inspector を標準搭載
  • ✅ 2 つのプロトコルに対応(ChatGPT と MCP Apps クライアントの両方で動作)

MCP Apps と ChatGPT Apps SDK の比較

mcp-use は複数のウィジェットプロトコルに対応しており、最大限の互換性を実現します:

プロトコル用途互換性ステータス
MCP Apps(type: "mcpApps")最大限の互換性✅ ChatGPT + MCP Apps クライアント推奨
ChatGPT Apps SDK(type: "appsSdk")ChatGPT 専用機能✅ ChatGPT のみサポート対象
MCP-UIシンプルな静的コンテンツ✅ MCP クライアントのみ特定用途向け
MCP Apps が選ばれる理由

MCP Apps は、Model Context Protocol におけるインタラクティブウィジェットの公式標準(SEP-1865)です:

  • 汎用性:ChatGPT、Claude Desktop、Goose、およびすべての MCP Apps クライアントで動作します
  • 将来性:オープンな仕様に基づいており、長期的な互換性を確保します
  • 安全性:きめ細かな CSP 制御を備えた二重 iframe サンドボックスを採用しています
  • 設定不要:type: "mcpApps" を指定すると、mcp-use が両方のプロトコル向けのメタデータを自動生成します

重要なポイント:サーバー設定で type: "mcpApps" を使用すると、ウィジェットは ChatGPT(Apps SDK プロトコル)と MCP Apps クライアントの両方で自動的に動作します。ウィジェットを一度作成すれば、プロトコルの変換は mcp-use が処理します。

ウィジェットの作成

シンプルなウィジェット(単一ファイル)

resources/weather-display.tsx を作成します:

import { McpUseProvider, useWidget, type WidgetMetadata } from "mcp-use/react";
import { z } from "zod";

// Define widget metadata
export const widgetMetadata: WidgetMetadata = {
  description: "Display current weather for a city",
  props: z.object({
    city: z.string().describe("City name"),
    temperature: z.number().describe("Temperature in Celsius"),
    conditions: z.string().describe("Weather conditions"),
    humidity: z.number().describe("Humidity percentage"),
  }),
};

const WeatherDisplay: React.FC = () => {
  const { props, isPending } = useWidget();

  // Always handle loading state first
  if (isPending) {
    return (
      <McpUseProvider autoSize>
        <div className="animate-pulse p-4">Loading weather...</div>
      </McpUseProvider>
    );
  }

  return (
    <McpUseProvider autoSize>
      <div className="weather-card p-4 rounded-lg shadow">
        <h2 className="text-2xl font-bold">{props.city}</h2>
        <div className="temp text-4xl">{props.temperature}°C</div>
        <p className="conditions">{props.conditions}</p>
        <p className="humidity">Humidity: {props.humidity}%</p>
      </div>
    </McpUseProvider>
  );
};

export default WeatherDisplay;

これで完了です!ウィジェットは自動的に次のように処理されます:

  • MCP ツール weather-display として登録
  • MCP リソース ui://widget/weather-display.html として登録
  • Apps SDK との互換性を考慮してバンドル
  • ChatGPT ですぐに使用可能
複雑なウィジェット(フォルダー構成)

複数のコンポーネントを含むウィジェットの場合:

resources/
└── product-search/
    ├── widget.tsx          # Entry point (required name)
    ├── components/
    │   ├── ProductCard.tsx
    │   └── FilterBar.tsx
    ├── hooks/
    │   └── useFilter.ts
    ├── types.ts
    └── constants.ts

エントリーポイント(widget.tsx):

import { McpUseProvider, useWidget, type WidgetMetadata } from "mcp-use/react";
import { z } from "zod";
import { ProductCard } from "./components/ProductCard";
import { FilterBar } from "./components/FilterBar";

export const widgetMetadata: WidgetMetadata = {
  description: "Display product search results with filtering",
  props: z.object({
    products: z.array(
      z.object({
        id: z.string(),
        name: z.string(),
        price: z.number(),
        image: z.string(),
      })
    ),
    query: z.string(),
  }),
};

const ProductSearch: React.FC = () => {
  const { props, isPending, state, setState } = useWidget();

  if (isPending) {
    return (
      <McpUseProvider autoSize>
        <div>Loading...</div>
      </McpUseProvider>
    );
  }

  return (
    <McpUseProvider autoSize>
      <div>
        <h1>Search: {props.query}</h1>
        <FilterBar onFilter={(filters) => setState({ filters })} />
        <div className="grid grid-cols-3 gap-4">
          {props.products.map((p) => (
            <ProductCard key={p.id} product={p} />
          ))}
        </div>
      </div>
    </McpUseProvider>
  );
};

export default ProductSearch;

ウィジェットのメタデータ

自動登録に必要なメタデータ:

export const widgetMetadata: WidgetMetadata = {
  // Required: Human-readable description
  description: "Display weather information",

  // Required: Zod schema for widget props
  props: z.object({
    city: z.string().describe("City name"),
    temperature: z.number(),
  }),

  // Optional: Disable automatic tool registration
  exposeAsTool: true, // default

  // Optional: Unified metadata (works for BOTH ChatGPT and MCP Apps)
  metadata: {
    csp: {
      connectDomains: ["https://api.weather.com"],
      resourceDomains: ["https://cdn.weather.com"],
    },
    prefersBorder: true,
    autoResize: true,
    widgetDescription: "Interactive weather display",
  },
};

重要:

  • description:ツールとリソースの説明に使用されます
  • props:Zod スキーマでウィジェットの入力パラメーターを定義します
  • exposeAsTool:カスタムツール経由でのみウィジェットを使用する場合は、false に設定します
  • metadata:両方のプロトコルで機能する統一設定です(推奨)

コンテンツセキュリティポリシー(CSP)

CSP 設定を使用して、ウィジェットがアクセスできる外部リソースを制御します:

export const widgetMetadata: WidgetMetadata = {
  description: "Weather widget",
  props: z.object({ city: z.string() }),
  metadata: {
    csp: {
      // APIs your widget needs to call
      connectDomains: ["https://api.weather.com", "https://weather-backup.com"],

      // Static assets (images, fonts, stylesheets)
      resourceDomains: ["https://cdn.weather.com"],

      // External content to embed in iframes
      frameDomains: ["https://embed.weather.com"],

      // Script CSP directives (use carefully!)
      scriptDirectives: ["'unsafe-inline'"],
    },
  },
};

CSP フィールドのリファレンス:

  • connectDomains:fetch、WebSocket、XMLHttpRequest 経由で呼び出す API
  • resourceDomains:読み込む画像、フォント、スタイルシート、動画
  • frameDomains:iframe に埋め込む外部コンテンツ
  • scriptDirectives:script-src CSP ディレクティブ(本番環境では 'unsafe-eval' を避けてください)

セキュリティのベストプラクティス:

  • ✅ 正確なドメインを指定します:https://api.weather.com
  • ❌ ワイルドカードは避けます:https://*.weather.com(安全性が低くなります)
  • ❌ 絶対に必要な場合を除き、'unsafe-eval' は使用しないでください
  • ✅ デプロイ前に開発環境で CSP をテストしてください

メタデータ設定オプション

モダンな統合アプローチ(推奨)

metadata フィールドを使用して、2 つのプロトコルをサポートします。

export const widgetMetadata: WidgetMetadata = {
  description: "Weather widget",
  props: propSchema,
  metadata: {
    // Works for BOTH MCP Apps AND ChatGPT
    csp: {
      connectDomains: ["https://api.weather.com"],
      resourceDomains: ["https://cdn.weather.com"],
    },
    prefersBorder: true,
    autoResize: true,
    widgetDescription: "Displays current weather",
  },
};
レガシー Apps SDK アプローチ(非推奨)

古い ChatGPT 専用フォーマットです(引き続きサポートされていますが、推奨されません)。

export const widgetMetadata: WidgetMetadata = {
  description: "Weather widget",
  props: propSchema,
  appsSdkMetadata: {
    // ChatGPT only - snake_case with openai/ prefix
    "openai/widgetCSP": {
      connect_domains: ["https://api.weather.com"],
      resource_domains: ["https://cdn.weather.com"],
    },
    "openai/widgetPrefersBorder": true,
    "openai/toolInvocation/invoking": "Loading...",
    "openai/toolInvocation/invoked": "Loaded",
  },
};

移行に関する注意:古いフォーマットでは、openai/ プレフィックスとスネークケース(例:connect_domains)を使用する appsSdkMetadata を使います。新しいフォーマットでは、キャメルケース(例:connectDomains)を使用する metadata を使い、どちらのプロトコルにも対応します。

カスタム ChatGPT 機能で両方を使用する

両方のフィールドを組み合わせて、標準のメタデータと ChatGPT 固有のオーバーライドを使用できます。

export const widgetMetadata: WidgetMetadata = {
  description: "Weather widget",
  props: propSchema,
  // Unified metadata (dual-protocol)
  metadata: {
    csp: { connectDomains: ["https://api.weather.com"] },
    prefersBorder: true,
  },
  // ChatGPT-specific overrides/additions
  appsSdkMetadata: {
    "openai/widgetDescription": "ChatGPT-specific description",
    "openai/customFeature": "some-value", // Any custom OpenAI metadata
    "openai/locale": "en-US",
  },
};

ユースケース:統合フォーマットに存在しないカスタムの OpenAI 固有メタデータを渡す必要がある場合は、appsSdkMetadata に追加します。フィールドは openai/ プレフィックス付きで ChatGPT に直接渡されます。

useWidget フック

useWidget フックでは、必要な機能をすべて利用できます。

const {
  // Widget props from tool input
  props,

  // Loading state (true = tool still executing)
  isPending,

  // Persistent widget state
  state,
  setState,

  // Theme from host (light/dark)
  theme,

  // Call other MCP tools
  callTool,

  // Display mode control
  displayMode,
  requestDisplayMode,

  // Additional tool output
  output,
} = useWidget<MyPropsType, MyOutputType>();
Props と読み込み状態

重要: ツールの実行が完了する前にウィジェットがレンダリングされます。必ず isPending を処理してください。

const { props, isPending } = useWidget<WeatherProps>();

// Pattern 1: Early return
if (isPending) {
  return <div>Loading...</div>;
}
// Now props are safe to use

// Pattern 2: Conditional rendering
return <div>{isPending ? <LoadingSpinner /> : <div>{props.city}</div>}</div>;

// Pattern 3: Optional chaining (partial UI)
return (
  <div>
    <h1>{props.city ?? "Loading..."}</h1>
  </div>
);
ウィジェットの状態

ウィジェットの操作間でデータを保持します。

const { state, setState } = useWidget();

// Save state (persists in ChatGPT localStorage)
const addFavorite = async (city: string) => {
  await setState({
    favorites: [...(state?.favorites || []), city],
  });
};

// Update with function
await setState((prev) => ({
  ...prev,
  count: (prev?.count || 0) + 1,
}));
MCP ツールの呼び出し

ウィジェットからほかのツールを呼び出せます。

const { callTool } = useWidget();

const refreshData = async () => {
  try {
    const result = await callTool("get-weather", {
      city: "Tokyo",
    });
    console.log("Result:", result.content);
  } catch (error) {
    console.error("Tool call failed:", error);
  }
};
表示モードの制御

異なる表示モードをリクエストします。

const { displayMode, requestDisplayMode } = useWidget();

const goFullscreen = async () => {
  await requestDisplayMode("fullscreen");
};

// Current mode: 'inline' | 'pip' | 'fullscreen'
console.log(displayMode);

ウィジェット付きカスタムツール

2 つのプロトコルをサポートする、ウィジェットを返すツールを作成します。

import { MCPServer, widget, text } from "mcp-use/server";
import { z } from "zod";

const server = new MCPServer({
  name: "weather-app",
  version: "1.0.0",
});

server.tool(
  {
    name: "get-weather",
    description: "Get current weather for a city",
    schema: z.object({
      city: z.string().describe("City name"),
    }),
    // Widget config (registration-time metadata)
    widget: {
      name: "weather-display", // Must match widget in resources/
      invoking: "Fetching weather...",
      invoked: "Weather data loaded",
    },
  },
  async ({ city }) => {
    // Fetch data from API
    const data = await fetchWeatherAPI(city);

    // Return widget with runtime data
    return widget({
      props: {
        city,
        temperature: data.temp,
        conditions: data.conditions,
        humidity: data.humidity,
      },
      output: text(`Weather in ${city}: ${data.temp}°C`),
      message: `Current weather for ${city}`,
    });
  }
);

server.listen();

ポイント:

  • サーバー設定の baseUrl により、アセットを適切に読み込めます
  • ウィジェットは ChatGPT と MCP Apps クライアントの両方で自動的に動作します
  • ツール定義に widget: { name, invoking, invoked } を指定します
  • widget({ props, output }) ヘルパーは実行時データを返します
  • props はウィジェットに渡され、output はモデルに表示されます
  • ウィジェットは resources/ フォルダー内に配置する必要があります

静的アセット

画像やフォントなどには public/ フォルダーを使用します。

my-app/
├── resources/
├── public/              # Static assets
│   ├── images/
│   │   ├── logo.svg
│   │   └── banner.png
│   └── fonts/
└── index.ts

ウィジェットでのアセットの使用:

import { Image } from "mcp-use/react";

function MyWidget() {
  return (
    <div>
      {/* Paths relative to public/ folder */}
      <Image src="/images/logo.svg" alt="Logo" />
      <img src={window.__getFile?.("images/banner.png")} alt="Banner" />
    </div>
  );
}

コンポーネント

McpUseProvider

一般的なセットアップを統合したプロバイダーです。

import { McpUseProvider } from "mcp-use/react";

function MyWidget() {
  return (
    <McpUseProvider
      autoSize // Auto-resize widget
      viewControls // Add debug/fullscreen buttons
      debug // Show debug info
    >
      <div>Widget content</div>
    </McpUseProvider>
  );
}
Image コンポーネント

データ URL と公開パスの両方を処理します。

import { Image } from "mcp-use/react";

function MyWidget() {
  return (
    <div>
      <Image src="/images/photo.jpg" alt="Photo" />
      <Image src="data:image/png;base64,..." alt="Data URL" />
    </div>
  );
}
ErrorBoundary

エラーを適切に処理します。

import { ErrorBoundary } from "mcp-use/react";

function MyWidget() {
  return (
    <ErrorBoundary
      fallback={<div>Something went wrong</div>}
      onError={(error) => console.error(error)}
    >
      <MyComponent />
    </ErrorBoundary>
  );
}

テスト

Inspector の使用
  1. 開発サーバーを起動します。

    yarn dev
    
  2. Inspector を開きます。

    • http://localhost:3000/inspector に移動します
  3. ウィジェットをテストします。

    • Tools タブをクリックします
    • ウィジェット用のツールを探します
    • テスト用パラメーターを入力します
    • 実行してウィジェットのレンダリングを確認します
  4. インタラクションをデバッグします。

    • ブラウザーのコンソールを使用します
    • RPC ログを確認します
    • 状態の保持をテストします
    • ツール呼び出しを確認します
ChatGPT でのテスト
  1. 開発者モードを有効にします。

    • Settings → Connectors → Advanced → Developer mode
  2. サーバーを追加します。

    • Connectors タブに移動します
    • リモート MCP サーバーの URL を追加します
  3. 会話でテストします。

    • Plus メニューから Developer Mode を選択します
    • コネクターを選択します
    • ChatGPT にツールを使うよう依頼します

プロンプトのヒント:

  • 明確に指定します:「weather-app コネクターの get-weather ツールを使用してください……」
  • 別の手段を使わないよう指定します:「組み込みツールは使用せず、自分のコネクターだけを使用してください」
  • 入力を指定します:「{ city: 'Tokyo' } を指定して get-weather を呼び出してください」

2 つのプロトコルに関する注意:サーバー設定で type: "mcpApps" を使用すると、ウィジェットは ChatGPT(Apps SDK 経由)と MCP Apps クライアント(Claude Desktop、Goose など)の両方で自動的に動作します。コードを変更せずに、同じウィジェットを複数のクライアントでテストできます。

ベストプラクティス

スキーマ設計

分かりやすいスキーマを使用します。

// ✅ Good
const schema = z.object({
  city: z.string().describe("City name (e.g., Tokyo, Paris)"),
  temperature: z.number().min(-50).max(60).describe("Temp in Celsius"),
});

// ❌ Bad
const schema = z.object({
  city: z.string(),
  temp: z.number(),
});
テーマのサポート

常に両方のテーマをサポートします。

const { theme } = useWidget();

const bgColor = theme === "dark" ? "bg-gray-900" : "bg-white";
const textColor = theme === "dark" ? "text-white" : "text-gray-900";
読み込み状態

最初に必ず isPending を確認します。

const { props, isPending } = useWidget<MyProps>();

if (isPending) {
  return <LoadingSpinner />;
}

// Now safe to access props.field
return <div>{props.field}</div>;
ウィジェットの焦点

ウィジェットの焦点を保ちます。

// ✅ Good: Single purpose
export const widgetMetadata: WidgetMetadata = {
  description: "Display weather for a city",
  props: z.object({ city: z.string() }),
};

// ❌ Bad: Too many responsibilities
export const widgetMetadata: WidgetMetadata = {
  description: "Weather, forecast, map, news, and more",
  props: z.object({
    /* many fields */
  }),
};
エラー処理

エラーを適切に処理します。

const { callTool } = useWidget();

const fetchData = async () => {
  try {
    const result = await callTool("fetch-data", { id: "123" });
    if (result.isError) {
      console.error("Tool returned error");
    }
  } catch (error) {
    console.error("Tool call failed:", error);
  }
};

設定

本番環境のセットアップ

本番環境用のベース URL を設定します。

const server = new MCPServer({
  name: "my-app",
  version: "1.0.0",
  baseUrl: process.env.MCP_URL || "https://myserver.com",
});
環境変数
# Server URL
MCP_URL=https://myserver.com

# For static deployments
MCP_SERVER_URL=https://myserver.com/api
CSP_URLS=https://cdn.example.com,https://api.example.com

変数の用途:

  • MCP_URL:ウィジェットのアセットと CSP のベース URL
  • MCP_SERVER_URL:ツール呼び出しに使用する MCP サーバーの URL(静的デプロイの場合)
  • CSP_URLS:コンテンツセキュリティポリシーに追加するドメイン

デプロイ

mcp-use Cloud へのデプロイ
# Login
npx mcp-use login

# Deploy
yarn deploy
本番環境向けビルド
# Build
yarn build

# Start
yarn start

ビルドプロセス:

  • TypeScript をコンパイルします
  • React ウィジェットをバンドルします
  • アセットを最適化します
  • 本番環境用の HTML を生成します

よく使われるパターン

データ取得ウィジェット
const DataWidget: React.FC = () => {
  const { props, isPending, callTool } = useWidget();

  if (isPending) {
    return <div>Loading...</div>;
  }

  const refresh = async () => {
    await callTool("fetch-data", { id: props.id });
  };

  return (
    <div>
      <h1>{props.title}</h1>
      <button onClick={refresh}>Refresh</button>
    </div>
  );
};
状態を持つウィジェット
const CounterWidget: React.FC = () => {
  const { state, setState } = useWidget();

  const increment = async () => {
    await setState({
      count: (state?.count || 0) + 1,
    });
  };

  return (
    <div>
      <p>Count: {state?.count || 0}</p>
      <button onClick={increment}>+1</button>
    </div>
  );
};
テーマ対応ウィジェット
const ThemedWidget: React.FC = () => {
  const { theme } = useWidget();

  return (
    <div className={theme === "dark" ? "dark-theme" : "light-theme"}>
      Content
    </div>
  );
};

トラブルシューティング

ウィジェットが表示されない

問題: ウィジェットファイルは存在するのに、ツールが表示されません

解決策:

  • .tsx 拡張子であることを確認します
  • widgetMetadata オブジェクトをエクスポートします
  • React コンポーネントをデフォルトエクスポートします
  • サーバーログでエラーを確認します
  • ウィジェット名がファイル名/フォルダー名と一致していることを確認します
Props が受け取れない

問題: コンポーネントが空の props を受け取ります

解決策:

  • まず isPending を確認します(保留中は props が空です)
  • useWidget() フックを使用します(React props ではありません)
  • widgetMetadata.props が有効な Zod スキーマであることを確認します
  • ツールのパラメーターがスキーマと一致していることを確認します
CSP エラー

問題: ウィジェットは読み込まれるものの、アセットの読み込みに失敗します

解決策:

  • サーバー設定で baseUrl を設定します
  • metadata.csp(新方式)または appsSdkMetadata['openai/widgetCSP'](旧方式)を使って、ドメインを CSP に追加します
  • すべてのリソースで HTTPS を使用します
  • ブラウザーのコンソールで CSP 違反を確認します
本番環境での CSP エラー

問題: 本番環境でコンテンツセキュリティポリシーによってリソースがブロックされます

解決策:

  1. CSP 違反メッセージがないか、ブラウザーのコンソールを確認します
  2. CSP 設定に不足しているドメインを追加します:
    metadata: {
      csp: {
        connectDomains: ['https://api.example.com'], // Add missing API domain
        resourceDomains: ['https://cdn.example.com'], // Add missing CDN domain
      }
    }
    
  3. 正確なドメインを使用します。本番環境ではワイルドカードを避けてください
  4. デプロイ前にInspector でテストして、CSP の問題を早期に検出します
  5. 環境変数を使う方法:カンマ区切りのドメインを指定して、環境変数 CSP_URLS を設定します
プロトコルの互換性に関する問題

問題: ウィジェットが ChatGPT では動作するものの MCP Apps クライアントでは動作しません(またはその逆)

解決策:

  • デュアルプロトコルに対応するには type: "mcpApps" を使用します(推奨)
  • サーバー設定で baseUrl が正しく設定されていることを確認します
  • メタデータの形式を確認します。デュアルプロトコルでは appsSdkMetadata(snake_case)ではなく metadata(camelCase)を使用します
  • 両方のプロトコルに対応する Inspector でテストします

各タイプを使う場面:

  • type: "mcpApps" - 最大限の互換性(推奨)
  • type: "appsSdk" - ChatGPT のみ(仕様にない ChatGPT 固有の機能が必要な場合に使用)

詳細情報

クイックリファレンス

コマンド:

  • npx create-mcp-use-app my-app --template mcp-apps - プロジェクトを作成
  • yarn dev - ホットリロードを有効にして開発
  • yarn build - 本番環境向けにビルド
  • yarn start - 本番サーバーを起動
  • yarn deploy - mcp-use Cloud にデプロイ

ウィジェットの構成:

  • resources/widget-name.tsx - 単一ファイルのウィジェット
  • resources/widget-name/widget.tsx - フォルダー形式のウィジェットエントリーポイント
  • public/ - 静的アセット

ウィジェットのメタデータ:

  • description - ウィジェットの説明
  • props - 入力用の Zod スキーマ
  • exposeAsTool - ツールとして自動登録(デフォルト:true)
  • metadata - 統合設定(デュアルプロトコル、推奨)
  • metadata.csp - コンテンツセキュリティポリシーの設定
  • appsSdkMetadata - ChatGPT 固有のオーバーライド(任意)

CSP フィールド:

  • connectDomains - 呼び出す API
  • resourceDomains - 読み込む静的アセット
  • frameDomains - 埋め込む iframe
  • scriptDirectives - スクリプトポリシー

useWidget フック:

  • props - ウィジェットの入力パラメーター
  • isPending - 読み込み状態フラグ
  • state, setState - 永続状態
  • callTool - 他のツールを呼び出す
  • theme - 現在のテーマ(ライト/ダーク)
  • displayMode, requestDisplayMode - 表示を制御する

コメント