Hono v4.8.0で@hono/mcp
がリリースされました。これを使うと手軽にMCPサーバーを作成することができるということで、試してみました。
本記事ではDenoを用いて実行していますが、Node.jsやBun、Cloudflare Workerなどでも基本的な手順は同じです。適宜読み替えてください。
$ deno --version
deno 2.3.6 (stable, release, aarch64-apple-darwin)
v8 13.7.152.6-rusty
typescript 5.8.3
前置き
リモートMCPサーバー(Streamable HTTP)について
MCP(Model Context Protocol)は、AIが外部のシステムとやり取りするためのプロトコルです。
さて、MCPには「ローカルで実行するもの」と「サーバー上で実行し、HTTPで通信するもの」の2種類あります。
今回は「サーバー上で実行し、HTTPで通信する」=Streamable HTTP Transportと呼ばれる仕組みでMCPサーバーを実装してみましょう!
Honoを使うメリット
MCPの公式SDKのexampleでは、expressが使われています。
しかし、Honoを使うことで、Cloudflare worker や Bun 、 AWS Lambda 、 Deno Deployなど、様々な環境でMCPサーバーを動かすことが可能になります。
実装
先に依存関係のインストールを済ませておきます。
Deno以外の環境で実行する際は、npm install
やbun install
などに適宜読み替えてください。
$ deno add npm:hono npm:@hono/mcp npm:@modelcontextprotocol/sdk npm:zod
まずはMCPサーバーを実装します。
今回はとりあえず足し算を行うtoolを定義します。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
/** MCPサーバーを作成する関数 */
export function createMcpServer() {
const mcpServer = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
// MCPサーバーから呼び出すことができるツールの定義
// 足し算を行うtoolを定義する
mcpServer.registerTool("add", {
// ツール名
title: "Add Numbers",
// ツールの説明
description: "Adds two numbers together.",
// ツールの情報
annotations: {
readOnlyHint: true, // 外部の状態を変更しない
openWorldHint: false, // 外部システムと接続しない
},
// ツールの引数
inputSchema: {
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
},
// ツールの出力形式
outputSchema: {
result: z.number().describe("The sum of the two numbers"),
},
}, ({ a, b }) => {
// 足し算 a+bを計算
const structuredContent = {
result: a + b,
};
// textとstructuredContentを以下の形で返却する
return {
content: [{
type: "text",
text: JSON.stringify(structuredContent),
}],
structuredContent,
};
});
return mcpServer;
}
次にHonoでHTTPサーバーを作成し、先ほどのMCPサーバーを呼び出せるようにします。
import { StreamableHTTPTransport } from "@hono/mcp";
import { Hono } from "hono";
import { createMcpServer } from "./mcp/server.ts";
const app = new Hono();
app.get("/", (c) => {
return c.text("Hello, MCP Server is available at /mcp");
});
app.all("/mcp", async (c) => {
// mcpサーバーを作成
const mcpServer = createMcpServer();
// 通信に利用するTransportを作成
const transport = new StreamableHTTPTransport();
// mcpサーバーに接続
await mcpServer.connect(transport);
// mcpサーバーへリクエストを送り、結果を返却
return transport.handleRequest(c);
});
// `deno serve`コマンドで実行できるようエクスポート
// Deno以外の環境で起動する場合は適宜読み替えてください
// 参考: https://hono.dev/docs/getting-started/cloudflare-workers
export default app satisfies Deno.ServeDefaultExport;
実装は以上です!
次は、このツールをvscodeのCopilot Agentから呼び出してみましょう!
ローカルで実行し接続してみる
サーバーを起動します。
$ deno serve --watch --port 5503 ./src/main.ts
.vscode/mcp.json
に、MCPサーバーへの接続設定を書いておきます。
{
"servers": {
"add-two-numbers-debug": {
"type": "http",
"url": "http://localhost:5503/mcp"
}
}
}
上記設定を書いておくことで、ファイル上に起動ボタンが現れるので、「▶︎起動」を押して起動します。
起動した状態で、Copilotのチャットからmcpサーバーを呼び出してみます。
(入力欄の左下から「Agentモード」にする必要があります。)
無事MCPサーバーを呼び出すことができました!
デプロイしてリモート上のMCPサーバーに接続する
先ほど作成したサーバーを、deno deployにデプロイして公開してみましょう。
Deno Deployは「Deno Deploy Early Access」という名前で次世代版がベータリリースされています。
しかし、本記事で紹介しているのは、従来のDeno Deploy(=classic版)へデプロイする手順です。
Early Accessの方はおそらくデプロイ手順が異なるためご注意ください。
まずデプロイのため、CLIツールであるdeployctl
をインストールします。
$ deno install -A jsr:@deno/deployctl --global
次に、deployctl deploy
コマンドでデプロイします。
GitHubアカウントでの認証などが行われると思うので、手順に従ってアカウントを接続します。
$ deployctl deploy
以上でデプロイが完了です!デプロイが完了すると、最後にデプロイ先のURLが出力されるので、先程の.vscode/mcp.json
に設定を追加します。
View at:
- https://sour-ferret-80.deno.dev
- https://sour-ferret-80-mzeqhtqxnmab.deno.dev
{
"servers": {
"add-two-numbers-debug": {
"type": "http",
"url": "http://localhost:5503/mcp"
},
+ "add-two-numbers": {
+ "type": "http",
+ "url": "https://sour-ferret-80.deno.dev/mcp"
+ }
}
}
以上で接続設定も完了です!
vscodeからリモートMCPに接続できるようになっているか確認しましょう。
無事接続できましたね!
まとめ
-
@hono/mcp
を使ってMCPサーバーを作成しました。-
@hono/mcp
を使うと、MCPサーバーをBun、Cloudflare Workers、Denoなど、様々な場所で動かせます。
-
- MCPサーバーをdeno deployへデプロイし、手元のGitHub Copilotから接続して動作確認することができました。
筆者はHonoで故事成語を返すmcpサーバーを作ってみました。手軽に公開して手軽にAIを拡張できるのがいい体験でした!