2026年4月15日水曜日

MCP Appsのサンプルアプリbasic-serverのPreact,React,Solid,Svelte,Vue版をデータベースで実行する

先日の記事「MCP Appsのサンプルアプリbasic-server-vanillajsをデータベースで実行する」では、VanillaJS(UIフレームワークを使用しない)で作成したMCPアプリをデータベースでホストしました。

GitHubのリポジトリmodelcontextprotocol/ext-appsには、VanillaJS以外にUIフレームワークとしてPreact、React、Solid、Svelte、Vueを使ったMCPアプリのサンプルが含まれています。これらのアプリケーションはすべてツールget-timeを呼び出しています。また、UI自体の見かけはVanillaJSのMCPアプリと同じになっています。

これらのMCPアプリをデータベースでホストしてみます。データベースでのリモートMCPサーバーの実装はresources/read呼び出しを受けて、データベースに保存しているバンドル化されたMCPアプリのソース(HTML+JavaScript+CSS)をクライアントに戻すだけです。そのため、ツールの実装さえ同じであればMCPアプリは一切変更なしで動作するはずです。

結果ですが、modelcontextprotocol/ext-appsにあるbasic-server-preact、basic-server-react、basic-server-solid、basic-server-svelte、basic-server-vueのすべてのMCPアプリが変更せずに動作しています。

作業自体は記事「MCP Appsのサンプルアプリbasic-server-vanillajsをデータベースで実行する」と同じ手順で、作成したリソースにそれぞれのMCPアプリのバンドルを登録します。MCPアプリのUIバンドルはext-apps/examples/basic-server-xxxx/dist/mcp-app.htmlとして作成されています。


Preact、React、Solid、Svelte、Vueの5つのMCPサーバーを登録しますが、ひとつひとつ手作業で登録するのはつらいので、以下のスクリプトを書きました。


APEXのSQLコマンドから上記のスクリプトを実行すると、ファンクションget_timeを呼び出すツールとしてget-time-preact、get-time-react、get-time-solid、get-time-svelte、get-time-vueが作成されます。また同名のリソースが作成され、ツールに紐づけられます。


以上でツールとリソースは作成されます。この後に、リソースにそれぞれのUIバンドルmcp-app.htmlを登録します。

登録後にMCP Inspectorを使って動作を確認します。

npx -y @modelcontextprotocol/inspector

MCPサーバーext-appsに接続し、MCP Appsを一覧します。全部で6つのアプリが選択できます。


アプリの作成に使用しているUIフレームワークが異なるだけで、MCPアプリ自体はどれでも同じ見かけと動作をします。


ただし、VanillaJSではServer Timeは以下のように表示されます。


他のアプリは以下のように表示されます。


コードを確認すると、VanillaJSでの時刻の取り出しは以下のファンクションで行われていました。構造化出力を優先して参照しています。
function extractTime(result: CallToolResult): string {
  const { time } = (result.structuredContent as { time?: string }) ?? {};
  return time ?? "[ERROR]";
}
Preactを確認すると以下でした。構造化出力を参照していません。
function extractTime(callToolResult: CallToolResult): string {
  const { text } = callToolResult.content?.find((c) => c.type === "text")!;
  return text;
}
現在時刻の表示の違いは、ファンクションget_timeのレスポンスの取得方法が異なることが原因でした。

この他Reactについては、Received a response for an unknown message IDというエラーが発生しています。Reactのみで発生していることと、エラーメッセージにあるmessage IDはMCPアプリとホストの間でやり取りするメッセージに割り振られているIDで、ホストとデータベースで実行されるMCPサーバー(ツール)の間のメッセージに割り振られているIDではありません。よって、これはMCPアプリ側の問題だと思われます。

以上でデータベースに実装したリモートMCPサーバーで、各種UIフレームワークで作成したMCPアプリをホストできることが確認できました。

今回の記事は以上になります。