A TypeScript framework for building MCP servers with client session management capabilities, supporting tools definition, authentication, image content, logging, and error handling.
FastMCPは、クライアントセッション管理が可能なMCPサーバーを構築するためのTypeScriptフレームワークです。
[!NOTE]
Python実装版はFastMCP Pythonをご覧ください。
FastMCPは以下の機能を提供します:
npm install fastmcp
[!NOTE]
FastMCPの実際の使用例は多数あります。事例紹介をご覧ください。
import { FastMCP } from "fastmcp"; import { z } from "zod"; // または他の検証ライブラリ(Standard Schemaをサポートしているもの) const server = new FastMCP({ name: "マイサーバー", version: "1.0.0", }); server.addTool({ name: "add", description: "2つの数値を足し算します", parameters: z.object({ a: z.number(), b: z.number(), }), execute: async (args) => { return String(args.a + args.b); }, }); server.start({ transportType: "stdio", });
これだけで動作するMCPサーバーができました!
ターミナルで以下のようにテストできます:
git clone https://github.com/punkpeye/fastmcp.git cd fastmcp pnpm install pnpm build # CLIを使った足し算サーバーの例をテスト: npx fastmcp dev src/examples/addition.ts # MCP Inspectorを使った足し算サーバーの例を検査: npx fastmcp inspect src/examples/addition.ts
Server-Sent Events(SSE)は、サーバーがHTTPS接続を介してクライアントにリアルタイム更新を送信するメカニズムです。MCPにおいて、SSEは主にリモートMCP通信を可能にするために使用され、リモートマシンでホストされたMCPにアクセスしてネットワーク経由で更新を中継できるようにします。
SSEサポート付きでサーバーを実行することもできます:
server.start({ transportType: "sse", sse: { endpoint: "/sse", port: 8080, }, });
これにより、サーバーが起動し、http://localhost:8080/sse
でSSE接続をリッスンします。
その後、SSEClientTransport
を使用してサーバーに接続できます:
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; const client = new Client( { name: "example-client", version: "1.0.0", }, { capabilities: {}, }, ); const transport = new SSEClientTransport(new URL(`http://localhost:8080/sse`)); await client.connect(transport);
MCPのツールでは、サーバーが実行可能な関数を公開し、クライアントやLLMがアクションを実行するために呼び出すことができます。
FastMCPはツールパラメーターの定義にStandard Schema仕様を使用しています。これにより、Zod、ArkType、Valibotなど、仕様を実装している好みのスキーマ検証ライブラリを使用できます。
Zodの例:
import { z } from "zod"; server.addTool({ name: "fetch-zod", description: "URLのコンテンツを取得します(Zodを使用)", parameters: z.object({ url: z.string(), }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });
ArkTypeの例:
import { type } from "arktype"; server.addTool({ name: "fetch-arktype", description: "URLのコンテンツを取得します(ArkTypeを使用)", parameters: type({ url: "string", }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });
Valibotの例:
Valibotにはピア依存関係@valibot/to-json-schemaが必要です。
import * as v from "valibot"; server.addTool({ name: "fetch-valibot", description: "URLのコンテンツを取得します(Valibotを使用)", parameters: v.object({ url: v.string(), }), execute: async (args) => { return await fetchWebpageContent(args.url); }, });
execute
は文字列を返すことができます:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { return "こんにちは、世界!"; }, });
これは以下と同等です:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "こんにちは、世界!", }, ], }; }, });
メッセージのリストを返したい場合は、content
プロパティを持つオブジェクトを返せます:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "text", text: "1つ目のメッセージ" }, { type: "text", text: "2つ目のメッセージ" }, ], }; }, });
画像のコンテンツオブジェクトを作成するには、imageContent
を使用します:
import { imageContent } from "fastmcp"; server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { return imageContent({ url: "https://example.com/image.png", }); // または... // return imageContent({ // path: "/path/to/image.png", // }); // または... // return imageContent({ // buffer: Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "base64"), // }); // または... // return { // content: [ // await imageContent(...) // ], // }; }, });
imageContent
関数は以下のオプションを受け取ります:
url
: 画像のURLpath
: 画像ファイルへのパスbuffer
: バッファとしての画像データurl
、path
、buffer
のいずれか1つのみを指定する必要があります。
上の例は以下と同等です:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { return { content: [ { type: "image", data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", mimeType: "image/png", }, ], }; }, });
ツールはコンテキストオブジェクトのlog
を使用してクライアントにメッセージをログ出力できます:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args, { log }) => { log.info("ファイルをダウンロード中...", { url: args.url, }); // ... log.info("ファイルをダウンロードしました"); return "完了"; }, });
log
オブジェクトには以下のメソッドがあります:
debug(message: string, data?: SerializableValue)
error(message: string, data?: SerializableValue)
info(message: string, data?: SerializableValue)
warn(message: string, data?: SerializableValue)
ユーザーに表示されるべきエラーは、UserError
インスタンスとしてスローする必要があります:
import { UserError } from "fastmcp"; server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args) => { if (args.url.startsWith("https://example.com")) { throw new UserError("このURLは許可されていません"); } return "完了"; }, });
ツールはコンテキストオブジェクトのreportProgress
を呼び出すことで進捗を報告できます:
server.addTool({ name: "download", description: "ファイルをダウンロードします", parameters: z.object({ url: z.string(), }), execute: async (args, { reportProgress }) => { reportProgress({ progress: 0, total: 100, }); // ... reportProgress({ progress: 100, total: 100, }); return "完了"; }, });
リソースは、MCPサーバーがクライアントに提供したいあらゆる種類のデータを表します。これには以下が含まれます:
各リソースは一意のURIで識別され、テキストまたはバイナリデータを含むことができます。
server.addResource({ uri: "file:///logs/app.log", name: "アプリケーションログ", mimeType: "text/plain", async load() { return { text: await readLogFile(), }; }, });
[!NOTE]
load
は複数のリソースを返すことができます。これは例えば、ディレクトリが読み込まれたときにディレクトリ内のファイルのリストを返すために使用できます。async load() { return [ { text: "1つ目のファイルの内容", }, { text: "2つ目のファイルの内容", }, ]; }
load
でバイナリコンテンツを返すこともできます:
async load() { return { blob: 'base64でエンコードされたデータ' }; }
リソーステンプレートを定義することもできます:
server.addResourceTemplate({ uriTemplate: "file:///logs/{name}.log", name: "アプリケーションログ", mimeType: "text/plain", arguments: [ { name: "name", description: "ログの名前", required: true, }, ], async load({ name }) { return { text: `${name}のサンプルログ内容`, }; }, });
リソーステンプレート引数の自動補完を有効にするために、complete
関数を提供します:
server.addResourceTemplate({ uriTemplate: "file:///logs/{name}.log", name: "アプリケーションログ", mimeType: "text/plain", arguments: [ { name: "name", description: "ログの名前", required: true, complete: async (value) => { if (value === "サンプル") { return { values: ["サンプルログ"], }; } return { values: [], }; }, }, ], async load({ name }) { return { text: `${name}のサンプルログ内容`, }; }, });
プロンプトは、サーバーが再利用可能なプロンプトテンプレートとワークフローを定義し、クライアントがユーザーやLLMに簡単に提示できるようにします。これにより、一般的なLLMインタラクションを標準化して共有するための強力な方法を提供します。
server.addPrompt({ name: "git-commit", description: "Gitコミットメッセージを生成します", arguments: [ { name: "changes", description: "Gitの差分または変更の説明", required: true, }, ], load: async (args) => { return `これらの変更に対する簡潔かつ説明的なコミットメッセージを生成してください: ${args.changes}`; }, });
プロンプトは引数の自動補完を提供できます:
server.addPrompt({ name: "countryPoem", description: "国についての詩を書きます", load: async ({ name }) => { return `こんにちは、${name}さん!`; }, arguments: [ { name: "name", description: "国の名前", required: true, complete: async (value) => { if (value === "日") { return { values: ["日本"], }; } return { values: [], }; }, }, ], });
enum
を使用したプロンプト引数の自動補完引数にenum
配列を提供すると、サーバーは自動的に引数の補完を提供します。
server.addPrompt({ name: "countryPoem", description: "国についての詩を書きます", load: async ({ name }) => { return `こんにちは、${name}さん!`; }, arguments: [ { name: "name", description: "国の名前", required: true, enum: ["日本", "フランス", "イタリア"], }, ], });
FastMCPではカスタム関数を使用してクライアントをauthenticate
できます:
import { AuthError } from "fastmcp"; const server = new FastMCP({ name: "マイサーバー", version: "1.0.0", authenticate: ({request}) => { const apiKey = request.headers["x-api-key"]; if (apiKey !== '123') { throw new Response(null, { status: 401, statusText: "Unauthorized", }); } // ここで返すものは`context.session`オブジェクトでアクセスできます return { id: 1, } }, });
これで、ツール内で認証されたセッションデータにアクセスできます:
server.addTool({ name: "sayHello", execute: async (args, { session }) => { return `こんにちは、${session.id}さん!`; }, });
session
オブジェクトはFastMCPSession
のインスタンスであり、アクティブなクライアントセッションを記述します。
server.sessions;
クライアントとサーバー間の1対1通信を可能にするために、各クライアント接続に対して新しいサーバーインスタンスを割り当てます。
on
メソッドを使用してサーバーから発行されるイベントをリッスンできます:
server.on("connect", (event) => { console.log("クライアント接続:", event.session); }); server.on("disconnect", (event) => { console.log("クライアント切断:", event.session); });
FastMCPSession
FastMCPSession
はクライアントセッションを表し、クライアントとやり取りするためのメソッドを提供します。
FastMCPSession
インスタンスの取得方法については、セッションの例を参照してください。
requestSampling
requestSampling
はサンプリングリクエストを作成し、レスポンスを返します。
await session.requestSampling({ messages: [ { role: "user", content: { type: "text", text: "現在のディレクトリにはどのファイルがありますか?", }, }, ], systemPrompt: "あなたは役立つファイルシステムアシスタントです。", includeContext: "thisServer", maxTokens: 100, });
clientCapabilities
clientCapabilities
プロパティにはクライアント機能が含まれています。
session.clientCapabilities;
loggingLevel
loggingLevel
プロパティは、クライアントによって設定されたロギングレベルを記述します。
session.loggingLevel;
roots
roots
プロパティには、クライアントによって設定されたルートが含まれています。
session.roots;
server
server
プロパティには、セッションに関連付けられたMCPサーバーのインスタンスが含まれています。
session.server;
on
メソッドを使用してセッションから発行されるイベントをリッスンできます:
session.on("rootsChanged", (event) => { console.log("ルート変更:", event.roots); }); session.on("error", (event) => { console.error("エラー:", event.error); });
サーバーをテストしてデバッグする最速の方法は、fastmcp dev
を使用することです:
npx fastmcp dev server.js npx fastmcp dev server.ts
これにより、mcp-cli
を使用してターミナルでMCPサーバーをテストおよびデバッグするためのサーバーが実行されます。
もう一つの方法は、公式のMCP Inspector
を使用してWebUIでサーバーを検査することです:
npx fastmcp inspect server.ts
ガイド https://modelcontextprotocol.io/quickstart/user に従って、次の設定を追加してください:
{ "mcpServers": { "my-mcp-server": { "command": "npx", "args": [ "tsx", "/プロジェクトへのパス/src/index.ts" ], "env": { "環境変数名": "値" } } } }
[!NOTE]
FastMCPを使用したサーバーを開発した場合は、ぜひPR提出して事例として紹介してください!
Discover shared experiences
Shared threads will appear here, showcasing real-world applications and insights from the community. Check back soon for updates!