FastMCP

FastMCP

A TypeScript framework for building MCP servers with client session management capabilities, supporting tools definition, authentication, image content, logging, and error handling.

Category
Visit Server

README

FastMCP

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

SSE

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: 画像のURL
  • path: 画像ファイルへのパス
  • buffer: バッファとしての画像データ

urlpathbufferのいずれか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 `これらの変更に対する簡潔かつ説明的なコミットメッセージを生成してください:\n\n${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);
});

サーバーの実行

MCP-CLIでテスト

サーバーをテストしてデバッグする最速の方法は、fastmcp devを使用することです:

npx fastmcp dev server.js
npx fastmcp dev server.ts

これにより、mcp-cliを使用してターミナルでMCPサーバーをテストおよびデバッグするためのサーバーが実行されます。

MCP Inspectorで検査

もう一つの方法は、公式のMCP Inspectorを使用してWebUIでサーバーを検査することです:

npx fastmcp inspect server.ts

よくある質問

Claude Desktopで使用するには?

ガイド https://modelcontextprotocol.io/quickstart/user に従って、次の設定を追加してください:

{
  "mcpServers": {
    "my-mcp-server": {
      "command": "npx",
      "args": [
        "tsx",
        "/プロジェクトへのパス/src/index.ts"
      ],
      "env": {
        "環境変数名": "値"
      }
    }
  }
}

事例紹介

[!NOTE]

FastMCPを使用したサーバーを開発した場合は、ぜひPR提出して事例として紹介してください!

謝辞

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured