mcp-examples
Enables retrieving user and post data through MCP tools, with Zod-based request validation and OpenAPI/Swagger UI support.
README
MCP Examples
Cloudflare WorkersとHonoで、REST APIとModel Context Protocol(MCP)のツールを実装するサンプルです。ユーザー・投稿データの取得、Zodによる入力検証、OpenAPI仕様とSwagger UIの生成を含みます。
セットアップ
依存関係をインストールし、開発サーバーを起動します。
pnpm install
pnpm run dev
開発サーバーの起動後、次のURLを利用できます。
| URL | 用途 |
|---|---|
/api/users |
ユーザーAPI |
/api/posts |
投稿API |
/api/openapi |
OpenAPI JSON |
/api/docs |
Swagger UI |
/mcp |
MCPエンドポイント |
本番用ビルドとCloudflare Workersへのデプロイには、次のコマンドを使用します。
pnpm run build
pnpm run deploy
Wranglerの設定からCloudflareBindings型を生成する場合は、次のコマンドを実行します。
pnpm run cf-typegen
生成した型は、HonoインスタンスのBindingsに指定します。
const app = new Hono<{ Bindings: CloudflareBindings }>();
リクエスト検証とOpenAPI
このプロジェクトはhono-openapi@1.3.1とZod 4を使用します。src/features/users/routes.tsでは、hono-openapiのvalidatorがリクエストを検証すると同時に、query・path parameterのスキーマをOpenAPI仕様へ反映します。
zValidatorからvalidatorへ移行する
@hono/zod-validatorのzValidatorを使用しているルートは、importとミドルウェア名を次のように変更します。Zodスキーマ、および検証後の値を取得するc.req.valid()は変更しません。
-import { zValidator } from "@hono/zod-validator";
+import { validator } from "hono-openapi";
userRoutes.get(
"/",
- zValidator("query", getUsersQuerySchema, (result, c) => {
+ validator("query", getUsersQuerySchema, (result, c) => {
if (!result.success) {
return c.json(
{
success: false,
message: "クエリパラメータの形式が正しくありません",
- errors: result.error.issues,
+ errors: result.error,
},
400,
);
}
}),
async (c) => {
const query = c.req.valid("query");
// 検証済みのqueryを使用する
},
);
paramを検証するGET /users/:idも同じ要領で移行します。
validator("param", getUserByIdParamsSchema, (result, c) => {
if (!result.success) {
return c.json(
{
success: false,
message:
"ユーザーIDの指定が正しくありません(1以上の整数を指定してください)",
errors: result.error,
},
400,
);
}
});
両validatorでは、検証失敗時のresult.errorの型が異なります。
| validator | result.error |
クライアントへIssue一覧を返す指定 |
|---|---|---|
@hono/zod-validatorのzValidator |
ZodError |
result.error.issues |
hono-openapiのvalidator |
Standard SchemaのIssue配列 | result.error |
hono-openapiのvalidatorにZodスキーマを直接渡せるため、入力検証ではresolver()によるラップは不要です。
validatorとdescribeRouteの役割
describeRouteはリクエスト検証に必須ではありません。2つのミドルウェアは、次のように役割を分担します。
| API | 役割 |
|---|---|
validator |
リクエストを実行時に検証し、検証済みの値をc.req.valid()へ格納する。検証対象のスキーマをOpenAPIのparameterまたはrequest bodyへ反映する。 |
describeRoute |
summary、tags、operationId、レスポンスなど、OpenAPI operationの追加情報を定義する。 |
validatorだけでもルートと入力スキーマはOpenAPI仕様へ出力されますが、レスポンスはスキーマや説明を持たない200として生成されます。このプロジェクトでは、全RESTルートでレスポンスやタグも明示するため、describeRouteをvalidatorと併用します。
+import { COMMON_ERROR_RESPONSES, OPENAPI_TAGS } from "@/api/openapi";
+import { describeRoute, validator } from "hono-openapi";
userRoutes.get(
"/",
+ describeRoute({
+ tags: [OPENAPI_TAGS.USERS],
+ summary: "ユーザー一覧を取得する",
+ responses: {
+ 200: { description: "ユーザー一覧の取得成功" },
+ 400: { description: "クエリパラメータが不正" },
+ ...COMMON_ERROR_RESPONSES,
+ },
+ }),
validator("query", getUsersQuerySchema, (result, c) => {
// 検証エラーの応答
}),
async (c) => {
// ユーザー一覧を返す既存のハンドラー
},
);
OPENAPI_TAGSとCOMMON_ERROR_RESPONSESはsrc/api/openapi.tsで共有します。各ルート固有のsummary、成功・400・404の説明はルート側に残し、全ルートで同一となる500・502の説明だけを共通化します。
レスポンス本文のスキーマを定義するときは、describeRouteのresponses内でresolver()を使用できます。実際の成功レスポンスは{ success: true, data: users }というラッパーを持つため、dataの配列だけではなく、ラッパー全体に対応するZodスキーマを指定してください。
Swagger UIから実ルートを呼び出す仕組み
REST APIは、2段階でHonoアプリへマウントされています。
userRoutes の "/"
→ apiRoot の "/users"
→ app の "/api"
→ 実際のルート "/api/users"
外側のsrc/index.tsxは、apiRootを/apiへマウントします。
app.route("/api", apiRoot);
一方、OpenAPI仕様は内側のapiRootから生成します。
apiRoot.route("/users", usersRoutes);
apiRoot.get(
"/openapi",
openAPIRouteHandler(apiRoot, {
documentation: {
info: {
title: "Post App API",
version: "1.0.0",
description: "Cloudflare with Hono Examples",
},
servers: [{ url: "/api" }],
},
}),
);
openAPIRouteHandler()へ渡しているのは外側のappではなくapiRootです。そのため、生成されるOpenAPI仕様のpathsには、/apiを含まない内側のパスが記録されます。
{
"servers": [{ "url": "/api" }],
"paths": {
"/users": {},
"/users/{id}": {},
"/posts": {},
"/posts/{id}": {}
}
}
Swagger UIは、OpenAPIのserver URLとpathを組み合わせてリクエスト先を決定します。
server "/api" + path "/users" = "/api/users"
serversを設定しない場合、Swagger UIは通常、仕様にある/usersをそのままホスト直下へ送信します。実ルートの/api/usersを呼び出すには、現在の実装のようにdocumentation.serversへ{ url: "/api" }を設定します。apiRoot側のルートを/api/usersへ変更すると、外側のマウントと重なって実ルートが/api/api/usersになるため、ルート定義側へ/apiを重ねないでください。
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
E2B
Using MCP to run code via e2b.