21 KiB
stdio トランスポートを使った MCP サーバー
⚠️ 重要な更新: MCP仕様書 2025-06-18 により、スタンドアロンの SSE (Server-Sent Events) トランスポートは非推奨となり、「Streamable HTTP」トランスポートに置き換えられました。現在の MCP 仕様では主に次の2つのトランスポート機構が定義されています:
- stdio - 標準入出力(ローカルサーバーに推奨)
- Streamable HTTP - SSEを内部的に使用する可能性があるリモートサーバー向け
本レッスンは、ほとんどの MCP サーバー実装に推奨されるstdio トランスポートに焦点を当てて更新されています。
stdio トランスポートは、MCP サーバーが標準入力と標準出力のストリームを介してクライアントと通信するためのものです。これは、現在の MCP 仕様で最も一般的かつ推奨されるトランスポート方式であり、さまざまなクライアントアプリケーションと簡単に統合できるシンプルで効率的な方法を提供します。
概要
このレッスンでは、stdio トランスポートを使った MCP サーバーの構築と利用方法を解説します。
学習目標
このレッスン終了時には以下が可能になります:
- stdio トランスポートを使った MCP サーバーの構築
- Inspector を使った MCP サーバーのデバッグ
- Visual Studio Code での MCP サーバーの利用
- 現行 MCP トランスポート機構と stdio が推奨される理由の理解
stdio トランスポートの仕組み
stdio トランスポートは、現行 MCP 仕様(2025-11-25)でサポートされている2つのトランスポートタイプのうちの1つです。仕組みは以下の通りです:
- シンプルな通信:サーバーは標準入力(stdin)から JSON-RPC メッセージを読み込み、標準出力(stdout)にメッセージを送信します。
- プロセスベース:クライアントが MCP サーバーをサブプロセスとして起動します。
- メッセージ形式:メッセージは個々の JSON-RPC リクエスト、通知、またはレスポンスで、改行で区切られています。
- ログ出力:サーバーは必要に応じて標準エラー(stderr)に UTF-8 文字列を書き込むことがあります。
重要な要件:
- メッセージは必ず改行で区切られ、埋め込み改行を含んではいけません
- サーバーは有効な MCP メッセージでないものを stdout に書き込んではいけません
- クライアントは有効な MCP メッセージでないものをサーバーの stdin に書き込んではいけません
TypeScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{
name: "example-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
上のコードでは:
- MCP SDK から
ServerクラスとStdioServerTransportをインポートしています - 基本的な設定と能力を持つサーバーインスタンスを作成しています
StdioServerTransportインスタンスを作成し、stdin/stdout 経由の通信を有効にするためサーバーに接続しています
Python
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# サーバーインスタンスを作成する
server = Server("example-server")
@server.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
上のコードでは:
- MCP SDK を使ってサーバーインスタンスを作成しています
- デコレーターを使ってツールを定義しています
- stdio_server コンテキストマネージャーを使用してトランスポートを処理しています
.NET
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
builder.Services.AddLogging(logging => logging.AddConsole());
var app = builder.Build();
await app.RunAsync();
SSE と違う主な点は stdio サーバーが:
- Webサーバー設定や HTTP エンドポイントを必要としないこと
- クライアントがサブプロセスとして起動すること
- stdin/stdout ストリームで通信すること
- 実装とデバッグがより簡単であること
演習: stdio サーバーの作成
サーバーを作成するにあたり、以下のことを念頭に置きます:
- 接続とメッセージ用にエンドポイントを公開するために Web サーバーを使用する必要があります。
実習: 簡単な MCP stdio サーバーの作成
この実習では、推奨される stdio トランスポートを使って単純な MCP サーバーを作成します。このサーバーはクライアントが標準の Model Context Protocol を使って呼び出せるツールを公開します。
前提条件
- Python 3.8 以上
- MCP Python SDK:
pip install mcp - 非同期プログラミングの基本知識
さっそく最初の MCP stdio サーバーを作成してみましょう:
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
# ロギングを設定する
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# サーバーを作成する
server = Server("example-stdio-server")
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
# stdioトランスポートを使用する
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
非推奨の SSE アプローチとの主な違い
Stdio トランスポート(現在の標準):
- シンプルなサブプロセスモデル - クライアントがサーバーを子プロセスとして起動
- JSON-RPC メッセージを使った stdin/stdout 通信
- HTTP サーバー設定は不要
- 性能とセキュリティが向上
- デバッグと開発が容易
SSE トランスポート(MCP 2025-06-18 以降非推奨):
- SSE エンドポイントを持つ HTTP サーバーが必要
- Webサーバーインフラによる複雑なセットアップ
- HTTP エンドポイントの追加セキュリティ考慮事項
- Webベースのシナリオでは Streamable HTTP に置き換えられた
stdio トランスポートでサーバーを作る
stdio サーバー作成の基本手順は以下の通りです:
- 必要なライブラリをインポート - MCP サーバーコンポーネントと stdio トランスポート
- サーバーインスタンスを作成 - サーバーとその機能を定義
- ツールを定義 - 公開したい機能を追加
- トランスポートをセットアップ - stdio 通信を設定
- サーバーを起動 - サーバーを開始しメッセージを処理
ステップごとに作っていきましょう:
ステップ1: 基本的な stdio サーバーを作成
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# ロギングを設定する
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# サーバーを作成する
server = Server("example-stdio-server")
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
ステップ2: ツールを追加
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def calculate_product(a: int, b: int) -> int:
"""Calculate the product of two numbers"""
return a * b
@server.tool()
def get_server_info() -> dict:
"""Get information about this MCP server"""
return {
"server_name": "example-stdio-server",
"version": "1.0.0",
"transport": "stdio",
"capabilities": ["tools"]
}
ステップ3: サーバーの起動
コードを server.py として保存し、コマンドラインで実行します:
python server.py
サーバーが起動し、stdin からの入力を待機します。stdio トランスポート経由で JSON-RPC メッセージで通信します。
ステップ4: Inspector でのテスト
MCP Inspector を使ってサーバーをテストできます:
- Inspector をインストール:
npx @modelcontextprotocol/inspector - Inspector を起動し、サーバーを指定
- 作成したツールをテスト
.NET
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddMcpServer();
stdio サーバーのデバッグ
MCP Inspector の使用
MCP Inspector は MCP サーバーのデバッグとテストに役立つツールです。stdio サーバーでの使い方は以下の通り:
-
Inspector をインストール:
npx @modelcontextprotocol/inspector -
Inspector を実行:
npx @modelcontextprotocol/inspector python server.py -
サーバーをテスト:Inspector のウェブインターフェースで以下が可能です:
- サーバーの能力を表示
- パラメーターを変えたツールのテスト
- JSON-RPC メッセージの監視
- 接続問題の調査
VS Code の使用
VS Code でも直接 MCP サーバーをデバッグできます:
-
.vscode/launch.jsonに起動構成を作成:{ "version": "0.2.0", "configurations": [ { "name": "Debug MCP Server", "type": "python", "request": "launch", "program": "server.py", "console": "integratedTerminal" } ] } -
サーバーコードにブレークポイントを設定
-
デバッガーを起動し、Inspector でテスト
よくあるデバッグのヒント
- ログは
stderrに書き、stdoutには MCP メッセージのみを出力する - すべての JSON-RPC メッセージが改行区切りであることを確認
- 最初は単純なツールでテストし、複雑な機能は後から追加
- Inspector を活用してメッセージ形式を検証する
VS Code での stdio サーバーの利用
MCP stdio サーバーを作成したら、VS Code に統合して Claude などの MCP 対応クライアントで利用できます。
設定方法
-
%APPDATA%\Claude\claude_desktop_config.json(Windows) または~/Library/Application Support/Claude/claude_desktop_config.json(Mac) に MCP 設定ファイルを作成:{ "mcpServers": { "example-stdio-server": { "command": "python", "args": ["path/to/your/server.py"] } } } -
Claude を再起動:新設定を読み込むため Claude を閉じて再度開く
-
接続テスト:Claude と会話し、サーバーツールを試す:
- 「greeting ツールを使って挨拶してくれる?」
- 「15 と 27 の合計を計算して」
- 「サーバー情報を教えて」
TypeScript stdio サーバー例
参考のための完全な TypeScript 例:
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{
name: "example-stdio-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// ツールを追加する
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_greeting",
description: "Get a personalized greeting",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "Name of the person to greet",
},
},
required: ["name"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_greeting") {
return {
content: [
{
type: "text",
text: `Hello, ${request.params.arguments?.name}! Welcome to MCP stdio server.`,
},
],
};
} else {
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
.NET stdio サーバー例
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
var app = builder.Build();
await app.RunAsync();
[McpServerToolType]
public class Tools
{
[McpServerTool, Description("Get a personalized greeting")]
public string GetGreeting(string name)
{
return $"Hello, {name}! Welcome to MCP stdio server.";
}
[McpServerTool, Description("Calculate the sum of two numbers")]
public int CalculateSum(int a, int b)
{
return a + b;
}
}
まとめ
本レッスンでは以下を学びました:
- 現行の stdio トランスポート(推奨手法)を使った MCP サーバーの構築
- SSE トランスポートが stdio と Streamable HTTP に置き換えられた理由の理解
- MCP クライアントから呼び出せるツールの作成
- MCP Inspector を使ったサーバーデバッグ
- VS Code と Claude との統合方法
stdio トランスポートは、非推奨となった SSE アプローチと比較して、より簡単で安全かつ高性能に MCP サーバーを構築できる方法です。2025-06-18 仕様以降、ほとんどの MCP サーバー実装に推奨されています。
.NET
- まずはツールを作成しましょう。Tools.cs というファイルに以下の内容を記述します:
using System.ComponentModel;
using System.Text.Json;
using ModelContextProtocol.Server;
演習: stdio サーバーのテスト
stdio サーバーができたら、正しく動作するかテストしましょう。
前提条件
-
MCP Inspector がインストールされていること:
npm install -g @modelcontextprotocol/inspector -
サーバーコードが保存されていること(例:
server.py)
Inspector でのテスト
-
Inspector をサーバーで起動:
npx @modelcontextprotocol/inspector python server.py -
ウェブインターフェースを開く:Inspector はサーバーの能力を表示するブラウザウィンドウを開きます。
-
ツールをテスト:
get_greetingツールに様々な名前で呼び出しcalculate_sumツールに異なる数値を入力get_server_infoツールでサーバーメタデータ確認
-
通信状況を監視:Inspector でクライアントとサーバー間の JSON-RPC メッセージを確認
正常時に見るべき内容
サーバーが正しく起動していれば以下が見られます:
- Inspector に表示されたサーバーの能力
- テスト可能なツールの一覧
- 成功した JSON-RPC メッセージ交換
- インターフェースに表示されるツールの応答
よくある問題と対処法
サーバーが起動しない:
- 必要な依存関係 (
pip install mcp) がインストールされているか確認 - Python の構文・インデントをチェック
- コンソールのエラーメッセージを確認
ツールが表示されない:
@server.tool()デコレータがあるか確認- ツール関数が
main()実行前に定義されているか - サーバー設定が正しく行われているか確認
接続の問題:
- stdio トランスポートが正しく使われているか
- 他のプロセスとの干渉がないか確認
- Inspector のコマンド構文を見直す
課題
自分でサーバーの機能を拡張してみましょう。例えば このページ の API を呼び出すツールを追加したり、サーバーの形を自由に決めてください。楽しんで作ってみてください :)
解答例
解答例 動作するコードを含んだ一例です。
重要ポイント
この章での重要ポイントは以下の通りです:
- stdio トランスポートはローカル MCP サーバーに推奨される通信機構である
- stdio トランスポートにより MCP サーバーとクライアント間が標準入出力ストリームでシームレスに通信可能
- Inspector と Visual Studio Code の両方で stdio サーバーを直接利用でき、デバッグや統合が簡単に行える
サンプル集
追加リソース
次に学ぶこと
次のステップ
stdio トランスポートで MCP サーバーの作成方法を学んだので、次の応用トピックに進みましょう:
- 次へ: MCP の HTTP ストリーミング(Streamable HTTP) - リモートサーバー向けのもう一つのサポートトランスポートを学ぶ
- 応用: MCP セキュリティベストプラクティス - MCP サーバーのセキュリティ対策を実装
- 本番用: デプロイ戦略 - 本番環境向けサーバーのデプロイ方法
追加リソース
- MCP 仕様書 2025-11-25 - 公式仕様
- MCP SDK ドキュメント - 全言語向け SDK リファレンス
- コミュニティサンプル - コミュニティによる他のサーバー例
免責事項: 本書類は AI 翻訳サービス Co-op Translator を使用して翻訳されています。正確性を期していますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知おきください。原文の原語版が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。本翻訳の利用により生じたいかなる誤解や解釈違いについても、当方は責任を負いかねます。