# MCP ツール一覧と日常運用 `atasira` MCP サーバー(`src/mcp_server/server.py`, FastMCP, stdio, entry point `atasira-mcp`)は**ちょうど 8 ツール**を公開する。各ツールは `$ATASIRA_BFF_URL` に対し `Authorization: Bearer $ATASIRA_PAT` で BFF REST API を叩く薄いラッパーであり、**MCP 層は独自の権限を一切追加しない** — RBAC(role + box assignment)はすべて BFF 側でそのまま強制される。セットアップは `01-connect.md`。 > **注**: 一部の古いドキュメント(`.claude/commands/box-ops.md` §4, 2026-07-28 付)は「LLM 切替の専用 MCP ツールは未実装」と書くが、これは**陳腐化**している。`atasira_get_box_llm` / `atasira_set_box_llm` は既に実装済みで、MCP 経由の切替はこれを使う(curl より優先)。 ## ツール一覧 | ツール | 対応 API | 認可 | |--------|----------|------| | `atasira_list_boxes()` | `GET /api/v1/boxes` | 認証済み。可視範囲は RBAC 準拠 | | `atasira_box_status(box_id)` | `GET /api/v1/boxes/{box_id}` | can_view | | `atasira_create_box_draft(...)` | `POST /api/v1/boxes/box-drafts` | 認証済み(常に pending_approval) | | `atasira_send_instruction(box_id, message, session_id?)` | `POST /boxes/{box_type}/sessions(+/messages)` | can_instruct | | `atasira_get_responses(box_id, session_id)` | `GET .../sessions/{id}/messages` | can_view | | `atasira_pending_drafts()` | `GET /api/v1/boxes/box-drafts/pending` | **admin PAT のみ** | | `atasira_get_box_llm(box_id)` | `GET /api/v1/boxes/{box_id}/llm` | can_view | | `atasira_set_box_llm(box_id, provider?, model?, node?)` | `PUT /api/v1/boxes/{box_id}/llm` | admin または box primary のみ | ### 1. `atasira_list_boxes()` 引数なし。可視 Box 一覧(admin=全件、非 admin=assignment 分のみ)。行はサーバー側で `box_type` 単位に dedup される。 ``` atasira_list_boxes() # -> {"boxes": [{"id":"...", "box_type":"market-watch", "state":"running", ...}], "total": N} ``` ### 2. `atasira_box_status(box_id: str)` `box_id` は **DB id または box_type** どちらでも可(クライアントが解決)。`state`(`idle`/`running`/`paused`/`stopped`/`error`)、`box_type`、`last_heartbeat` を返す。 ``` atasira_box_status("market-watch") ``` ### 3. `atasira_create_box_draft(purpose, box_type, name="", success_criteria=None, os_operations=None, tools=None, url_allowlist=None, prohibited_actions=None, allow_network=False)` **常に `state=pending_approval` の draft を作るだけ。** active 化する MCP ツール/経路はこのクライアントに存在しない(C9 ゲート / INV-1/INV-2)。特権 box_type(`admin-pm`/`admin-ops`)は 403(INV-5)。詳細は `02-box-lifecycle.md`。 ``` atasira_create_box_draft( purpose="Yahoo Auctions で FD3S 純正部品の新着出品を監視し LINE 通知", box_type="market-watch-fd3s", os_operations=["browser:navigate","op:read","notify:line"], tools=["Read"], allow_network=True, ) # -> {"draft_id":"...", "status":"pending_approval", "over_limit": true/false, ...} ``` ### 4. `atasira_send_instruction(box_id, message, session_id=None)` `box_id` を box_type に解決し、`session_id` 省略時は `POST /api/v1/boxes/{box_type}/sessions`、続いて `POST .../sessions/{session_id}/messages` に `{"content": message}`。RBAC は `require_box_access(RELATION_INSTRUCT)`(primary/secondary または admin/operator、無ければ 403)。**応答(`agent_message`)は同じ呼び出しで同期的に返る**。返った `session_id` を次回に渡すと同じ会話を継続(履歴は直近 10 ターン再生)。 ``` atasira_send_instruction(box_id="market-watch", message="今週の検知件数を教えて") # -> {"box_type":"market-watch", "session_id":"a1b2c3...", "user_message":{...}, "agent_message":{"role":"agent","content":"..."}} ``` ### 5. `atasira_get_responses(box_id, session_id)` `GET /api/v1/boxes/{box_type}/sessions/{session_id}/messages`。`session_id` は `atasira_send_instruction` が返したもの。RBAC は `RELATION_VIEW`。`{box_type, session_id, messages: [...], total}`(`user`/`agent` 両方の全メッセージ)を返す。 ``` atasira_get_responses(box_id="market-watch", session_id="a1b2c3...") ``` ### 6. `atasira_pending_drafts()` 引数なし。`GET /api/v1/boxes/box-drafts/pending`。**admin PAT が必要。** C9 承認キューを surfacing する(承認自体は console の人間操作のみ。承認 MCP ツールは存在しない — INV-1/INV-2)。 ``` atasira_pending_drafts() # -> [{"box_type":"market-watch-fd3s", "purpose":"...", "over_limit":..., "requested_by":"..."}, ...] ``` ### 7. `atasira_get_box_llm(box_id: str)` `GET /api/v1/boxes/{box_id}/llm`。**`box_id` は DB id**(`atasira_list_boxes` が返すもの)。解決済み実効設定 + 生 override を返す。`node` は `effective_provider == "atsllm"` のときのみ意味を持つ。 ``` { "provider":"atsllm", "model":null, "source":"builtin", "effective_provider":"atsllm", "available_providers":["atsllm","claude","gpt"], "node":"m5", "node_source":"builtin", "effective_node":"m5", "available_nodes":[{"id":"m5","configured":true,...},{"id":"m1","configured":true,...}], "override_provider":null, "override_model":null, "override_node":null } ``` ### 8. `atasira_set_box_llm(box_id, provider="", model="", node="")` `PUT /api/v1/boxes/{box_id}/llm`。クライアントは **先に GET してマージ**するため、単一フィールド変更が他の保存済み override を潰さない。引数の意味: - 省略 or `""` → そのフィールドは現状維持(保存済み `override_*` を引き継ぐ) - 文字列 `"none"` → そのフィールドの override を解除(manifest/env/builtin チェーンへ戻る) - その他文字列 → その値に set 3 フィールドすべて `"none"` で override 行ごと削除。`provider` 変更時に `model` 未指定なら旧 model override を意図的に drop(例: qwen 系 model 名が GPT へ漏れるのを防止)。認可は **admin または box primary のみ**(それ以外 403)。未 configured の `node` は **HTTP 400**(fail-closed)。詳細は `04-llm-provider-node.md`。 ``` atasira_set_box_llm(box_id="<db id>", provider="gpt") # GPT へ(node は非 atsllm では無視) atasira_set_box_llm(box_id="<db id>", node="m1") # AtsLLM box を公開 m1 ノードへ atasira_set_box_llm(box_id="<db id>", provider="none", model="none", node="none") # 全解除=既定へ ``` ## 日常運用パターン `.claude/commands/box-ops.md`(`/box-ops`)の機械版。標準ループ: **1. 状態確認** — `atasira_list_boxes()` で可視 Box、`atasira_box_status(box_id)` で `state`/`last_heartbeat`。heartbeat が古い/欠落なら Box の `host_agent` プロセス障害を疑う(アプリバグではなく)。 **2. 指示 → 応答** — `atasira_send_instruction(box_id, message)`(`session_id` 省略で新規会話、応答は同じ呼出で返る)。継続は前回の `session_id` を渡す。後で読み直すなら `atasira_get_responses(box_id, session_id)`。ここで 403 = その Box の primary/secondary assignment(または admin role)が無い → step 4 で付与するか admin に依頼。 **3. pause / resume / kill** — **MCP ツールなし**。admin/operator のみ `POST /api/v1/boxes/{box_id}/control` に `{"action": "pause"|"resume"|"kill"}`(`require_role("admin","operator")`)。有効遷移: `pause`: running/idle→paused / `resume`: paused→running / `kill`: running/paused/idle/error→stopped(それ以外は 400 `Cannot '<action>' box in state '<state>'`)。応答 `new_state` で検証。 ```bash curl -sS -X POST "$ATASIRA_BFF_URL/api/v1/boxes/<box_id>/control" \ -H "Authorization: Bearer $ATASIRA_PAT" -H "Content-Type: application/json" \ -d '{"action": "pause"}' ``` **4. 他ユーザーへ Box を付与(box assignment)** — **MCP ツールなし**。BFF 直叩き。`role_in_box` = `primary`/`secondary`/`observer`。admin または現 primary のみ付与可(primary は secondary/observer のみ付与可、primary の付替えは admin のみ)。同一 (box, user) の重複付与は 409(role 変更は削除→再付与)。 ```bash # 付与 curl -sS -X POST "$ATASIRA_BFF_URL/api/v1/boxes/<box_id>/user-assignments" \ -H "Authorization: Bearer $ATASIRA_PAT" -H "Content-Type: application/json" \ -d '{"user_id": "<user_id>", "role_in_box": "secondary"}' # 剥奪 curl -sS -X DELETE "$ATASIRA_BFF_URL/api/v1/boxes/<box_id>/user-assignments/<user_id>" \ -H "Authorization: Bearer $ATASIRA_PAT" ``` 検証: 付与ユーザーの `atasira_list_boxes()`(または `GET /api/v1/users/<user_id>/boxes`)に当該 Box が現れる。 **5. admin: pending draft レビュー** — `atasira_pending_drafts()` で承認待ちを surfacing。承認は console の人間操作のみ(このツールは承認しない)。 **6. LLM provider/node 切替** — `atasira_get_box_llm` / `atasira_set_box_llm`(上記 7/8、`04-llm-provider-node.md`)。