TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

VSCodeでMCPサーバ(Python SDK)をデバッグする方法

MCPのPython SDKには、デバッグするためのuvのCLIコマンド

uv run mcp dev

が用意されている。

これを使うと、MCP Inspectorが起動し、ツールの一覧の表示やカスタム入力によるツールテストが可能になる。

しかし、デバッガで処理をステップ実行したり、変数状態を調べたりすることはできない。

ここでは、VSCodeのデバッガで起動して、デバッグする方法を紹介する。

MCPサーバのサンプルコード

以下の解説では、以下のサンプルコード(server.py)を使用して説明する。

"""
FastMCP quickstart example.

cd to the `examples/snippets/clients` directory and run:
    uv run server fastmcp_quickstart stdio
"""

from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"


# Add a prompt
@mcp.prompt()
def greet_user(name: str, style: str = "friendly") -> str:
    """Generate a greeting prompt"""
    styles = {
        "friendly": "Please write a warm, friendly greeting",
        "formal": "Please write a formal, professional greeting",
        "casual": "Please write a casual, relaxed greeting",
    }

    return f"{styles.get(style, styles['friendly'])} for someone named {name}."

MCPサーバをStreamable HTTPに対応させる

直接ホストする場合

MCPサーバを自分自身のプロセスでホストする場合、以下の行を追加する。

if __name__ == "__main__":
    mcp.run(transport="streamable-http")
ASGIサーバを使う場合

ASGIサーバをuvicornなどのアプリケーションサーバでホストする場合は、以下の1行を追加する。

app = mcp.streamable_http_app()


注:公式READMEの[Mounting to an Existing ASGI Server] -> [StreamableHTTP servers] -> [Basic mounting]に記載されている方法では、

RuntimeError: Task group is not initialized. Make sure to use run().

が発生する。READMEの記載が誤っており、issue #713に上記とは別の回避策が記載されている。
具体的には、Starletteにマウントする場合は、以下のように、lifespanを設定することで回避できる。

import contextlib
from starlette.applications import Starlette
from starlette.routing import Mount

# ...

@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
    async with contextlib.AsyncExitStack() as stack:
        await stack.enter_async_context(mcp.session_manager.run())
        yield
        
app = Starlette(
    routes=[
        Mount("/", app=mcp.streamable_http_app())
    ],
    lifespan=lifespan
)

VSCodeデバッグ設定

直接ホストする場合

通常のPythonファイルのデバッグと同じように設定して、デバッグ実行すればよい。

ASGIサーバを使う場合

デバッグタブから、create a launch.json fileを選択して、Python Debuggerを選択する。

Debug Configurationで、FastAPIを選択する。

ソースコード名を入力する(例:server.pyの場合、server)

uvicornで起動する定義が作成される。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: FastAPI",
            "type": "debugpy",
            "request": "launch",
            "module": "uvicorn",
            "args": [
                "server:app",
                "--reload"
            ],
            "jinja": true
        }
    ]
}

MCPサーバのテスト

GitHub Copilotから実行

GitHub Copilotから実行する場合は、F1キーを押して、「MCP: Add Server...」を選択して、「HTTP (HTTP or Server-Sent Events」を選択する。

URLに、「http://127.0.0.1:8000/mcp」を入力する。

サーバIDを入力する(デフォルトのままでも良い)。

設定の保存先を選択する(ここではWorkspaceを選択)。

Workspaceの「.vscodeディレクトリに、mcp.jsonが作成される。

{
	"servers": {
		"my-mcp-server-4b6438b8": {
			"url": "http://127.0.0.1:8000/mcp",
			"type": "http"
		}
	},
	"inputs": []
}

これで、GitHub CopilotからMCPサーバに接続できるようになる。

GitHub CopilotをAgentモードにして、「#add 」を付けて、足し算の式を入力すると、

MCPサーバアクセスの許可を求めてくる。

許可すると、addツールの実行結果が表示される。


ソースにブレークポイントを設定すると、停止してデバッグすることができる。

MCP Inspectorから実行

uv run mcp devで、MCP Inspectorを起動する。

$ uv run mcp dev server.py

Transport Typeを「Streamable HTTP」にして、URLに「http://127.0.0.1:8000/mcp」と入力して、Connectを押す。

ToolsタブからList Toolsをクリックして、addを選択して、パラメータを入力して実行できる。


以上