JobMojito について
JobMojito の MCP サーバーは、AI クライアントから採用面接、ペルソナを使った評価、コーチングセッションを利用できるようにします。候補者や結果の管理、ドキュメント検索、ワークスペース分析も認証付き API ツールとして提供します。
主な機能
- 01面接とペルソナセッションの作成
- 02コーチングカタログでの練習
- 03候補者とセッション結果の管理
- 04最新の製品ドキュメント検索
- 05マーチャント一覧と分析の参照
活用シーン
- 01職務記述から採点式の採用面接を準備
- 02顧客シナリオへの対応を練習
- 03文字起こしと構造化された分析を確認
MCP 対応
JobMojito API のエンドポイントを MCP ツールとして公開し、開発者向けドキュメントやヘルプセンターのライブ検索ツールも備えます。ユーザーは Supabase OAuth で認証し、その JWT が API に転送されます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://mcp.jobmojito.com/mcpclaude mcp add --transport http com-jobmojito-jobmojito https://mcp.jobmojito.com/mcp{"mcpServers":{"com-jobmojito-jobmojito":{"type":"http","url":"https://mcp.jobmojito.com/mcp"}}}Cursor で開く{"servers":{"com-jobmojito-jobmojito":{"type":"http","url":"https://mcp.jobmojito.com/mcp"}}}VS Code で開く{"mcpServers":{"com-jobmojito-jobmojito":{"type":"http","url":"https://mcp.jobmojito.com/mcp"}}}{"mcpServers":{"com-jobmojito-jobmojito":{"serverUrl":"https://mcp.jobmojito.com/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
29| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| limit | integer | いいえ | ソースごとの最大結果数(1~25)。 |
| query | string | はい | 自然言語の検索クエリまたはキーワード。 |
| source | string | いいえ | 検索対象を限定するには、"all"(デフォルト)、"developer"、または "help" を指定します。 |
| conversation_id | string | いいえ | サーバーの直前の応答に含まれる正確な conversation_id を変更せずに渡してください。サーバーは最初の呼び出しでこれを提供します。決して捏造せず、値を取得するまではツールを並列呼び出ししないでください。その後のユーザーメッセージや別のタスクの後も含め、会話中は同じ conversation_id を渡し続けてください。ユーザーが新しいリクエストを開始してもリセットしないでください。 |
詳細
JobMojito MCP サーバー
はじめに
JobMojito では、AI が主導する対話セッションを 3 種類提供しています。それぞれの違いは重要です。1 つのツールで、そのうち 2 種類を作成できるためです。
- 面接 — 採用向けの、スコア付きの質疑応答です。職務記述書から質問を生成することも、独自の質問を用意することもできます。音声のみの面接官、ライブ動画アバター、または録画済みのアバターを使って、30 以上の言語で実施でき、候補者向けの体験全体をブランドに合わせてカスタマイズできます。
- シミュレーションペルソナ — 質問リストの代わりに、アバターが懐疑的な購入者、怒っている顧客、対応の難しいステークホルダーといった、設定された人物を演じて自由形式で会話し、その対応力をスコア化します。面接と同じ招待、請求、結果のフローを使うため、採用担当者の結果一覧にほかの結果と並んで表示されます。
- コーチング — 同じペルソナエンジンを、評価ではなく練習に使用します。学習者は閲覧可能なカタログから自分でセッションを開始し、個人のコーチング時間から秒単位で支払い、結果は採用担当者には共有されず非公開のままです。ディレクトリ、タグフィルター、Markdown ページを使って整理できます。
注意点が 1 つあります。
create_personaは 2 番目と 3 番目のプロダクトの両方を作成します。どちらになるかはportal引数で選択しますが、デフォルトはcoachingです。評価やスクリーニングに使う場合は、必ずportal="interview"を明示してください。そうしないと、誤ったプロダクトが作成され、クレジットの請求先が間違い、採用担当者には表示されません。
3 種類すべてで、候補者を一括登録してそれぞれに個別リンクを発行し、AI が参照するドキュメントをナレッジベースにアップロードし、文字起こし、構造化された分析、共有可能な HTML または PDF レポートを確認できます。また、マーチャントとサブマーチャントにわたるワークスペース、クレジット、分析データを管理できます。
プラットフォームが提供するのは、資格を持つ人間のレビュー担当者による意思決定を支援する情報です。採用の決定そのものを行うことは決してありません。また、候補者にはプロセスに AI が関与することを伝えます。
プロダクト関連のリンク:管理コンソールは app.jobmojito.com、開発者向け/API ドキュメントは developer.jobmojito.com、ヘルプセンターは help.jobmojito.com、このリポジトリが提供するホスト型 MCP エンドポイントは https://mcp.jobmojito.com/mcp です。
このリポジトリは、これらすべての機能を Claude や ChatGPT などの AI アシスタントで利用できるようにする MCP サーバーです。
FastMCP で構築され、Prefect Horizon(FastMCP チームが提供する MCP プラットフォーム。app.prefect.cloud → Horizon)へのデプロイを想定した、JobMojito API 用の MCP サーバーです。
以下を提供します。
- JobMojito の最新 OpenAPI 仕様から自動生成される 32 個の API ツール(面接、シミュレーションペルソナ、コーチングカタログ、候補者と結果、ナレッジベース、マーチャント一覧/分析データ、カスタムレポート)。
GETの一覧取得を含むすべてのエンドポイントが、整理された名前のツールとして公開され、それぞれにタイトルと読み取り専用/破壊的操作のアノテーションが付与されます。 - 開発者向けドキュメントとヘルプセンターをリアルタイムで参照する 2 つのドキュメントツール(
search_documentation、get_documentation)。ドキュメントは既存の各プラットフォームを唯一の情報源として維持し、このリポジトリにはコピーしません。 - Supabase OAuth。これにより、エンドユーザーは Claude、ChatGPT などから直接ログインできます。サインインしたユーザーの Supabase JWT は、呼び出しのたびに JobMojito API に転送されます。
仕組み
MCP client (Claude / ChatGPT)
│ OAuth login (Supabase OAuth Server, DCR)
▼
JobMojito MCP server (this repo, on Horizon)
│ forwards the user's Supabase JWT
▼
JobMojito API (https://cool.jobmojito.com/functions/v1)
| 項目 | 方法 |
|---|---|
| API → ツール | FastMCP.from_openapi(...) を使用し、すべてのルートをツールにマッピングします。operationId を挿入して、厳選した名前を設定します |
| 仕様の最新性 | 起動時にライブで取得します。実行時キャッシュとコミット済みスナップショットをフォールバックとして使用します |
| 認証 | SupabaseProvider(リモート OAuth)。リクエストごとに JWT を上流 API に転送します |
| ドキュメント | developer.jobmojito.com/llms.txt と .md、および help.jobmojito.com(Featurebase)のヘルプセンターを読み込む組み込みツール |
ファイル
| ファイル | 目的 |
|---|---|
server.py | エントリポイント — mcp を構築して公開します(Horizon で server.py:mcp を指定してください) |
config.py | 環境変数で制御する設定 |
openapi_loader.py | ライブ取得とキャッシュ/スナップショットへのフォールバック、および operationId の挿入 |
naming.py | エンドポイントごとに厳選したツール名、タイトル、ヒント、注釈 |
upstream.py | ユーザーの Supabase JWT を API に転送する httpx クライアント |
middleware.py | 呼び出しログ、上流エラーの書き換え、結果サイズの制限、注釈の補完 |
merchants.py | マーチャント選択ツール(MCP App UI)と list_my_merchants のテキストフォールバック |
docs_tools.py | search_documentation / get_documentation |
featurebase.py | Featurebase REST クライアント(ヘルプセンターの記事) |
mintlify.py | Mintlify 開発者向けドキュメントの MCP プロキシとクライアント認証情報による認証 |
tests/ | test_smoke.py(インベントリ、スキーマの緩和、ドキュメント)と test_listing_readiness.py(ディレクトリの要件) |
docs/ | 開発者向けドキュメント:アーキテクチャ、開発、デプロイ |
scripts/update_snapshot.py | コミット済みのフォールバック仕様を更新 |
scripts/try_docs.py | ドキュメントツールのローカルスモークテスト |
data/openapi.snapshot.json | オフライン用のフォールバック仕様(お使いのマシンから再生成してください) |
lazy_auth.py | 未認証での機能検出と、401 チャレンジでの scope= |
wellknown.py | /healthz、OpenAI ドメインチャレンジ、Smithery サーバーカード |
server.json | 公式 MCP Registry エントリ |
.github/workflows/publish-registry.yml | main へのプッシュで server.py:SERVER_VERSION が変更されたとき(または手動実行時)に、server.json を MCP Registry に公開します |
ローカルでの開発とテスト(macOS)
# 1. Set up a virtualenv and install deps
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# 2. Configure secrets in .env (auto-loaded; gitignored)
cp .env.example .env # then fill in your keys/credentials
# 3. Static check — see exactly what Horizon will deploy
fastmcp inspect server.py:mcp
# 4. Run the unit tests (offline; uses the snapshot fallback)
ENABLE_AUTH=false pytest -q --asyncio-mode=auto
# 5. Smoke-test the docs tools live (Featurebase + Mintlify federation)
ENABLE_AUTH=false python scripts/try_docs.py "how do I create an interview"
# 6. Run the server and connect a client
ENABLE_AUTH=false python server.py # → http://localhost:8000/mcp
# then, in another terminal, open the MCP Inspector:
npx @modelcontextprotocol/inspector
# transport: "Streamable HTTP", URL: http://localhost:8000/mcp
テストに関する注意事項:
- ドキュメントツール(
search_documentationと、マウントされた Mintlify のsearch_*_developer_*/query_docs_filesystem_*)はENABLE_AUTH=falseで動作します。 Supabase へのログインは不要です。最も手早く確認するにはscripts/try_docs.pyを実行してください。 - API ツール(
create_interview、list_candidates、…)は実際の JobMojito API を呼び出すため、Supabase ユーザートークンが必要です。ローカルでテストするには、.envでJOBMOJITO_DEV_BEARER_TOKENに有効な Supabase アクセストークンを設定してください。これはENABLE_AUTH=falseの場合に転送されます。(本番環境では絶対に設定しないでください。本番環境では ユーザーの OAuth セッションからトークンを取得します。) - ローカルでの完全な OAuth が必要になることはほとんどありません。必要な場合は、
ENABLE_AUTH=trueで実行し、BASE_URL=http://localhost:8000を設定して、 OAuth に対応したクライアントを接続してください(Supabase を経由して認証が行われます)。
フォールバックのスナップショットを更新するには、API に接続できるネットワークから
python scripts/update_snapshot.pyを実行してください(このリポジトリにコミット済みのスナップショットは 構造を示すための簡易フォールバックです。この操作で完全なライブ仕様に置き換えられます)。
Supabase OAuth の設定
このサーバーでは Supabase の OAuth Server 機能を使用します(Dynamic Client Registration をサポートしているため、MCP クライアントが自分で登録します)。MCP サーバーは OAuth の リソースサーバー であり、トークンを検証します。トークンを発行するのは Supabase です。
プロジェクト: https://momsbvnltsydezmoesqt.supabase.co
SupabaseProvider は、このプロジェクト URL からすべてのエンドポイントを導出します。
| エンドポイント | URL |
|---|---|
| 認可 | …/auth/v1/oauth/authorize |
| トークン | …/auth/v1/oauth/token |
| JWKS | …/auth/v1/.well-known/jwks.json |
| OIDC ディスカバリー | …/auth/v1/.well-known/openid-configuration |
手順:
- Supabase Dashboard → Authentication → OAuth Server
- OAuth Server と Allow Dynamic OAuth Apps を有効にします
- Site URL:
https://app.jobmojito.com - Authorization Path:
/oauth/consent
- 環境変数:
SUPABASE_PROJECT_URL=https://momsbvnltsydezmoesqt.supabase.co、BASE_URL=https://mcp.jobmojito.com(公開ベース URL。/mcpは付けません)、SUPABASE_JWT_ALGORITHM=ES256(JWKS に RSA キーが表示される場合はRS256に切り替えます)。 - JobMojito Edge Functions が
apikeyヘッダーを必要とする場合は、SUPABASE_ANON_KEYを設定します。
同意の処理は Supabase またはアプリが行い、このサーバーは行いません。 Site
URL が app.jobmojito.com のため、Supabase は承認/拒否画面を
https://app.jobmojito.com/oauth/consent で表示します。この画面では、ユーザーはすでに Supabase
セッションにログインしています。この MCP サーバーは OAuth リソースサーバーのみを担い、同意ページは表示しません。SITE_URL と OAUTH_CONSENT_PATH は参考情報であり、Supabase OAuth Server の設定と一致させてください。
トークンに関する注意:
SupabaseProviderはトークンの audience を検証できません(Supabase Auth はまだ RFC 8707 のリソースインジケーターを実装していません)。これは想定どおりの動作であり、起動時にログへ記録されます。
認証モデル
すべてのツールの 呼び出し で、ユーザーが Supabase OAuth にサインインしている必要があります —
search_documentation と get_documentation も対象です。ENABLE_AUTH=true のままにしてください。
サインインしたユーザーのトークンは JobMojito API に転送されるため、呼び出しにはそのユーザーの権限が適用されます。
意図的に設けられた唯一の例外は、機能の検出 です。ENABLE_LAZY_AUTH
(デフォルトは true)が有効な場合、initialize、ping、および */list メソッドはトークンなしで応答し、ディレクトリーのクローラーがツール一覧を表示できます。この方法でデータにアクセスすることはできません。すべての tools/call、リソースの読み取り、プロンプトには、引き続き検証済みの JWT が必要です。
Prefect Horizon へのデプロイ
- このリポジトリーを GitHub にプッシュします。
- horizon.prefect.io にアクセスし、GitHub でサインインして、このリポジトリーを選択します。
- 次の項目を設定します。
- Entrypoint:
server.py:mcp - Dependencies:
requirements.txtから自動検出 - Horizon Authentication: off — このサーバーは独自の Supabase OAuth を提供するため、これを認証レイヤーとして使用します。
- Entrypoint:
- 環境変数/シークレットを設定します。
ENABLE_AUTH=trueBASE_URL=https://mcp.jobmojito.com— 重要です。 これはサーバーの 公開ベース URL であり、/mcpも末尾のスラッシュも付けません。SupabaseProviderが OAuth リソースとして通知する URL です。デフォルトのhttp://localhost:8000のままにすると、クライアントは401 invalid_tokenを受け取ります。起動ログにはbase_url=…が出力され、localhost の場合は警告が表示されます。SUPABASE_PROJECT_URL=https://momsbvnltsydezmoesqt.supabase.co- Edge Functions が
apikeyヘッダーを必要とする場合はSUPABASE_ANON_KEY。 - ヘルプセンターのドキュメント用に
FEATUREBASE_API_KEY。
- デプロイします。 MCP エンドポイントは
https://mcp.jobmojito.com/mcpです。Horizon はmainへのプッシュごとに再デプロイします。
ログインのテスト
initialize での 401 は、MCP OAuth の通常の最初のステップです。クライアントはディスカバリーメタデータを読み取り、Supabase ログインを実行することを想定しています。Horizon のInspector / ChatMCP はこのログインを実行しないため、単に 401 が表示されます。https://mcp.jobmojito.com/mcp をClaude.ai のカスタムコネクターとして追加してテストしてください。完全な OAuth フローが実行され、Supabase ログインが求められます。
Supabase 側が設定されていることを確認してください(設定されていないと、いずれにせよフローは 401 になります)。OAuth Server と Dynamic Client Registration を有効にし、Site URL を https://app.jobmojito.com、Authorization Path を /oauth/consent に設定してください。また、同意ページをアプリ上でホストしてください。
OpenAPI 仕様は起動時にライブで取得されるため、再デプロイのたびに最新の JobMojito API が自動的に反映されます。
ドキュメントを単一の情報源で管理する
ドキュメントはここに複製していません。search_documentation はライブインデックスを構築し、get_documentation は必要に応じてページを取得します。どちらもソースプラットフォームを直接読み込みます。そこでドキュメントを編集すると、キャッシュ TTL(DOCS_CACHE_TTL_MINUTES、デフォルトは 60 分)以内に MCP に変更が反映されます。
| ソース | 読み込み方法 | 認証情報 |
|---|---|---|
developer.jobmojito.com(Mintlify) | クライアント認証情報が設定されている場合、このサーバーにマウントされたMintlify MCP(セマンティックな search と query_docs_filesystem。インポートされた OpenAPI を含む)を使用します。未設定の場合は、組み込みツール経由で公開の llms.txt/.md を読み込みます | MCP クライアント ID/シークレット(フェデレーション用) |
help.jobmojito.com(Featurebase) | FEATUREBASE_API_KEY が設定されている場合はREST API(本文を含む構造化された記事)を使用し、未設定の場合は公開 HTML をスクレイピングします | API キー(任意) |
このサーバーと Mintlify の両方を使う理由
Mintlify は OpenAPI をインポートしますが、その MCP は読み取り専用のドキュメント機能です。エージェントは API リファレンスを検索して読むことができますが、API を呼び出すことはできません。このサーバーは同じ OpenAPI から、認証済みで呼び出し可能なツールを作成します(サインイン中の Supabase ユーザーとして動作します)。つまり、Mintlify は「どのように動作するのか」に答え、このサーバーは「実際に処理する」という役割を担います。フェデレーションでは、Mintlify のドキュメント検索ツールをアクションツールと並べてマウントするため、エンドユーザーは 1 つのコネクターから両方を利用できます。
開発者向けドキュメント:Mintlify フェデレーション
developer.jobmojito.com は Mintlify サイトで、MCP は search と query_docs_filesystem のツール(インポートされた OpenAPI を含む)を公開します。このサーバーはこれをプロキシとしてマウントします。フェデレーションが有効になると、重複を避けるため、組み込みの developer-llms.txt ソースは無効になります。
デフォルトで公開(認証情報不要)。 Mintlify は /mcp で公開 MCP を提供します。開発者向けドキュメントは公開されているため、DEVELOPER_DOCS_MCP_URL はデフォルトで https://developer.jobmojito.com/mcp に設定され、認証なしでマウントされます。そのまま利用できます。
認証済みエンドポイント(任意)。 Mintlify は、グループ制限コンテンツ向けにOAuth クライアントクレデンシャルを使用する /authed/mcp エンドポイントも提供しています。デフォルトでは有効になっていません。サイトの /.well-known/mcp には、有効にするまで public サーバーのみが広告されます。利用するには、次の手順を実行してください。
- Mintlify ダッシュボード → MCP server page → Enable MCP Server(有効にしないと
/authed/mcp/oauth/tokenが 404 を返します)。 - そこでクライアント認証情報を作成し(MCP クライアント認証情報。Mintlify API キーではありません)、
DEVELOPER_DOCS_MCP_CLIENT_ID/_CLIENT_SECRETを設定します。 DEVELOPER_DOCS_MCP_URL=https://developer.jobmojito.com/authed/mcpを設定します。
URL に /authed が含まれ、かつ両方の認証情報が設定されている場合にのみ認証が付与されます。その後、サーバーは {url}/oauth/token で認証情報を交換し、トークンをキャッシュ/更新します。
Featurebase:認証情報の見分け方
Featurebase はドキュメントを 3 つの方法で提供しており、認証情報の形式で見分けられます。
- REST API → 単一の API キー(
Authorization: Bearer <key>とX-API-Keyとして送信)。ベース URL はhttps://do.featurebase.appです。Featurebase ダッシュボードで作成します。auth.featurebase.app/choose-org からログインし、Settings → Advanced → API に進んでキーをコピーしてください。(直接/settings/apiにアクセスすると 404 になります。まず組織を選択する必要があります。)このサーバーではヘルプセンター用に使います (FEATUREBASE_API_KEYを設定してください)。 - Hosted MCP(
mcp-read.featurebase.app、「Reader」コネクター)→ 対話型 OAuth(認可コード + PKCE、クライアントシークレットなし)。Claude/ChatGPT で人間が「接続」をクリックするよう設計されています。このサーバーを経由させるのではなく、AI クライアントのコネクターとして直接追加するのが最適です(マシントークン/クライアントクレデンシャルグラントがありません)。 - 公開ウェブ →
llms.txt/.md(開発者向けドキュメント)、認証不要。
Client ID + Client secret のペアは、Featurebase のドキュメント用認証情報ではありません。 REST API(API キー)でも MCP(PKCE、シークレットなし)でも、この形式は使いません。 そのペアをお持ちの場合、Featurebase の SSO/ID 管理用 OAuth アプリ、または別のシステムのものと思われます。ドキュメントには、上記の REST API キーを使用してください。
Featurebase Reader MCP(フェデレーションなし)
Mintlify とは異なり、Featurebase Reader MCP(mcp-read.featurebase.app)は対話型 OAuth(クライアントクレデンシャルには非対応)のみをサポートしているため、ここにはマウントされていません。ネイティブ検索を利用するには、AI クライアントのコネクターとして直接追加してください。
HELP_DOCS_MCP_URL は参照用として設定に残されています。
ディレクトリーの掲載と見つけやすさ
このサーバーは、コードを変更せずに Anthropic コネクターディレクトリー、OpenAI プラグインディレクトリー(ChatGPT + Codex)、公式 MCP Registry の要件を満たすように構築されています。具体的には次のとおりです。
| 要件 | 設定箇所 |
|---|---|
すべてのツールに title と readOnlyHint/destructiveHint があり、根拠が記述されている | naming.py::TOOL_META。server.py::_customize_component によって適用され、middleware.ToolMetadataBackfillMiddleware によって補完されます |
| 読み取りと書き込みは別々のツール(包括的なツールはなし) | naming.py — tests/test_listing_readiness.py で検証 |
認証情報なしで tools/list が動作し、クローラーがツール一覧を表示できる | lazy_auth.py |
保護されたリソースのメタデータに scopes_supported があり、401 に scope= が付く | server.py::_build_auth + lazy_auth.WWWAuthenticateScopeMiddleware |
| そのままの 4xx/5xx ではなく、対応可能なエラーメッセージを返す | middleware.UpstreamErrorMiddleware |
| 結果がクライアントのサイズ上限を超えない | middleware.ResultSizeGuardMiddleware |
| 稼働時間監視用のヘルスプローブ | GET /healthz |
| OpenAI ドメインの検証 | GET /.well-known/openai-apps-challenge(OPENAI_APPS_CHALLENGE_TOKEN を設定) |
| MCP Registry のエントリー | server.json + 公開ワークフロー |
送信時に OpenAI が求める注釈の根拠を生成します。
python -c "import naming,json;print(json.dumps(naming.annotation_justifications(),indent=2))"
デプロイまたはホスト名の変更後は、公開 ID を検証してください。これは、正常に稼働しているサーバーがすべてのクライアントに 401 を返す原因として、最もよくあるものです。
curl -s https://mcp.jobmojito.com/.well-known/oauth-protected-resource/mcp
# "resource" MUST equal "https://mcp.jobmojito.com/mcp"
curl -s https://mcp.jobmojito.com/healthz
掲載先
| ディレクトリー | 状況 |
|---|---|
Official MCP Registry(com.jobmojito/jobmojito) | 公開済み — publish-registry.yml は、git タグではなく、main 上で server.py:SERVER_VERSION が変更されたときに実行されます。Registry のバージョンは変更できないため、説明を変更するにはバージョンを上げる必要があります。 |
| OpenAI プラグインディレクトリー(ChatGPT + Codex) | 掲載済み |
| Anthropic コネクターディレクトリー | 審査中 |
| Glama | 掲載済み |
| Smithery | 掲載済み |
このリポジトリ以外で未対応の項目
コードの準備はできています。以下はコードの問題ではありません。
- MCP ホストと Supabase の前段にあるすべての場所で、Anthropic の送信元 IP 範囲
160.79.104.0/21を許可リストに追加します。 ブロックする WAF は、Anthropic で最もよく報告されている失敗原因です。 - CDN で
/.well-known/*、llms.txt、*.mdのキャッシュを回避し、サーバーの前段で SSE がバッファリングされないことを確認します。 - レビュアー用テストアカウントを使える状態に保ちます。 掲載後に、両方のディレクトリで再テストが行われる場合があります。アカウントのクレジットがなくなると、サーバーの障害のように見える形で失敗します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。