MCP(Model Context Protocol)とは
AIエージェントと外部システムを接続するためのオープンソース標準規格です。
MCPを使用することで、ClaudeやChatGPTなどのAIエージェントは、データソース(ローカルファイル、データベースなど)、ツール(検索エンジンなど)、ワークフロー(特殊なプロンプトなど)に接続し、必要な情報にアクセスしてタスクを実行できるようになります。
よくUSB-Cポートに例えられ、多様なデバイスを共通の規格で接続するように、MCPもAIと外部システムを共通の規格で接続しています。
カスタムサーバーを作ってみる
理解を深めるため、実際に作ってみようと思います。
作るもの:
- Figmaの情報を取得するMCPサーバー
-
get_figma_image: 指定したノードの画像をダウンロードし、output/フォルダに保存するツール -
generate_component: 指定したノードから HTML+CSS Modulesのコンポーネントを生成し、output/フォルダに保存するツール
-
- Claude Codeなど、MCP対応クライアントから呼び出せる
開発環境:
- Node.js: v24.15.0
- TypeScript: v6.0.3
- Claude Code: v2.1.145
成果物
コードの全容はこちらです。
使い方はREADMEをご確認ください。
コードの解説
ここからはMCPサーバーに関わるコードを抜粋して解説していきます。
Figma APIに関わるコードは解説しませんので、気になる方はこちらの公式ドキュメントを参考にしてください。
ディレクトリ構成
figma-mcp/
├── src/
│ ├── index.ts # ツール登録
│ ├── figma-client.ts # Figma API クライアント
│ └── tools/ # ツールごとにファイルを分割
│ ├── get-figma-image.ts
│ └── generate-component.ts
├── dist/ # ビルド出力
├── output/ # 生成された画像・コンポーネントの保存先
├── .env # 環境変数(gitignore済み)
└── .mcp.json # MCP サーバー設定
.mcp.json
MCPサーバーの起動設定を定義するファイルです。
プロジェクトルートに.mcp.jsonを置いて、現在のプロジェクトのみMCPをインストールしています。
{
"mcpServers": {
"figma-mcp": {
"command": "node",
"args": ["dist/index.js"],
"env": {}
}
}
}
command - サーバー起動を実行するコマンド
args - 引数(サーバーを起動させるファイルのパス)
env - 環境変数(今回は空)
index.ts
サーバー起動・ツール登録をしているファイルです。
公式のREADME通りに実装しています。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
MCPの公式SDKが提供するクラス。
MCPサーバーを作るための土台です。
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
MCPサーバーとクライアントの通信手段を実装するクラス。
Stdio = 標準入出力(stdin/stdout)を使って通信します。
// McpServerのインスタンスを作成
const server = new McpServer({ name: "figma-mcp", version: "1.0.0" });
// ツールを登録(importした関数を実行)
registerGetFigmaImage(server);
registerGenerateComponent(server);
// サーバー立ち上げ
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Figma MCP サーバーが起動しました");
}
// 実行
main().catch((err) => {
console.error(err);
process.exit(1);
});
ツールを管理しやすくするため、ツール個別の処理は/tools配下に切り出しており、今回はimportした関数を実行しています。
tools/get-figma-image.ts
ツールの詳細を定義しているファイルです。
コンポーネント生成ツールを定義している tools/generate-component.ts もMCPツール登録の構造は同じなので割愛します。コールバック内部はそれぞれ異なる処理を行っており、詳細はリポジトリでご確認ください。
import { z } from "zod";
TypeScript向けの型定義・バリデーションライブラリです。
ツール登録の際、入力パラメータ(inputSchema)をzodで定義しています。
これにより「型安全なバリデーション」と「AIへのパラメータ説明の自動生成」が同時に行えます。
export function registerGetFigmaImage(server: McpServer) {
server.registerTool(
"get_figma_image",
{
description: "Figma の URL から画像を取得して保存します",
inputSchema: {
figmaUrl: z.url().describe("Figma の URL(例: https://www.figma.com/file/<KEY>/...?node-id=<ID>)"),
format: z.enum(["png", "svg", "jpg"]).default("png").describe("画像フォーマット"),
scale: z.number().min(0.5).max(4).default(2).describe("スケール倍率(0.5〜4, Retina は 2)"),
}
},
async ({ figmaUrl, format, scale }) => {
...
}
);
ツールを登録するための関数です。
第一引数: ツールの名前
第二引数: ツール設定
description: 自然言語で機能の説明
inputSchema: 入力パラメータ
第三引数: コールバック関数(引数にはinputSchemaで定義したパラメータが展開されて渡ってくる)
return {
content: [
{
type: "text",
text: `✅ 画像を保存しました\n\n保存パス: ${filePath}\nノード ID: ${normalizedNodeId}\nフォーマット: ${format} (x${scale})`,
},
],
};
contentは必須で返す必要があります。
今回はText Contentのみを返していますが、他にも色々なContentを返すことができます。
詳しくはこちらをご確認ください。
コードの解説は以上となります。
MCPサーバー内部の処理の流れ
ここからはMCPサーバーが呼び出されたとき、内部でどのような処理が行われているのか深掘りしました。
StdioServerTransportとzodの役割を整理しながら見ていきます。
処理の流れ
①AIがパラメータを決定し、JSON形式でMCPサーバーに送信
↓
②StdioServerTransportがstdin経由で受け取り、オブジェクトに変換
↓
③zodがバリデーション
↓
④コールバック関数実行 → 外部API通信
↓
⑤結果をcontentにまとめてreturn
↓
⑥StdioServerTransportがstdout経由でAIに返す
②StdioServerTransportがstdin経由で受け取り、オブジェクトに変換
StdioServerTransportは、MCPサーバーとクライアントの通信手段を実装するクラスでした。
AIから送られてきたJSONをstdin経由で受け取り、MCPサーバーが扱えるオブジェクトに変換します。
③zodがバリデーション
zodは、TypeScript向けの型定義・バリデーションライブラリでした。
MCPサーバーでは主に2つの役割を担っています。
1. バリデーション
StdioServerTransportがオブジェクトに変換した値を、zodがバリデーションします。
// 分かりやすくコードを簡略化
inputSchema: {
figmaUrl: z.url().describe("Figma の URL"),
format: z.enum(["png", "jpg"]).describe("画像フォーマット"),
scale: z.number().min(1).max(4).describe("画像のスケール"),
}
例えばscale: 10といった範囲外の数値が渡ってきた場合、zodがAIにエラーを返します。AIはエラーを受け取ると、値を修正して再度ツールを呼び出します。
もしzodがない場合、不正な値がコールバック関数に渡されてしまい、外部APIがエラーや意図しない結果を返してきます。自分でzodを使わずバリデーションを書くことはできますが、zodを使うことでより簡潔に型安全なバリデーションが書けます。
2. AIへのパラメータ説明の自動生成
zodで定義したスキーマは、SDKによって自動的にJSONスキーマに変換されます。
// zodで書いたスキーマ
scale: z.number().min(1).max(4).describe("画像のスケール")
// SDKが自動変換したJSONスキーマ
{
"type": "number",
"minimum": 1,
"maximum": 4,
"description": "画像のスケール"
}
このJSONスキーマはAIへの参考情報として渡され、AIが「scaleには1〜4の数値を入れるんだな」と理解し、ツールを正しく呼び出してくれます。
.describe()に書いた説明文もここで使用されます。
最後に
思っていたより少ないコードでMCPサーバーを構築できました。
APIさえ提供されていれば、自分好みのツールを作れるのがMCPの魅力だと感じます。
ぜひ試してみてください。
