FastMCP: MCPサーバーとクライアント構築の完全ガイド

FastMCP: MCPサーバーとクライアント構築の完全ガイド

FastMCP 2.0の全容を解説するチュートリアルです。このライブラリを使えば、Model Context Protocol (MCP) のサーバーとクライアントをPythonらしく、かつ迅速に構築できます。LLMアプリケーション向けのツール、リソース、プロンプトの作成方法を習得しましょう。

レッスン 6 2025-07-03 07:21

ファストMCPとCursor IDEの連携

Cursor IDEとFastMCPの統合

Cursor IDEは、Model Context Protocol(MCP)サーバーへの優れたサポートを提供し、FastMCPサーバーを開発ワークフローにシームレスに統合できます。このガイドでは、CursorでFastMCPサーバーをセットアップして使用する方法を説明します。

CursorにおけるMCPとは?

Model Context Protocol(MCP)は、Cursorを外部ツールやデータソースに接続するためのプロトコルです。プロジェクト構造を繰り返し説明する代わりに、ツールと直接統合できます。

Cursorは、stdoutに出力できる、またはHTTPエンドポイントを提供できるあらゆる言語で書かれたMCPサーバーをサポートしています。そのため、FastMCP(Python)は完璧にフィットします!

CursorでFastMCPを使用する理由

FastMCPのシンプルさと強力な機能は、Cursorとの統合に最適です。

  • 迅速な開発: 最小限のボイラープレートでMCPサーバーを構築
  • 豊富なツール: 型安全性に優れた洗練されたツールを作成
  • リソースアクセス: AIアシスタントにコンテキストデータを提供
  • 簡単なデプロイ: さまざまなユースケースに対応する複数の転送オプション

転送方法

Cursorは、MCPサーバー用に3つの転送方法をサポートしています。

転送 実行 デプロイ ユーザー 入力 認証
stdio ローカル Cursorが管理 シングルユーザー シェルコマンド 手動
SSE ローカル/リモート サーバーとしてデプロイ 複数ユーザー SSEエンドポイントのURL OAuth
Streamable HTTP ローカル/リモート サーバーとしてデプロイ 複数ユーザー HTTPエンドポイントのURL OAuth

FastMCPサーバーについては、ローカル開発およびテスト用にstdioメソッドに焦点を当てます。

CursorでのFastMCPのセットアップ

ステップ1: FastMCPサーバーの作成

まず、開発ツールを提供するシンプルなFastMCPサーバーを作成しましょう。

# cursor_dev_tools.py
import asyncio
import subprocess
from pathlib import Path
from fastmcp import FastMCP

# MCPサーバーを作成します
mcp = FastMCP("Cursor Development Tools")

@mcp.tool()
def get_project_structure(max_depth: int = 2) -> str:
    """指定された深さまでの現在のプロジェクト構造を取得します。."""
    try:
        result = subprocess.run(
            ["find", ".", "-type", "f", "-name", "*.py", "-o", "-name", "*.js", "-o", "-name", "*.ts", "-o", "-name", "*.json"],
            capture_output=True,
            text=True,
            cwd="."
        )
        files = result.stdout.strip().split('\n')

        # ディレクトリで整理
        structure = {}
        for file in files:
            if file:
                parts = Path(file).parts
                current = structure
                for part in parts[:-1]:
                    if part not in current:
                        current[part] = {}
                    current = current[part]
                current[parts[-1]] = "file"

        return f"Project Structure:\n{_format_structure(structure)}"
    except Exception as e:
        return f"Error getting project structure: {str(e)}"

def _format_structure(structure, indent=0):
    """構造辞書をツリーとしてフォーマットします。"""
    result = []
    for key, value in structure.items():
        prefix = "  " * indent + "├── "
        if isinstance(value, dict):
            result.append(f"{prefix}{key}/")
            result.append(_format_structure(value, indent + 1))
        else:
            result.append(f"{prefix}{key}")
    return "\n".join(result)

@mcp.tool()
def run_command(command: str, working_dir: str = ".") -> str:
    """指定されたディレクトリでシェルコマンドを実行します。"""
    try:
        result = subprocess.run(
            command,
            shell=True,
            capture_output=True,
            text=True,
            cwd=working_dir,
            timeout=30
        )

        output = []
        if result.stdout:
            output.append(f"STDOUT:\n{result.stdout}")
        if result.stderr:
            output.append(f"STDERR:\n{result.stderr}")

        output.append(f"Return code: {result.returncode}")
        return "\n\n".join(output)

    except subprocess.TimeoutExpired:
        return "Command timed out after 30 seconds"
    except Exception as e:
        return f"Error executing command: {str(e)}"

@mcp.tool()
def search_code(pattern: str, file_extension: str = "py") -> str:
    """プロジェクトファイル内のコードパターンを検索します。"""
    try:
        result = subprocess.run(
            ["grep", "-r", "--include", f"*.{file_extension}", pattern, "."],
            capture_output=True,
            text=True
        )

        if result.returncode == 0:
            return f"Found matches for '{pattern}':\n\n{result.stdout}"
        else:
            return f"No matches found for pattern '{pattern}' in *.{file_extension} files"

    except Exception as e:
        return f"Error searching code: {str(e)}"

@mcp.resource("file://project-docs")
async def get_project_docs():
    """プロジェクトのドキュメントとREADMEファイルを提供します。"""
    docs = []

    # 一般的なドキュメントファイルを検索します
    doc_files = ["README.md", "README.rst", "docs/README.md", "CONTRIBUTING.md"]

    for doc_file in doc_files:
        path = Path(doc_file)
        if path.exists():
            try:
                content = path.read_text()
                docs.append(f"=== {doc_file} ===\n{content}\n")
            except Exception as e:
                docs.append(f"=== {doc_file} ===\nError reading file: {str(e)}\n")

    if not docs:
        docs.append("No documentation files found in project root.")

    return "\n".join(docs)

if __name__ == "__main__":
    mcp.run()

ステップ2: CursorでのMCPの設定

設定には2つのオプションがあります。

オプションA: プロジェクト固有の設定

プロジェクトのルートに.cursor/mcp.jsonを作成します。

{
  "mcpServers": {
    "fastmcp-dev-tools": {
      "command": "python",
      "args": ["cursor_dev_tools.py"],
      "env": {}
    }
  }
}

オプションB: グローバル設定

グローバルアクセス用にホームディレクトリに~/.cursor/mcp.jsonを作成します。

{
  "mcpServers": {
    "fastmcp-dev-tools": {
      "command": "python",
      "args": ["/path/to/your/cursor_dev_tools.py"],
      "env": {}
    }
  }
}

ステップ3: 環境変数の使用

APIキーや設定が必要なサーバーの場合:

{
  "mcpServers": {
    "fastmcp-api-server": {
      "command": "python",
      "args": ["api_server.py"],
      "env": {
        "API_KEY": "your-api-key-here",
        "DEBUG": "true"
      }
    }
  }
}

CursorでのMCPツールの使用

自動ツール使用

Cursor Composer Agentは、関連性がある場合、「利用可能なツール」にリストされているMCPツールを自動的に使用します。FastMCPツールはチャットインターフェースに表示されます。

手動ツール呼び出し

特定のツールを名前で要求することもできます。 - 「get_project_structureツールを使ってプロジェクトのレイアウトを表示して」 - 「search_codeツールを実行してすべての非同期関数を検索して」 - 「run_commandを実行して依存関係をインストールして」

ツールの承認と自動実行

デフォルトでは、CursorはMCPツールを使用する前に承認を求めます。次のことができます。

  1. 手動承認: ツール名の横にある矢印をクリックして引数を確認し、承認します。
  2. 自動実行モード: 「Yoloモード」を有効にすると、承認なしでツールが自動的に実行されます。

Cursor向けFastMCPの高度な機能

画像の返却

FastMCPサーバーは、Cursorがチャットに表示する画像を返すことができます。

import base64
from fastmcp import FastMCP

mcp = FastMCP("Image Generator")

@mcp.tool()
def generate_diagram() -> dict:
    """シンプルな図を生成し、画像として返します。"""
    # 画像を作成または生成します
    with open("diagram.png", "rb") as f:
        image_data = base64.b64encode(f.read()).decode()

    return {
        "content": [
            {
                "type": "image",
                "data": image_data,
                "mimeType": "image/png"
            }
        ]
    }

複雑なリソースプロバイダー

FastMCPのリソースシステムを使用して、豊富なコンテキストデータを提供します。

@mcp.resource("file://git-status")
async def get_git_status():
    """現在のgitリポジトリのステータスを提供します。"""
    try:
        # gitステータスを取得します
        status_result = subprocess.run(
            ["git", "status", "--porcelain"],
            capture_output=True,
            text=True
        )

        # 最近のコミットを取得します
        log_result = subprocess.run(
            ["git", "log", "--oneline", "-10"],
            capture_output=True,
            text=True
        )

        return f"Git Status:\n{status_result.stdout}\n\nRecent Commits:\n{log_result.stdout}"

    except Exception as e:
        return f"Error getting git status: {str(e)}"

デバッグとトラブルシューティング

MCPログの表示

CursorでMCPサーバーの問題をデバッグするには:

  1. Outputパネルを開きます(Macでは⌘⇧U、Windows/LinuxではCtrl+Shift+U
  2. ドロップダウンから「MCP Logs」を選択します
  3. 接続エラー、認証の問題、サーバークラッシュを確認します

よくある問題

サーバーが起動しない - Pythonとスクリプトが正しいパスにあることを確認してください - mcp.jsonの設定構文を確認してください - すべての依存関係がインストールされていることを確認してください

ツールが表示されない - 設定を変更した後、Cursorを再起動してください - エラーメッセージについてMCPログを確認してください - FastMCPサーバーがコマンドラインから正しく実行されていることを確認してください

権限エラー - Pythonスクリプトに実行権限があることを確認してください - Cursorが指定されたディレクトリにアクセスできることを確認してください

サーバーのテスト

FastMCPサーバーを個別にテストします。

# サーバーを直接実行
python cursor_dev_tools.py

# MCPクライアントツールでテスト
npx @modelcontextprotocol/inspector cursor_dev_tools.py

セキュリティのベストプラクティス

CursorでFastMCPサーバーを使用する場合:

  1. ソースの確認: 信頼できる開発者からのMCPサーバーのみを使用してください
  2. コードのレビュー: 特に機密性の高いプロジェクトでは、インストール前にサーバーコードを監査してください
  3. 権限の制限: 最小限の必要な権限を持つ制限されたAPIキーを使用してください
  4. 環境変数: 機密情報は環境変数に保存し、ハードコードしないでください
  5. ローカル開発: 機密性の高い開発作業にはstdio転送を使用してください

実世界での例

開発ワークフローの統合

# 強化された開発ツールサーバー
from fastmcp import FastMCP
import subprocess
import json

mcp = FastMCP("Advanced Dev Tools")

@mcp.tool()
def run_tests(test_pattern: str = "") -> str:
    """オプションのパターンフィルタリングでプロジェクトテストを実行します。"""
    cmd = ["python", "-m", "pytest"]
    if test_pattern:
        cmd.extend(["-k", test_pattern])

    result = subprocess.run(cmd, capture_output=True, text=True)
    return f"Test Results:\n{result.stdout}\n{result.stderr}"

@mcp.tool()
def format_code() -> str:
    """blackを使ってPythonコードを整形します。"""
    result = subprocess.run(
        ["black", ".", "--check", "--diff"],
        capture_output=True,
        text=True
    )

    if result.returncode == 0:
        return "Code is already formatted correctly"
    else:
        return f"Code formatting suggestions:\n{result.stdout}"

@mcp.tool()
def check_dependencies() -> str:
    """古いパッケージの依存関係をチェックします。"""
    result = subprocess.run(
        ["pip", "list", "--outdated", "--format", "json"],
        capture_output=True,
        text=True
    )

    try:
        outdated = json.loads(result.stdout)
        if outdated:
            output = "Outdated packages:\n"
            for pkg in outdated:
                output += f"- {pkg['name']}: {pkg['version']} -> {pkg['latest_version']}\n"
            return output
        else:
            return "All packages are up to date!"
    except:
        return "Error checking dependencies"

API統合ツール

@mcp.tool()
def fetch_api_docs(api_url: str) -> str:
    """OpenAPI/SwaggerエンドポイントからAPIドキュメントを取得します。"""
    import requests

    try:
        response = requests.get(f"{api_url}/openapi.json", timeout=10)
        if response.status_code == 200:
            api_spec = response.json()
            return f"API Documentation for {api_url}:\n{json.dumps(api_spec, indent=2)}"
        else:
            return f"Failed to fetch API docs: HTTP {response.status_code}"
    except Exception as e:
        return f"Error fetching API docs: {str(e)}"

次のステップ

FastMCPがCursorと統合されたので、次のことを行えます。

  1. 利用可能なツールの探索: 事前に構築されたサーバーについては、MCP Toolsディレクトリをチェックしてください
  2. カスタムツールの構築: 開発ワークフロー用のドメイン固有のツールを作成します
  3. サーバーの共有: 便利なFastMCPサーバーをコミュニティに公開することを検討してください
  4. 本番環境へのデプロイ: チームコラボレーションのために、SSEまたはHTTP転送に移行します

FastMCPの使いやすさとCursorの強力なMCP統合の組み合わせにより、シームレスなAI支援開発エクスペリエンスが実現します。特定のコードベースとワークフローを理解するツールの構築を始めましょう!

トラブルシューティングFAQ

Q: FastMCPサーバーがCursorのツールリストに表示されません A: mcp.jsonの構文が正しいことを確認し、Cursorを再起動してください。サーバーがpython your_server.pyで個別に実行されることを確認してください。

Q: ツールが呼び出されていますが、エラーが返されます A: CursorのOutputパネルにあるMCPログを確認してください。一般的な問題には、依存関係の不足や不適切な作業ディレクトリなどがあります。

Q: サーバーを一時的に無効にするにはどうすればよいですか? A: 設定(⌘⇧J)→機能→Model Context Protocolに移動し、設定を削除せずにサーバーをオフに切り替えます。

Q: リモートのCursorインストールでFastMCPを使用できますか? A: リモート開発の場合、stdioの代わりにSSEまたはHTTP転送でFastMCPサーバーをデプロイすることを検討してください。

FastMCPとCursorを使用することで、特定のニーズとコードベースを理解するAI支援開発ツールを作成するための強力なプラットフォームが手に入ります!