Claude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する

アプリの作り方

Claude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する

AIに作業を任せるほど、ターミナル・ブラウザ・各種ツールを行き来する手間が増えていく。「今どのエージェントが何をしているのか」を見失う。その散らかりを、ひとつのデスクトップアプリに畳み込めないかと考えた。

目次
  1. このガイドで作るもの
  2. 前提環境:最初に道具を揃える
  3. 設計の起点:なぜ Tauri + Python サイドカーなのか
  4. バイブコーディングで作る順番:大きく作らず、小さく積む
  5. 作り方の要点
    1. 1. タブで「役割」を分ける
    2. 2. 外部ツールは MCP で繋ぐ
    3. 3. 品質ゲートを最初から回す
  6. 3層分離で「壊れない」司令塔を組む
    1. レイヤー責務:ロジックを置く場所を1か所に固定する
    2. Rust ↔ Python は loopback WebSocket + トークン認証
    3. Agent アダプタ:共通 ABC で「同じ作法」に揃える
    4. EventBus と短期/長期メモリの分離
    5. 3言語を全緑で回す品質ゲート
  7. Hermes を「ローカルLLMゲートウェイ」として組み込む
    1. 仕組み:アプリが hermes gateway を spawn する
    2. 設定:agents.toml に1ブロック足す
    3. Hermes 側の認証:どのモデルで喋らせるか
  8. 正直なまとめ

このガイドで作るもの

複数のAIエージェントの状態・会話・成果物を一画面で扱うデスクトップ司令塔「Claude Mission Control」。チャット、メディア生成(Studio)、ワークスペース把握、ノートブックを5つのタブに統合し、外部ツールは MCP(Model Context Protocol)で繋ぐ。1つのアプリで「投げて・見て・受け取る」が完結する構成だ。

Claude Mission Control のチャットタブ。中央にフォーカス中エージェント、右にSIBLINGS・ライブストリーム・メトリクス
起動直後のチャットタブ。中央にフォーカス中のエージェント、右に他エージェント(SIBLINGS)・ライブストリーム・メトリクスを並べる。ここが司令塔の主画面(サイドカー未接続の待機状態)。

前提環境:最初に道具を揃える

このアプリは3言語(TypeScript / Rust / Python)と外部CLIが噛み合う。動かす前に、土台を先に入れておく。ここを飛ばすと最初の pnpm tauri dev でつまずく。

  • Node.js 20+ と pnpm … フロント。依存に link: プロトコルがあるため npm は不可。npm i -g pnpm で入れる。
  • Rust 安定版(rustup)+ Tauri 2 のビルド要件 … デスクトップの殻。Windows なら Microsoft C++ Build Tools と WebView2 が要る。
  • Python 3.12+ と uv … サイドカーの依存管理(pip より速い)。
  • Hermes Agent … Hermes エージェントを使うなら必須(後述)。
  • Docker Desktop(任意) … OpenClaw アダプタを使うときだけ。
  • npx / Windows Terminal(wt) / Obsidian Local REST API … それぞれ Notebook タブ・Workspace タブ・Obsidian 連携で使う。

土台が入ったら、セットアップはこれだけだ。

# フロント
pnpm install

# Python サイドカー
cd sidecar
uv sync --extra dev
cd ..

# 開発起動(Rust が Python サイドカーを自動 spawn する)
pnpm tauri dev

設計の起点:なぜ Tauri + Python サイドカーなのか

UI は軽く配布しやすくしたい、でも AI/ツール連携は Python の資産を使いたい。そこでフロントを Tauri 2 + SvelteKit、バックを Python FastAPI のサイドカーとして同梱し、両者をローカルで通信させる構成にした。Electron より軽量な配布物にしつつ、Python 側で重い処理や外部 API を担わせられる。

バイブコーディングで作る順番:大きく作らず、小さく積む

「複数AIの司令塔」と聞くと身構えるが、いきなり全部は作れない。バイブコーディングの5原則そのままに、動く最小単位を1つずつ積む。実際このアプリも Phase 0→8 の小さな段で組み上げた。各段で「AIに何を頼むか」をプロンプト例で示す。

  1. Phase 0:殻だけ出す。まず空のウィンドウが1枚。
    プロンプト例:「Tauri 2 + SvelteKit(static adapter)の最小構成を作って。空ウィンドウが1枚出るところまで。ロジックはまだ要らない」
  2. Phase 1:サイドカーを1本だけ立てる。UI とは別プロセスの Python を起こし、ループバックWSで握手する。
    「Python(FastAPI)で ws://127.0.0.1:7878/ws を1本立てて。起動時に渡す --auth-token と一致しないWSは即閉じ、通ったら {"type":"ready"} を返すだけ」
  3. 最初のエージェントを1種だけ。共通インターフェース(ABC)を決め、まず Claude を pty で動かす1実装にする。
    AgentAdapter という抽象基底を作って。start/stop/status/send(prompt) の4つだけ。最初は claude を pty で駆動する実装を adapters/claude.py に」
  4. 横断ライブを足す。「今どのエージェントが何をしているか」を EventBus で配る。
    「pub/sub の EventBus を bus.py に。アダプタは publish するだけ、WS は subscribe してそのまま UI に流すだけ」
  5. 外部ツールは MCP に寄せる。個別アダプタを書かず「同じ作法」に統一する。
    「NotebookLM 連携を npx -y notebooklm-mcp の stdio JSON-RPC で。専用クライアントは作らず MCP 1本に寄せて」
  6. 2種類目以降のエージェントを増やす。ABC があるので registry に足すだけ。ここで Hermes を入れる(次章)。
  7. 品質ゲートを「最初から」回す。3言語が絡むと手作業確認は必ず崩れる。
    「pytest-asyncio と Vitest を最初から書いて。CI で pnpm / uv / cargo の3系統を全緑にしないとマージしない運用に」

コツは「1段ずつ動かして確かめてから次へ」。1段の中でも、AIの出力(特に層の境界をまたぐコード)は読んでから受け取る。丸呑みで積むと、後で必ず崩れる。

作り方の要点

1. タブで「役割」を分ける

機能を1画面に詰め込むと破綻する。Chat(会話・LIVEストリーム・スキルタイムライン)、Studio(画像/音声/動画/検索)、Workspace(プロジェクト把握)、Notebook の4系統にタブで分割し、それぞれが独立して動くようにした。「1タブ=1関心事」が、後からの拡張を楽にする。

Claude Mission Control のスタジオタブ。画像・音声・動画・X検索を1画面に集約
スタジオタブ。画像・音声・動画・X検索を1画面に集約している(役割ごとにタブを分ける設計の一例)。実際のアプリはこのあと Kanban・Mission Control タブも増えた。

2. 外部ツールは MCP で繋ぐ

各ツールに個別アダプタを書くと保守が地獄になる。Notebook 連携は MCP クライアント(Python)経由に寄せ、ツール側を差し替え可能にした。MCP に統一しておくと、新しいツールを「同じ作法」で足せる。

3. 品質ゲートを最初から回す

複数言語・複数プロセスのアプリは、手で確認していると必ず崩れる。pytest・vitest・E2E・CI を最初から全緑で維持する運用にした。「動いているはず」を「動いていると測れる」に変えるのが、この規模では生命線になる。

3層分離で「壊れない」司令塔を組む

ここからは、実際の Claude Mission Control がどう組まれているかを、稼働中の実装に沿って開く。肝は「3つの層に責務を厳格分離する」一点に尽きる。

Claude Mission Control の概観タブ。全エージェント・メモリ・シグナルの状態を一望する
Mission Control タブ。全エージェント・メモリ・シグナルの状態を一望する概観画面(起動直後・エージェント未登録の状態)。左に WORKSPACE / AGENTS / SELF、中央に HEARTBEAT・LATENCY。

レイヤー責務:ロジックを置く場所を1か所に固定する

3言語(TypeScript / Rust / Python)が混ざるアプリで最初にやるべきは、「どの層に何を書くか」を決め切ることだ。本アプリはこう固定した。

  • Svelte 5 UIsrc/)… 描画と状態表示のみ。ロジックはゼロ。Tauri invoke/event のラッパ(lib/ipc.ts)と Svelte ストア(agents / connection / conversation)だけを持つ。
  • Rust コアsrc-tauri/)… 薄く保つ。ウィンドウ/トレイ/blur/グローバルホットキー、Python サイドカーの spawn・健康監視・再起動、UI↔WS ブリッジ。秘密情報は OS の keyring に置き、.env に平文で置かない。
  • Python サイドカーsidecar/)… 統合ロジックの本拠地。エージェントを知っているのはここだけ。FastAPI+WebSocket、AgentRegistry、EventBus、aiosqlite 短期ストア、各 MCP クライアント。

「UI にロジックを書かない/Rust を太らせない/統合は全部 Python」を徹底すると、どこを直せばいいか迷わなくなる。

Rust ↔ Python は loopback WebSocket + トークン認証

フロントとサイドカーは ws://127.0.0.1:PORT のループバックで繋ぐ。HTTP の単発リクエストではなく WebSocket にするのは、エージェントの進捗をサーバ側から押し出す(イベント駆動)必要があるからだ。127.0.0.1 限定+起動時に発行するトークンで認証し、ローカルの他プロセスから叩かれない様にする。Rust は Python を spawn したら健康監視し、落ちたら再起動する「番人」に徹する。

サイドカーは起動時に --auth-token を受け取り(既定 127.0.0.1:7878 で待受)、WS はこのトークンが一致しないと 1008 で即切断する。Authorization: Bearer ヘッダを優先し、無ければ後方互換で ?token= も見る。

# sidecar.py(要点)
@app.websocket("/ws")
async def ws(websocket: WebSocket) -> None:
    token = _ws_token(websocket)                 # Bearer ヘッダ優先 / ?token= も可
    if not verify_token(expected=auth_token, presented=token):
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
        return
    await websocket.accept()
    await websocket.send_json({"type": "ready"})  # 握手完了
    # 以降: EventBus を WS へ流す forwarder + 受信コマンドの dispatcher

Agent アダプタ:共通 ABC で「同じ作法」に揃える

拡張性の核がこれだ。エージェント種別ごとの差異(起動方法・通信方法)を共通の抽象基底(ABC)の裏に隠し、adapters/ に1種別=1実装で置く。

共通の抽象基底はこれだけ。たった4メソッドに揃える。

# adapters/base.py(要点)
class AgentAdapter(ABC):
    name: str
    type: str
    @abstractmethod
    async def start(self) -> None: ...
    @abstractmethod
    async def stop(self) -> None: ...
    @abstractmethod
    async def status(self) -> AgentStatus: ...
    @abstractmethod
    def send(self, prompt: str) -> AsyncIterator[Event]: ...  # token/skill/error... を流す

この裏に、起動方法がまるで違う種別を adapters/ に「1種別=1実装」で隠す。本アプリは4種を持つ。

  • claude_code … pty(擬似端末)で対話プロセスを駆動
  • openclaw_docker … Docker コンテナ制御
  • hermes_daemon … Hermes のローカル HTTP ゲートウェイを叩く(次章で詳説)
  • antigravity … Antigravity CLI を駆動

起動方法が違う4種でも、UI からは AgentRegistry を通して同じインターフェースで扱える。サイドカーは agents.tomltype を見て対応アダプタを差し込むだけ。新しいエージェントは「ABC を実装して registry に登録」すれば増える。個別 if 分岐を UI やコアに撒かないのが、保守を生かすか殺すかの分かれ目だ。

Claude Mission Control のKanbanタブ。タスクを担当エージェントへDispatchするマルチエージェント・ボード
Kanban タブ。タスクを作って担当エージェントへ Dispatch する、マルチエージェントの作業ボード(TRIAGE → TODO → READY → RUNNING → BLOCKED → DONE)。

EventBus と短期/長期メモリの分離

横断ライブストリーム(どのエージェントが今何をしているか)は bus.pypub/sub EventBus で配る。各アダプタはイベントを publish するだけ、UI は subscribe するだけ。状態は2層に分ける。短期aiosqlite のローカルストア、長期記憶は Obsidian Vault へ MCP クライアント経由で永続化する。NotebookLM 連携は npx notebooklm-mcp を stdio で起動し JSON-RPC 2.0 で話す。すべて「MCP という同じ作法」に寄せてある。

3言語を全緑で回す品質ゲート

前半で「品質ゲートが生命線」と書いた、その実体。UI は Vitest + Testing Library、サイドカーは pytest-asyncio。パッケージは pnpm(依存に link: プロトコルがあるため npm は不可)・uv(Python)・cargo(Rust)の3系統。3言語が絡むと「片方を直して片方が壊れる」が日常になるので、CI 全緑を「進む条件」にしておく。

Hermes を「ローカルLLMゲートウェイ」として組み込む

ここが本ガイドで追記した肝だ。Hermes アダプタは、他の2種(pty・Docker)とは毛色が違う。Hermes 自身を OpenAI 互換の API サーバとしてローカルに立て、サイドカーが HTTP で叩く。これで grok / claude / gpt / llama を「同じ口」で差し替えられる。

仕組み:アプリが hermes gateway を spawn する

アダプタは Hermes Agent のゲートウェイを子プロセスで起こし、環境変数でローカル API サーバを有効化する。

# adapters/hermes.py(起動の要点)
env["API_SERVER_ENABLED"] = "true"
env["API_SERVER_PORT"]    = "7777"
env["API_SERVER_KEY"]     = "mission_control_key"
proc = await asyncio.create_subprocess_exec(
    "hermes", "gateway", "run", "--replace", env=env, ...)

# 生存確認: GET  http://127.0.0.1:7777/health
# 送信:     POST http://127.0.0.1:7777/v1/chat/completions
#           headers = {"Authorization": "Bearer mission_control_key"}
#           json    = {"model": "hermes-agent", "messages": [...], "stream": False}

OpenAI 互換なので、messages 配列に「system(過去インサイト)+直近履歴+今回の user」を積んで投げ、choices[0].message.content を受け取るだけ。長期記憶は Obsidian の Knowledge/hermes-insights.md 末尾を system に前置きする作りにしてある。

設定:agents.toml に1ブロック足す

Mission Control の設定は ~/.claude-mission-control/agents.toml。Hermes を1エージェントとして宣言する。

[agents.hermes]
type = "hermes_daemon"
binary = "hermes-agent.exe"   # 起動時に gateway 用の hermes(.exe) へ自動補正
gateway_port = 7777

[obsidian]
vault_path = "C:/path/to/MyVault"   # 長期記憶(insights)の置き場

Hermes 側の認証:どのモデルで喋らせるか

ゲートウェイが「誰に問い合わせるか」は Hermes 側の ~/.hermes/config.yaml が決める。アプリのモデル切替UIは、この model: ブロックを書き換えているだけだ。選べる代表は次の通り。

  • grok-4.3(provider: xai-oauth) … X の SuperGrok / Premium+ サブスクで認証。API キー不要。※この OAuth 経由の利用は xAI の利用規約の解釈・変更に依存する(公式アプリ外からの利用が制限される可能性がある)。確実に使うなら正規の xAI API キーを推奨。各自で現行規約を確認のこと。
  • claude-3.5-sonnet / gpt-4o / llama-3.3-70b(provider: openrouter) … OpenRouter の API キーで認証。1キーで複数モデルに届く。

初回はこの2手だけ通せばいい。OAuth ログインの詳しい流れはXメディア生成パイプラインの作り方の「Hermes セットアップ」と同じだ。

# 1. Hermes を入れる(依存込み)
iex (irm https://hermes-agent.nousresearch.com/install.ps1)   # Windows

# 2. プロバイダ認証(どちらか)
hermes login --provider xai-oauth   # SuperGrok(ブラウザで X にサインイン)
#   または hermes setup で OpenRouter キーを登録

# 3. 確認
hermes status   # Provider が出れば認証済み

つまずきどころ:①ゲートウェイの実体は hermes.exehermes-agent.exe を指定しても自動補正される)。②xai-oauth のトークンは約6時間で切れ、リフレッシュトークンが失効すると生成が全停止する(その時は hermes login --provider xai-oauth で入れ直す)。③ポート 7777 が他プロセスと衝突するなら gateway_port を変える。

正直なまとめ

このアプリの価値は派手なUIではなく、「UIは描画だけ・Rustは番人・Pythonが統合・拡張はアダプタ」という責務分離にある。ここさえ守れば、エージェントもツールも後から増やせる。Hermes をローカルゲートウェイにすれば、grok / claude / gpt / llama を同じ口で差し替えられるのも、この「アダプタに寄せる」設計の果実だ。動かすには SuperGrok / OpenRouter の認証や Docker(OpenClaw 使用時)など環境準備が要るが、最初から全部を作ろうとせず、Phase 0 の空ウィンドウから小さく積めば、未経験でもここへ辿り着ける。


👉 関連: 開発実例:Claude Mission Controlほかのアプリの作り方

New Eden Intelligence Hub の作り方 — EVE Online の SSO×ESI API で市場・資産・戦闘を一画面に集約する自分専用ダッシュボードNew Eden Intelligence Hub の作り方 — EVE Online の SSO×ESI API で市場・資産・戦闘を一画面に集約する自分専用ダッシュボード前のページ

AIアセットでゲームマップを作る — 生成スケッチの透過切り出しからレベルセレクトまで次のページAIアセットでゲームマップを作る — 生成スケッチの透過切り出しからレベルセレクトまで

ピックアップ記事

  1. New Eden Intelligence Hub の作り方 — EVE Onl…

  2. Claude Mission Control の作り方 — Tauri+Pyth…

  3. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyIns…

  4. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド…

関連記事

  1. 背景除去アプリを作る⑥|QGraphicsViewズーム・スポイト・QThread非同期・D&D一括処理【背景除去Studio制作】
  2. YouTubeチャンネル分析ツールの作り方 — Data APIで統計・投稿パターン・キーワードを可視化する

    アプリの作り方

    YouTubeチャンネル分析ツールの作り方 — Data APIで統計・投稿パターン・キーワードを可…

    キーワードでチャンネルを検索し統計・人気動画・投稿パターン・頻出ワード…

  3. 都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制作】

    アプリの作り方

    都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制…

    「面白くない」を4軸(目標・打ち手・変化・音)で解消する。都市ランクと…

  4. 都市開発シミュを作る③|需要・成長・経済の決定論シミュレーション(MVP完成)【Aurum City制作】

    アプリの作り方

    都市開発シミュを作る③|需要・成長・経済の決定論シミュレーション(MVP完成)【Aurum City…

    需要・成長・経済で街を動かす決定論シミュレーションの作り方。種から回す…

  5. New Eden Intelligence Hub の作り方 — EVE Online の SSO×ESI API で市場・資産・戦闘を一画面に集約する自分専用ダッシュボード

    アプリの作り方

    New Eden Intelligence Hub の作り方 — EVE Online の SSO×…

    自作の EVE Online 統合ダッシュボード「New Eden I…

  6. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyInstaller凍結の実践

    アプリの作り方

    高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyInstaller凍結の実…

    PaddleOCR-VLで撮影→解析→翻訳まで完結するOCRアプリの作…

注目

AIで、ここまで作れる

AIで作った2D RPGを、ブラウザでそのまま遊べます。その「作り方=最後まで完成させる進め方」も実例つきで公開中。

▶ ゲームを遊ぶやり方を読む

PR

ロリポップ!レンタルサーバー(PR)

レンタルサーバ:ロリポップ!(本サイトの稼働環境・PR)

  1. 背景除去アプリを作る②|AIなしでここまで抜ける — FloodFill・クロマキー・Color-to-Alphaの古典CVエンジン【背景除去Studio制作】

    アプリの作り方

    背景除去アプリを作る②|AIなしでここまで抜ける — FloodFill・クロマ…
  2. GitHub MCP Server がステートレス化 — 自作 MCP サーバを 2026-07-28 仕様へ移す棚卸しと検証手順

    AI・テック動向

    GitHub MCP Server がステートレス化 — 自作 MCP サーバを…
  3. FX Monitor Pro の作り方 — Flet で主要10通貨ペアを常時モニターするデスクトップ為替アプリ

    アプリの作り方

    FX Monitor Pro の作り方 — Flet で主要10通貨ペアを常時モ…
  4. Transcription Studio の作り方 — Whisper をローカルで走らせ、エンジンを切り替えて文字起こしする

    アプリの作り方

    Transcription Studio の作り方 — Whisper をローカ…
  5. AIでゲーム素材を量産する⑤|生成→透過切り出し(BiRefNet)→配置のパイプライン【Archipelago Saga制作】

    アプリの作り方

    AIでゲーム素材を量産する⑤|生成→透過切り出し(BiRefNet)→配置のパイ…
PAGE TOP

TAG CLOUD

ドラッグで回転・クリックでそのタグの記事一覧へ