MCP Task Orchestrator について
MCP Task Orchestrator は、複数エージェントや複数セッションでのコーディング作業を調整する開発者向け MCP サーバーです。作業項目と依存関係を保持し、プロンプトに頼らず、設定可能なワークフローゲートをサーバー側で適用します。
主な機能
- 01永続的な階層型作業項目グラフ
- 02サーバー側で適用するフェーズゲートと依存関係
- 03YAML ワークフロースキーマと再利用可能なトレイト
- 04担当者を記録する遷移・ノート履歴
- 05セッションのコンテキストと履歴の復元
活用シーン
- 01エージェントやセッションをまたいだコーディングタスクの調整
- 02必要なノートが揃うまで実装をブロック
- 03新しいセッションで現在の状態から作業を再開
MCP 対応
MCP クライアントに作業項目、ワークフロー、状態管理のツールを提供します。STDIO と HTTP に対応し、Claude Code プラグインも利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm -e DATABASE_PATH -e USE_FLYWAY -e AGENT_CONFIG_DIR -e MCP_TRANSPORT -e MCP_HTTP_PORT -e LOG_LEVEL -e LOG_FILE ghcr.io/jpicklyk/task-orchestrator:3.16.0DATABASE_PATHSQLite database file path (default: data/current-tasks.db)USE_FLYWAYEnable Flyway database migrations (default: true)AGENT_CONFIG_DIRDirectory containing .taskorchestrator/config.yaml for workflow schemas (default: working dir)MCP_TRANSPORTTransport mode: stdio (default) or httpMCP_HTTP_PORTHTTP port when using http transport (default: 3001)LOG_LEVELLogging level: DEBUG, INFO, WARN, ERROR (default: INFO)LOG_FILEOptional log file path. Unset (default) disables file logging; logs are always JSON on stderr.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/jpicklyk/task-orchestrator:3.16.0stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP Task Orchestrator
AI エージェントのワークフロー規律をサーバー側で強制します。
プロンプトベースのフレームワークは、LLM が指示に従うことを期待します。このツールは、従わなければ呼び出しをブロックします。
Task Orchestrator は、プロンプトではなくサーバーが品質ゲートを強制する、永続的な作業項目グラフを AI コーディングエージェントに提供する MCP サーバーです。マルチエージェントや複数セッションにまたがるコーディングワークフローを実行する開発者向けに作られています。オーケストレーターがサブエージェントに作業を割り当てる場合、前日の作業を新しいセッションが引き継ぐ場合、または自律的なループがバックログを処理する場合などに利用できます。Docker イメージとして提供され、あらゆる MCP クライアントで動作し、スキルやフックを追加するオプションの Claude Code プラグインも利用できます。
初めての方は、図解付きフィールドガイドから始めてください。 このページの考え方を、短いビジュアルページで解説しています。そのうちいくつかは操作可能で、フェーズゲートでトリガーを発生させたり、依存関係をたどりながら作業分解をクリックしたり、スキーマが解決される様子を確認したりできます。
課題
マルチエージェントのワークフローには、モデルが備えていないインフラストラクチャが必要です。オーケストレーターが複数のセッションにまたがってサブエージェントに作業を割り当てる際、作業開始前に必要なドキュメントを強制したり、どのエージェントがどの変更を行ったか追跡したり、作業分解における依存関係の順序を保証したりする組み込みの方法はありません。これらは構造上の課題であり、プロンプトではなくサーバーで対処するものです。
Task Orchestrator はこれらの機能をサーバーに実装します。必須の設計メモが記入されていない場合、advance は不足しているメモを示すエラーを返します。上流の依存項目が未完了の場合、遷移はブロックされます。すべての遷移とメモには、実行者が記録されます。新しいセッションでは、会話を再生する代わりに、1 回の呼び出しで状態全体を復元できます。また、ルールはハードコードされたプロンプトではなく YAML 設定なので、コードを変更せずに変更できます。
使用イメージ
Morning — new session, new agent, zero context:
Agent: items_read(select="context")
→ 2 items in work, 1 blocked, 1 stalled (missing implementation-notes)
Agent: items_read(select="history", since="2026-01-14T17:00:00Z")
→ Recent transitions show orchestrator-1 dispatched 3 sub-agents yesterday
Agent: advance(ops=[{ op: "transition", itemId: "a3f28c01", trigger: "start" }])
-> gate_blocked: "Item a3f28c01-... is missing 1 required notes." (detail.missing: requirements)
Agent: notes_write(ops=[{ op: "upsert", itemId: "a3f28c01", key: "requirements", role: "queue",
body: "Validate email format, enforce password complexity..." }])
-> results[0]: { ok: true, id: "...", version: 1, created: true }
Agent: advance(ops=[{ op: "transition", itemId: "a3f28c01", trigger: "start" }])
→ queue → work. Caller recorded. No context rebuilding.
クイックスタート
前提条件:Docker がインストールされ、実行されていること。
1. サーバーを登録する
最も簡単な設定は、セッションごとに STDIO コンテナを使う方法です。ポートもデーモンも REST API も必要ありません。プロジェクトの .mcp.json に追加します。
{
"mcpServers": {
"mcp-task-orchestrator": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "mcp-task-data:/app/data",
"ghcr.io/jpicklyk/task-orchestrator:latest"
]
}
}
}
Claude Code ユーザーは、代わりに CLI から同じ形式で登録できます。
claude mcp add-json mcp-task-orchestrator '{
"command": "docker",
"args": ["run", "--rm", "-i", "-v", "mcp-task-data:/app/data", "ghcr.io/jpicklyk/task-orchestrator:latest"]
}'
クライアントを再起動してください。サーバーは初回起動時に SQLite データベースを作成します。設定ファイルがなくても、すべてのツールはスキーマなしモードで動作し、ゲートも必須メモもありません。強制機能が必要になったら、スキーマを追加してください。
2. ワークフロースキーマを有効にする
プロジェクトに .taskorchestrator/config.yaml を作成し(例はワークフローの強制を参照するか、プラグインの /task-orchestrator:manage-schemas スキルを使用してください)、そのフォルダーをコンテナにマウントします。
{
"mcpServers": {
"mcp-task-orchestrator": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "mcp-task-data:/app/data",
"-v", "/absolute/path/to/your/project/.taskorchestrator:/project/.taskorchestrator:ro",
"-e", "AGENT_CONFIG_DIR=/project",
"ghcr.io/jpicklyk/task-orchestrator:latest"
]
}
}
}
サーバーは起動のたびに、マウントされたファイルをデータベースにインポートし(起動ステップの server-config-import)、保存されたコピーを配信します。ファイルの編集は、次回の再起動時に反映されます。複数のコンテナで同じデータボリュームを共有しながら異なるファイルをマウントすると、最後に起動したコンテナの設定が適用されます。複数プロジェクトで利用する場合は、手順 3 を使用してください。
ホスト側では絶対パスを使用してください。Claude Code の .mcp.json が展開するのは環境変数(${VAR} および ${VAR:-default})のみで、${workspaceFolder} のようなエディター形式のプレースホルダーは置き換えられません。公開されるのは .taskorchestrator/ フォルダーのみで、サーバーはプロジェクトの残りの部分にはアクセスできません。
3. マルチプロジェクトのセットアップ(HTTP + config-sync)
複数のリポジトリで作業する場合は、REST API を有効にした永続サーバーを 1 つ実行します。各プロジェクトの .taskorchestrator/config.yaml は、プラグインの config-sync フックを通じて自動的に同期されます。プロジェクトごとのコンテナも、手動のマウントも不要で、設定の変更は再起動なしでホットリロードされます。プラグインの /task-orchestrator:configure-server スキルを使うと、このセットアップを対話形式で生成できます。手動で設定する場合は、次のとおりです。
docker pull ghcr.io/jpicklyk/task-orchestrator:latest
docker run -d --name mcp-task-orchestrator-http --restart unless-stopped \
-v mcp-task-data:/app/data \
-e MCP_TRANSPORT=http -e API_ENABLED=true -e API_AUTH_MODE=none -e API_ALLOW_UNAUTHENTICATED=true \
-p 127.0.0.1:3001:3001 \
ghcr.io/jpicklyk/task-orchestrator:latest
HTTP 形式を使って .mcp.json に登録します。
{
"mcpServers": {
"mcp-task-orchestrator": {
"type": "http",
"url": "http://localhost:3001/mcp"
}
}
}
また、サーバーの場所を config-sync に伝えるクライアント側の変数をエクスポートします(設定しないと、config-sync は何もせずに終了します)。
export TASK_ORCHESTRATOR_API_URL=http://localhost:3001
あるいは、client.json(apiUrl のみで、トークンは不要)で URL を指定することもできます。プロジェクトモードの /task-orchestrator:init は、ループバックサーバーの場合に限り、パス、クエリ、フラグメントのない単一のオリジンとして、プロジェクト設定ファイルの隣にこのファイルを書き込みます(URL はマシン固有なので、.taskorchestrator/client.json を .gitignore に追加してください)。/task-orchestrator:init --user はユーザーレベルのファイルを書き込み、任意のホストで動作します。優先順位は、環境変数、プロジェクトレベルのファイル、ユーザーレベルのファイルの順です。/task-orchestrator:init は現在のディレクトリのプロジェクトルートを設定し、/task-orchestrator:init --user は個人用ルートを作成します。このルートは、独自の設定を持たないすべてのディレクトリに適用されます。
SECURITY: 認証なしのモード(REST と
/mcpの両方)では、ポートに接続できる人は誰でも、単一のlocalプリンシパルとして、完全な読み取り/書き込み/削除アクセス権を持ちます。これは、ポートがループバックのみに公開されている場合(-p 127.0.0.1:3001:3001)に限って安全です。0.0.0.0や、より広いインターフェイスでは絶対に公開しないでください。共有環境やネットワーク環境へのデプロイには、ベアラートークンまたは JWKS 認証を使用してください。詳しくは、Fleet Deployment を参照してください。
Docker を使わずに実行したい場合は、CONTRIBUTING.md でソースから fat JAR をビルドする方法を説明しています。
コア機能
フェーズモデル
すべての作業項目には 役割 があります。queue(未開始)、work(進行中)、review(任意。スキーマごとにオプトイン)、blocked(上流の依存関係が満たされていない)、terminal(完了またはキャンセル)です。各役割は、設定可能な 1 つ以上のステータスに対応します。エージェントはステータスを直接編集するのではなく、advance ツールの transition op を使って項目を移動します。すべてのゲートチェックはこの呼び出し時に行われます。スキーマでは役割にメモの要件を設定できます。たとえば、role: queue と宣言されたメモは、項目がキューフェーズを離れる前に存在している必要があります。
図解:Phase Gates では、役割とトリガーをトラックとして図示し、ゲートシミュレーターも備えています。
ワークフローの強制
スキーマでは、各フェーズでエージェントが作成すべき成果物を定義し、完了するまでサーバーが先への進行をブロックします。また、計画の最低要件も設定します。エージェントが計画モードに入ると、実装を開始する前に必要なドキュメントをスキーマが示し、計画の内容を形作ります。
# .taskorchestrator/config.yaml
work_item_schemas:
feature-task:
notes:
- key: requirements
role: queue
required: true
description: "Acceptance criteria before starting"
guidance: "Cover: problem statement, acceptance criteria, alternatives considered, test strategy."
skill: "spec-quality"
- key: implementation-notes
role: work
required: true
description: "What was built and why"
このスキーマでは、キューから trigger: "start" を指定して advance の transition を実行する際に、requirements が入力済みであることが求められます。サーバーは、不足しているメモを正確に列挙した gate_blocked エラーを返します。
guidance フィールドは、適切なタイミングで提示される作成手順を提供します。エージェントがそのメモを入力しようとすると、レスポンスで guidanceKey として名前が示されます(メモにスキル名が指定されている場合は skillPointer も含まれます)。また、items_read schema はそのテキストを返します。skill フィールドではさらに、メモの入力前にエージェントが呼び出すべきスキルを指定します。これにより、自由形式の文章ではなく、定義済みのフレームワークに沿って評価が行われます。
コンポーザブルな特性
特性を使うと、定義を重複させずに、あらゆるスキーマへ横断的なノート要件を追加できます。特性を一度定義し、任意のアイテムタイプに適用します:
traits:
needs-security-review:
notes:
- key: security-assessment
role: review
required: true
description: "Security review of auth, data handling, and access control"
skill: "security-review"
work_item_schemas:
feature-task:
default_traits:
- needs-security-review
notes:
# ... base notes
すべての feature-task アイテムは、自動的に security-assessment 要件を継承します。特性は items_write の create または update にある traits 配列で、アイテムごとに適用することもできます。そのため、認証に関わるタスクには needs-security-review が適用され、CSS の整理には適用されません。
図解:スキーマと特性では、タイプ、そのデフォルト特性、アイテムごとの特性がどのように解決されて、1つのゲートになるかを示します。シートでは、1つのフェーズを複数のエージェントに分割する方法を説明します。
永続的な作業アイテムグラフ
すべてが階層グラフ内の WorkItem です。アイテムは深さの制限なく入れ子にでき、型付きの依存関係エッジで接続されます。作業の内訳全体をアトミックに作成します:
{ "ops": [{
"op": "create_tree",
"root": { "title": "User Authentication", "type": "feature-task" },
"children": [
{ "ref": "schema", "title": "Database schema", "type": "feature-task" },
{ "ref": "api", "title": "Login API", "type": "feature-task" },
{ "ref": "tests", "title": "Integration tests", "type": "feature-task" }
],
"deps": [
{ "from": "schema", "to": "api" },
{ "from": "api", "to": "tests" }
]
} ] }
(オーケストレーションプロファイルの items_write。)
schema が終端状態になると、api のブロックは自動的に解除されます。すべての子アイテムが完了すると、auto ライフサイクルの親アイテムは終端状態へと連鎖的に移行します(review 状態の親アイテムは明示的な進行が必要です)。依存関係の順序は慣習ではなく、構造としてサーバーによって適用されます。
図解:作業グラフには、このツリーをクリックして操作できるバージョンがあり、ブロック、ブロック解除、親アイテムへの連鎖的な反映を示します。
実行者の帰属
すべての書き込みには、トランスポートプリンシパルが帰属します。これは、サーバーが接続方法から判断する呼び出し元であり、リクエスト内のフィールドで指定されるものではありません。Bearer または JWT 認証情報では、その所持者が識別されます(api:<id>)。stdio と、認証情報モードなしの HTTP は、単一の local プリンシパルとして実行されます。リクエスト本文の actor は unknown_parameter として拒否されます。
notes_read と items_read の history エントリには、(参照が許可されている呼び出し元について)その帰属情報が含まれます。どのノートを誰が書いたか、どの遷移を誰が行ったかを確認できます。事後デバッグは、会話の掘り起こしではなくデータクエリで行えるようになります。
エージェントを区別するには、それぞれに独自の認証情報を割り当てます(または、実行中であれば独自のシートトークンを割り当てます)。API_AUTH_MODE=bearer または jwks で REST API を有効にすると、/mcp は同じトークンで認証します。stdio またはローカルモードのセッションはすべて同じ local プリンシパルとなるため、それらのセッションではクレームとノートの所有権が共有されます。フリートのデプロイを参照してください。
セッションの継続性
コンテキストを再構築する必要はありません。1回の呼び出しで全体像を取り戻せます:
{ "select": "context" }
{ "select": "history", "since": "2026-01-15T09:00:00Z" }
(items_read。)1つ目は、アクティブなアイテム、ブロックされているアイテム、不足しているノートとクレームの概要を含む停滞中のアイテムを返します。2つ目は、実行者の帰属情報を含む最近の遷移を返します。祖先チェーンを取得するには "fields": ["ancestors"] を追加します。新しいセッションでも、2つの短いレスポンスで完全な状態を把握できます。
図解:作業の検索では、セッションで生じる各質問に答える読み取り呼び出しを対応づけ、次のアイテムがどのように順位付けされるかを示します。
構造化コンテキストとしてのノート
ノートは、作業アイテムに添付されるフェーズ固有のドキュメントです。実装エージェントは、プロジェクトの広範なコンテキストを調べる代わりに、自分のタスクに絞られた簡潔な要件ノートを読みます。
ノートはキーとロールでスコープが設定され、クエリで取得できます:
{ "select": "list", "itemId": "a3f28c01", "role": "work" }
(notes_read。)リストではメタデータのみ(id、key、role、version、bodyLength)が返されるため、エージェントはすべてのノート本文を読むトークンコストをかけずに、何が存在するかを確認できます。get では1つの本文を読み取ります。
全文検索
キーワードで作業アイテムとノートを検索できます。結果は関連度順に並ぶため、関連する作業を探す場合や、長い中断後に作業を再開する場合、エージェントは最も一致度の高い結果から確認できます。
{ "select": "search", "query": "authentication login", "kinds": ["item"] }
{ "select": "search", "query": "password validation", "kinds": ["note"] }
(items_read。)
検索対象をサブツリーに限定し、ロール、タグ、優先度で絞り込むことも、ワークスペース全体を検索することもできます。
REST API
オプションの HTTP レイヤー(API_ENABLED=true)では、すべてのツールを単一の RPC ルート(POST /api/v1/ops/{tool})経由で提供するほか、アイテムとノートのリソース取得、リース管理、サービスメタデータ、リアルタイムの SSE イベントをダッシュボード、CI システム、運用担当者向けに提供します。静的ベアラートークン、JWKS JWT 認証、およびクイックスタートに示されている認証なしのループバックモードをサポートしています。また、config-sync にも使用され、1 つのサーバーでプロジェクトごとのスキーマを使って複数のプロジェクトに対応できます。REST API リファレンスをご覧ください。
図解:ランタイムマップでは、サーバーのレイヤー、2 種類のデプロイ形態、REST API、クレーム、アクターの ID について説明しています。
設計理念
Task Orchestrator は、特定の手法を押し付けることなく、ワークフローの構造を強制します。ガードレールを管理するのはサーバーです。役割の遷移、依存関係の順序、ゲートの適用、実行者の記録を担います。それ以外はすべてエージェントが担います。必須の計画セレモニーはなく、エージェントの実装方法に関する意見もありません。スキーマ、特性、アクター認証は、.taskorchestrator/config.yaml で設定するオプトインのレイヤーです。モデルの能力が向上しても、ハーネスが邪魔になることはありません。
Claude Code プラグイン
このプラグインは、MCP サーバー上にワークフロー自動化を追加します。スキル、フック、オーケストレーションコンテキストが含まれます。
インストール:
/plugin marketplace add https://github.com/jpicklyk/task-orchestrator
/plugin install task-orchestrator@task-orchestrator-marketplace
追加される機能:
| レイヤー | 機能 |
|---|---|
| スキル | /task-orchestrator:quick-start、/task-orchestrator:init、/task-orchestrator:configure-server、/task-orchestrator:manage-schemas、/task-orchestrator:create-item など、一般的なワークフロー向けのスラッシュコマンド |
| フック | セッション開始時のコンテキスト注入、計画モードとの統合、サブエージェントへのコンテキスト引き継ぎとフェーズゲートの適用、プロジェクトごとの設定同期、実行終了時の振り返りプロンプト |
| オーケストレーションコンテキスト | SessionStart フックがオーケストレーションのコアを提供します(階層と委任の詳細は orchestrate スキルを参照)。Claude はコードを直接書かずに、計画を立て、サブエージェントに委任し、進捗を追跡します |
| ディレクターモード | /task-orchestrator:director は、オープンな実行、決定、集約で構成されるボードとしてセッションを実行します。ガードフックがコードへの介入を防ぎ、すべての読み取りをコーディネーターに委任します |
| 実行 | /task-orchestrator:run-wave と /task-orchestrator:ralph は席ごとのトークンを使ってサーバー上で実行を開始します。実行を終了すると、その振り返りが開始されます |
MCP サーバーはプラグインなしでも動作します。プラグインを使うと、Claude Code との連携がシームレスになります。
オプションの拡張(早期アクセス): task-orchestrator-mod は、プロセス内関数フックを備えた、別個のオプトイン型プラグインです。ライブワークグラフペイン、進行中のバンドとステータス行、プロセス内の振り返り、フェーズガード、呼び出し形状フックを提供します。早期アクセス版 Claude Code API に依存するため、最新の task-orchestrator プラグインと組み合わせることをおすすめします。
/plugin install task-orchestrator-mod@task-orchestrator-marketplace
図解:実行のオーケストレーションでは、1 つの機能がリクエストからアイテムの完了に至るまでを追います。改善ループでは、作業中に気づいた摩擦が、レビュー済みの設定変更に至るまでを示します。
MCP ツール
| カテゴリー | ツール | 目的 |
|---|---|---|
| 項目 | items_read, items_write | 作業項目の階層の読み取り、検索、要約、次の項目の特定、ゲートの状態と遷移履歴の確認(items_read が選択します);作成、更新、削除、ツリー全体の作成、ツリーの完了、再ピン留め(items_write の操作) |
| ノート | notes_read, notes_write | フェーズごとにスコープが設定された永続的なドキュメント。バージョン管理され、一括書き込みに対応しています |
| 依存関係 | deps_read, deps_write | パターンのショートカット(linear、fan-out、fan-in)とブロッキンググラフに対応した型付きエッジ |
| ワークフロー | advance | ゲートの適用と依存関係の検証を伴うトリガーベースの遷移、およびマルチエージェントフリート向けの claim、release、heartbeat 操作 |
| ドキュメント | docs_read, docs_write | プロジェクトのルートごとにバージョン管理された計画、ルール、ページのドキュメント |
| プロジェクト設定 | config | プロジェクトごとのスキーマ設定とルールテキストのプッシュ、検証、ロールバック、確認 |
各ツールは単一のレスポンスエンベロープを返します。また、任意の呼び出しで describe: true を指定すると、そのツールのスキーマが返されます。knowledge プロファイル(/mcp/knowledge、または stdio で MCP_TOOL_PROFILE=knowledge)では、オーケストレーションを含まない、より小規模な読み取り/書き込みのサブセットを利用できます。director プロファイル(/mcp/director、または MCP_TOOL_PROFILE=director)では、項目と依存関係の読み取りに加え、report ツールのみを利用できます。項目 ID には短い 16 進数のプレフィックスを使用できます。プレフィックス(8~32 桁の 16 進数)が一意であれば、完全な UUID の代わりに itemId="a3f28c01" を使用できます。3.x からアップグレードしますか?変更履歴の「Upgrading from 3.x」をご覧ください。各ツールのパラメーターとレスポンスの形式については、API リファレンスをご覧ください。
ドキュメント
| リソース | 内容 |
|---|---|
| フィールドガイド | コアとなる概念を図解で紹介する、一部インタラクティブなガイドです。最初に読むのに最適です。 |
| クイックスタートガイド | 最初の作業項目を含む、セットアップの詳細なガイドです |
| API リファレンス | すべての MCP ツールのパラメーター、レスポンスの形式、実行者の帰属情報 |
| REST API リファレンス | RPC ルート、リソース GET、リース管理、SSE、認証、ETag |
| ワークフローガイド | スキーマ、フェーズゲート、依存関係、ライフサイクルモード |
| フリートのデプロイ | マルチエージェント運用者向け:REST と /mcp の認証、呼び出し元 ID、ヘルスチェック、SQLite のチューニング、キャパシティプランニング |
| Wiki | ドキュメントの総合ハブ |
| 変更履歴 | リリース履歴 |
| コントリビューション | 開発環境のセットアップとコントリビューションの手順 |
技術スタック
- Kotlin と Coroutines
- SQLite + Exposed ORM:FTS5 全文検索を備え、設定は不要です
- Flyway によるバージョン管理されたスキーママイグレーション
- MCP Kotlin SDK:STDIO および Streamable HTTP トランスポート
- REST API と SSE 用の Ktor
- ワンコマンドでのデプロイに対応する Docker
レイヤードアーキテクチャ(Domain → Application → Infrastructure → Interfaces。Konsist のレイヤリングテストとパッケージ循環テストで適用され、どちらもベースラインは空です)を採用し、JUnit 5 による広範なテストスイートを備えています。
ライセンス
MIT ライセンス — 個人利用および商用利用は無料です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。