モデル呼び出しプロトコル(MCP)は、AIアシスタントが外部ツールと相互作用する方法を大幅に改善し、より強力で多様なアプリケーションを可能にしました。しかし、標準のMCP実装内で重要な制限があります:ツール呼び出しは本質的に「ブラックボックス」の操作であり、インテグレーションのための組み込まれたユーザーインターフェイスはありません。 この記事では、私たちが開発した革新的なアプローチを探索します。 この制限を克服するには、21st.dev 統合で UI コンポーネントの生成に焦点を当てた、MCP 通信のためのブラウザベースのインターフェイスを作成します。 第21回マジックMCP 問題:MCPにおける制限されたユーザーインタラクション モデル呼び出しプロトコルは、AIアシスタントが外部ツールを呼び出し、専門的なタスクを実行することを可能にします。 この制限は、UI コンポーネントを生成する際に特に問題があります。AI が UI コンポーネントを提案するとき、ユーザーはしばしば: See various design options Compare different implementations Customize details before integration Make informed choices based on visual representation 標準的なMCPアプローチは、この種のインタラクティブフィードバックループのための組み込みメカニズムを提供しません。 ソリューション:ブラウザベースのMCP通信 この制限に対処するために、ブラウザインターフェイスを介してMCPとの通信を可能にするシステムを開発しました。 バンドルをホストし、ウェブブラウザを開くことができるローカルMCPを作成します。 NPM で MCP に隣接するローカルバンドルを提供する ユーザーインターフェイスにリダイレクトするブラウザを自動的に開く ユーザーが相互作用し、利用可能なオプションから選択できるようにします。 サーバを閉じ、ユーザの選択で実行を再開します。 結果は、MCPのパワーを維持し、ユーザーが必要とするビジュアルフィードバックとインタラクション機能を追加するシームレスな統合です。 技術実施 これがどのように実施されているのか見ていきましょう。 Callbackサーバー 当社のソリューションの核心は、MCPとブラウザインターフェイス間の通信を容易にするコールバックサーバーです。 export class CallbackServer { private server: Server | null = null; private port: number; private sessionId = Math.random().toString(36).substring(7); // ... other properties async promptUser( config: CallbackServerConfig = {} ): Promise<CallbackResponse> { const { initialData = null, timeout = 300000 } = config; this.config = config; try { const availablePort = await this.findAvailablePort(); this.server = createServer(this.handleRequest); this.server.listen(availablePort, "127.0.0.1"); // Set up promise to handle user selection return new Promise<CallbackResponse>((resolve, reject) => { this.promiseResolve = resolve; this.promiseReject = reject; // ... server setup code // Open browser with unique session ID const url = `http://127.0.0.1:${availablePort}?id=${this.sessionId}`; open(url).catch((error) => { console.warn("Failed to open browser:", error); resolve({ data: { browserOpenFailed: true } }); this.shutdown(); }); }); } catch (error) { await this.shutdown(); throw error; } } } このサーバー: ダイナミックで利用可能なポートを見つける リクエストごとにユニークなセッション ID を作成します。 UI バンドルを提供 ブラウザを開いてオプションを表示する コールバックを通じてユーザーの選択を受け取る 選択したデータで約束を解決する Integration with MCP tool このアプローチを適用して、21st_magic_component_builder ツールを強化し、UI コンポーネントを生成しました。 export class CreateUiTool extends BaseTool { name = UI_TOOL_NAME; description = UI_TOOL_DESCRIPTION; // ... schema definition async execute({ message, searchQuery, absolutePathToCurrentFile, context, }: z.infer<typeof this.schema>): Promise<{ content: Array<{ type: "text"; text: string }>; }> { try { // Fetch UI component variations from API const response = await twentyFirstClient.post<{ data1: { text: string }; data2: { text: string }; data3: { text: string }; }>("/api/create-ui-variation", { message, searchQuery, fileContent: await getContentOfFile(absolutePathToCurrentFile), context, }); // Handle billing or error cases if (response.status !== 200) { open("https://21st.dev/settings/billing"); return { content: [ { type: "text" as const, text: response.data.text as string, }, ], }; } // Create server and prompt user through browser const server = new CallbackServer(); const { data } = await server.promptUser({ initialData: { data1: response.data.data1, data2: response.data.data2, data3: response.data.data3, }, }); // Process user selection and return formatted response const componentData = data || { text: "No component data received. Please try again.", }; // Return formatted response to user // ... } catch (error) { console.error("Error executing tool", error); throw error; } } } ユーザー体験 Flow 以下は、UI コンポーネントをリクエストするときにユーザー エクスペリエンスが流れる方法です。 Tool Invocation: AI アシスタントは、ユーザーが新しいUIコンポーネントをリクエストするときに21st_magic_component_builder ツールを呼び出します。 API リクエスト:ツールは 21st.dev API にリクエストを送信し、ユーザーのメッセージと文脈に基づいて複数の UI コンポーネント変異を生成します。 Browser Launch: ローカルサーバーが起動し、ブラウザウィンドウが自動的に開き、生成されたUIコンポーネントのオプションが表示されます。 ユーザインタラクション:ユーザは、ご希望のコンポーネントの変数を表示、相互作用し、選択することができます。 Selection Capture: ユーザーが選択をするとき、ブラウザはその選択をコールバックサーバーに送信します。 Execution Resumption: サーバが閉鎖され、選択したコンポーネントデータで実行が再開されます。 統合ガイダンス: AI アシスタントは選択したコンポーネントを受け取り、ユーザーのコードベースに統合するためのガイダンスを提供します。 このアプローチにより、ユーザーはUI コンポーネントに関する明確な決定を下し、MCP ワークフロー全体を維持することができます。 セキュリティとプライバシーの考慮事項 当社の実施には、いくつかのセキュリティ対策が必要です: ローカルホスティング:すべてのコミュニケーションはユーザーのマシン上でローカルで行われます(127.0.0.1) ユニークなセッションID:各ブラウザセッションには、クロスセッション干渉を防ぐためのユニークなIDがあります。 タイムアウトメカニズム: 設定可能な期間後にセッションが自動的に終了する(デフォルト 5 分) ポートセキュリティ: サーバーは衝突を避けるために動的に利用可能なポートを見つける 結論 MCP コミュニケーションへのブラウザベースのアプローチは、視覚的な相互作用から恩恵を受けるツールで作業する際のユーザー体験を大幅に改善します。MCP の強力な機能と Web インターフェイスのインタラクティブな性質の間のギャップを縮めることで、ユーザーにとってより直感的なワークフローを作成しました。このアプローチは、UI コンポーネントの生成に特に有益であり、視覚的な表示が知的意思決定に不可欠です。 ソースコードはこちらで入手可能 . GitHub