Kuroco mng_api Browser Skill
概要
Kurocoの管理API(mng_api)をclaude-in-chrome MCPツール経由で操作するスキル。
mng_apiの5つのモード:
-
whoami: セッション情報の取得(GET) — member_id, name, group_ids, expiresAt を返す
-
discover: 利用可能なモジュール・コントローラの探索(GET)
-
schema: コントローラ/サービスのリクエスト・レスポンススキーマ取得(GET)
-
advise: 自然言語でやりたいことを伝えると、呼ぶべきAPIと手順をAIが回答(POST)
-
execute: APIの実行(GET/POST) — columns パラメータでレスポンスカラム選択可能
認証方式: ブラウザのセッションCookie(__Host-rcms_api_access_token 、HttpOnly)を利用。javascript_tool でfetch()を実行すれば、Cookieが自動送信されるためトークンの抽出は不要。
前提条件:
-
claude-in-chrome MCPが利用可能(未設定の場合は下記「操作フロー」Step 0 で案内)
-
ユーザーがKuroco管理画面(https://..kuroco-mng.app )にログイン済み
-
対象サイトが不明な場合は、サイトキーまたは管理画面URLをユーザーに確認して特定する
-
すべての操作はログイン中ユーザーの権限で実行される
最小操作フロー(読み取り: 4-5回、書き込み: 5-6回の tool call):
-
javascript_tool : 認証チェック(MODE=whoami)
-
navigate
- get_page_text : /llms.txt でモジュール/コントローラ特定
- navigate
- get_page_text : /direct/rcms_api/llms/?mt={module} でフィールド名・パラメータ仕様を取得
-
(書き込み時) javascript_tool : MODE=schema でフィールド型・必須項目・ブロックエディタ構造を取得
-
javascript_tool : API実行(mt/ct形式)
Step 3 は必須。 /llms.txt (概要)にはモジュール一覧しかなく、ext_colのフィールド名は含まれない。フィールド名の把握にはモジュール詳細が必要。 Step 4 は書き込み操作で必須。 スキーマは data.request.properties にJSON Schema形式でフィールド定義を返す。topics_group_id を指定することでext_col/ブロックエディタの必須フィールドが判明する。 discoverモードは通常不要。llms.txtの2段階(概要→詳細)で十分な情報が得られる。
操作フロー
すべてのAPI操作はこのフローに従うこと。
操作開始前の判断: ユーザーから「〜を確認して」「〜を検索して」「〜のデータを見て」等のリクエストを受けた場合、まずそれが**データ取得(API)**で解決できるか判断する。管理画面のUIが目の前にあっても、反射的にクリック操作に入らないこと。APIで取得できるデータはAPIで取得する。UIブラウザ操作はAPIでは不可能な操作(ファイルアップロード、プレビュー、GUI固有の設定変更等)にのみ使用する。
Step 0: claude-in-chrome MCP の確認
このスキルは mcp__claude-in-chrome__* ツール群に依存する。操作開始前に、これらのツールが利用可能か確認する。
確認方法: mcp__claude-in-chrome__tabs_context_mcp を呼び出す。
-
成功した場合 → Step 1 へ進む
-
ツールが見つからない / 接続エラーの場合 → ユーザーにセットアップを案内する:
ブラウザ操作に必要な claude-in-chrome MCP が利用できません。 以下の手順でセットアップしてください。
【必要なもの】
- Google Chrome または Microsoft Edge
- Claude in Chrome 拡張機能(v1.0.36以上) → Chrome Web Store からインストール: https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn
- Claude Code v2.0.73 以上
【有効化の手順】
- Claude Code セッション内で
/chromeを実行 - または
claude --chromeで起動
セットアップ完了後、もう一度お試しください。
注意: Chrome連携は Anthropic の直接プラン(Pro, Max, Teams, Enterprise)が必要です。サードパーティプロバイダ(Amazon Bedrock, Google Cloud Vertex AI 等)経由では利用できません。
Step 1: 対象サイトの特定
mcp__claude-in-chrome__tabs_context_mcp を呼び出し、URLパターン ..kuroco-mng.app に一致するタブを探す。
-
タブが1つ見つかった場合 → そのタブのURLからベースURL(https://{site_key}.{env}.kuroco-mng.app )を取得し、以降の操作で使用
-
複数のKurocoタブが見つかった場合 → どのサイトを操作するかユーザーに確認
-
タブが見つからない場合 → AskUserQuestion ツールでサイトキーまたは管理画面URLを確認:
{ "questions": [{ "question": "操作対象のKuroco管理画面を特定できませんでした。サイトキーまたは管理画面URLを教えてください(例: demo / https://demo.g.kuroco-mng.app/management/ / https://demo.stg.kuroco-mng.app/management/)", "header": "対象サイト", "options": [ { "label": "URLを入力する", "description": "管理画面のURL(https://**..kuroco-mng.app/management/)を入力" }, { "label": "サイトキーを入力する", "description": "サイトキー(例: demo)を入力。環境はタブのURLまたはユーザーに確認" } ], "multiSelect": false }] }
ユーザーの回答からベースURLを特定し、mcp__claude-in-chrome__tabs_create_mcp で管理画面を開く:
-
URLが提供された場合 → URLからホスト部分を抽出(例: https://demo.g.kuroco-mng.app )
-
サイトキーが提供された場合 → https://{site_key}.{env}.kuroco-mng.app を構築(envはユーザーに確認、デフォルトは g )
注意: すべての操作はブラウザでログイン中のユーザーの権限で実行されます。そのユーザーがアクセス権を持たないモデルやメソッドは操作できません。
Step 2: 認証チェック(軽量リクエスト)
mcp__claude-in-chrome__javascript_tool で以下を実行:
(async () => { const r = await fetch('/direct/rcms_api/mng_api/?MODE=whoami', {credentials:'include'}); const d = await r.json(); return JSON.stringify({status: r.status, ok: r.ok, member_id: d.member_id, name: (d.name2 || '') + ' ' + (d.name1 || ''), group_ids: d.group_ids}); })()
重要: javascript_tool ではトップレベル await は使えない。 ページコンテキストでの評価となるため、await を使う場合は必ず (async () => { ... })() でラップすること。トップレベルで await を書くと SyntaxError: await is only valid in async functions になる。
MODE=whoami はセッション情報(member_id, name1, name2, group_ids, expiresAt)を返す軽量エンドポイント。認証確認と同時にログインユーザーの権限情報が取得できる。
Step 3: llms.txt でサイト構造把握(必須)
navigate
- get_page_text で llms.txt を読む。1回のリクエストで以下が得られる:
-
全モジュール・コントローラ一覧
-
コンテンツ定義・API・フォーム等のサイトマップ
-
mng_api の使い方・パラメータ仕様
-
ワークフロー例
navigate → /llms.txt get_page_text → サイト全体の構造を取得
注意:
-
管理画面ページ巡回の前に必ずllms.txtを確認。大半の構造情報はここで得られる(discoverモード通常不要)
-
llms.txt はKurocoがログインユーザーの権限に基づいて動的に生成する。ユーザーの権限外のAPIは表示されない
-
/llms.txt (概要)にはモジュール一覧のみ。ext_colフィールド名は次の Step 3.5 で取得
Step 3.5: モジュール詳細でフィールド名を把握(必須)
操作対象のモジュールが特定できたら、必ずモジュール詳細を読んでフィールド名を把握する。
navigate → /direct/rcms_api/llms/?mt={module} get_page_text → ext_colのフィールド名、Available Columns、パラメータ仕様を取得
このステップを省略してはならない。 ext_col_01〜20のフィールド名(例: ext_col_03 = to, ext_col_04 = cc)はモジュール詳細にしか記載されていない。管理画面のDOMを巡回したり、APIレスポンスの中身を推測するのは非効率でエラーの原因になる。
Step 4: スキーマ取得(書き込み操作では必須)
書き込み操作(INSERT/UPDATE)を行う場合は、必ずスキーマを取得してフィールド構造を確認すること。 特にブロックエディタや拡張項目(ext_col)を持つコンテンツ定義では、必須フィールド名や型がスキーマでしか把握できない。
重要: スキーマレスポンスはJSON Schema形式。 data.request 直下にはフィールド情報はない。data.request.properties にフィールド定義が、data.request.required に必須フィールドが格納されている。
コンテンツ定義固有のフィールドを取得するには topics_group_id を指定する:
// javascript_tool — topics_group_id指定でext_col含むフィールド一覧を取得 (async () => { const r = await fetch('/direct/rcms_api/mng_api/?MODE=schema&mt=topics&ct=topics_edit&topics_group_id=99', {credentials:'include'}); const data = await r.json(); const props = data.request?.properties || {}; const required = Array.isArray(data.request?.required) ? data.request.required : Object.keys(data.request?.required || {}); const fields = {}; Object.entries(props).forEach(([k, v]) => { fields[k] = {type: v.type, description: v.description, kurocoType: v['x-kuroco-type'], required: required.includes(k)}; }); return JSON.stringify(fields, null, 2); })();
注意:
-
topics_group_id を省略すると汎用フィールドのみ返る(ext_col が含まれない)
-
topics_group_id を指定するとブロックエディタ・拡張項目のフィールド名(ext_1 , ext_14 等)、型、必須フラグが取得できる
-
list系コントローラ(topics_list 等)はスキーマが空を返すため、書き込み用コントローラ(topics_edit )を指定すること
-
レスポンスの x-kuroco-type でフィールドの種類(wysiwyg , json , checkbox , file 等)がわかる
Step 5: API実行
認証確認・構造把握が完了したら、API実行パターンに従ってAPIを実行する。
Step 6: 認証失敗・セッション切れ対応
401または403が返った場合:
-
ユーザーにログインが必要な旨を伝える
-
ログインURL: {base_url}/management/login/login/ (base_urlはタブのURLから取得)
-
ユーザーがログインするまで待機
-
ログイン後に再度認証チェック
複数ステップの操作中に401/403が発生した場合:
-
即座に操作を停止
-
どこまで成功したかをユーザーに報告
-
再認証を案内
-
再認証後、未完了の操作から再開
手段選択の判断基準(最重要)
原則: データの取得・検索・フィルタリングが目的なら、UIではなくAPIを使う。
ブラウザで管理画面が開いていても、UI要素をクリックして情報を探すのは人間の操作方法であり、AIエージェントの操作方法ではない。ブラウザのセッションCookieは javascript_tool の fetch() でも自動送信されるため、UIナビゲーションとAPI呼び出しの認証コストは同じ。
目的 手段 理由
データ一覧の取得・検索・フィルタリング API(mng_api) 構造化JSON、プログラム的に処理可能
特定コンテンツの詳細確認 API(mng_api) columns指定で必要項目だけ取得可能
サイト構造・API仕様の把握 llms.txt 1回で全体把握可能
ファイルアップロード・プレビュー・GUI固有の設定変更 UIブラウザ操作 APIでは不可能な操作のみ
アンチパターン
やりがち 問題 推奨
管理画面のUI要素をクリックしてデータを検索・閲覧する 人間の操作を模倣しているだけ。遅く、結果がHTMLで構造化されていない。改善・自動化に繋がらない mng_apiのfetch()でJSON取得。同じセッションCookieが使えるのでUIを経由する理由がない
columns を指定せずにGETリクエスト レスポンスが巨大でブロックされる 常にcolumns=必要カラム を指定(効かない場合は.map() で抽出)
fetch() でHTMLを取得→DOMParserでパース Vue.jsレンダリング部分が空になる mng_api でJSON取得
document.querySelector('main').textContent で全文取得 Cookieブロックのリスク 必要なデータのみ抽出
トップレベル await を使う SyntaxError になる 必ず (async () => { ... })() でラップ
メールアドレスを含むフィールド値をそのまま返す [BLOCKED] になる .includes() で判定結果のみ返す
Object.keys(data.request) でスキーマのフィールドを探す JSON Schema形式なので type ,properties ,required しか返らない data.request.properties でフィールド一覧を取得する
スキーマ取得時に topics_group_id を省略する 汎用フィールドのみでext_colが含まれない &topics_group_id={id} を指定してコンテンツ定義固有のフィールドを取得
API実行パターン
パラメータ形式
mng_apiでは mt (モジュール)と ct (コントローラ)の形式を使用する。
パラメータ 説明 例
mt
モジュール名(小文字) topics , member , inquiry
ct
コントローラ名 topics_list , topics_edit , member_list
注意: model=Topics&method=list 形式は使用しないこと。HTMLが返却される場合がある。必ず mt/ct 形式を使用する。
GETリクエスト(一覧取得・検索)
// javascript_tool — columns + cnt で必要最小限のレスポンスを取得 (async () => { const r = await fetch('/direct/rcms_api/mng_api/?mt=topics&ct=topics_list&topics_group_id[]=1&cnt=10&columns=topics_id,subject,ymd', {credentials:'include'}); const data = await r.json(); return JSON.stringify(data, null, 2); // → columns対応エンドポイントではサーバー側フィルタ(各アイテム {topics_id, subject, ymd} のみ) // → 非対応の場合は .map() でクライアント側抽出: // data.topics_list?.map(t => ({id: t.topics_id, subject: t.subject})) })()
columns原則: GETリクエストでは常に columns を指定。対応エンドポイントではサーバー側フィルタリング、非対応でも無視されるだけなので常に指定して問題ない。効かなかった場合はクライアント側 .map() で抽出。columns はexecuteモード専用(discoverモードには適用されない)。
POSTリクエスト(作成・更新・削除)
// javascript_tool — MODE=INSERTで新規作成 (async () => { const r = await fetch('/direct/rcms_api/mng_api/?mt=topics&ct=topics_edit_api&MODE=INSERT', { method: 'POST', credentials: 'include', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ subject: 'タイトル', contents: '本文', topics_group_id: 1 }) }); const data = await r.json(); return JSON.stringify(data, null, 2); })()
重要なルール
ルール 説明
credentials 全リクエストに credentials: 'include' 必須
パラメータ形式 必ず mt/ct 形式を使用(model/method 形式は不可)
GET配列パラメータ [] suffix必須(例: topics_group_id[]=1 )
POST配列パラメータ ネイティブJSON配列(例: {"topics_group_id": [1]} )
件数制限 レスポンスが大きい場合は cnt パラメータで制限
columns指定 columns=col1,col2 でレスポンスカラムを最小限にする。対応エンドポイントでは必ず指定すること(javascript_toolの出力制限対策・レスポンス効率化)。効かないエンドポイントもあるため、その場合はクライアント側で抽出
変更操作の確認 insert/update/deleteは実行前にユーザーに確認すること
レスポンス切り詰め javascript_tool の出力制限があるため、大きなレスポンスは必要部分のみ抽出
レスポンス構造が不明な場合
.map() する前に Object.keys() で構造を確認。プロパティ名を推測して複数回試行せず、1回で構造を把握する:
(async () => { const r = await fetch(url, {credentials:'include'}); const data = await r.json(); const keys = Object.keys(data); const firstArrayKey = keys.find(k => Array.isArray(data[k])); const firstItem = firstArrayKey ? data[firstArrayKey][0] : null; return JSON.stringify({ topLevelKeys: keys, firstArrayKey, firstItemKeys: firstItem ? Object.keys(firstItem) : null }, null, 2); })();
詳細は references/error-handling.md を参照
API探索
adviseモード(AI支援、推奨)
やりたいことを自然言語で伝えると、どのAPIをどの順序で呼べばよいかAIが回答する。レスポンスの endpoint , api_spec はシステムが自動生成(ハルシネーションなし)。summary , description , body_example , note はAIが生成。
// javascript_tool — やりたいことからAPI手順を取得 (async () => { const r = await fetch('/direct/rcms_api/mng_api/?MODE=advise', { method: 'POST', credentials: 'include', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({request: '記事を新しく作成したい'}) }); const data = await r.json(); return JSON.stringify(data.advice?.steps?.map(s => ({ step: s.step, description: s.description, mt: s.mt, ct: s.ct, http_method: s.http_method, mode: s.mode, endpoint: s.endpoint })), null, 2); })()
discoverモード(構造化JSON、通常不要)
// javascript_tool — モジュール一覧取得(特定モジュールは &mt=topics を追加) (async () => { const r = await fetch('/direct/rcms_api/mng_api/?MODE=discover', {credentials:'include'}); const data = await r.json(); return JSON.stringify(data.modules.map(m => ({mt: m.mt, controllers: m.controllers.map(c => c.ct)})), null, 2); })()
使い分け
方法 用途
llms.txt概要(推奨) サイト全体のAPI構造を把握(最初に使う)
llms.txt詳細 特定モジュールのパラメータ仕様を確認
advise やりたいことからAPI手順をAIが提案(mt/ctが不明な場合に有用)
discover プログラム的にモジュール/コントローラを列挙(通常不要)
詳細は references/api-discovery.md を参照
管理画面ブラウザ操作
API呼び出しだけでは不十分な場合(ファイルアップロード、プレビュー、GUI設定変更等)に使用。
操作手順
-
mcp__claude-in-chrome__navigate で管理画面ページへ移動
-
mcp__claude-in-chrome__read_page でアクセシビリティツリー取得
-
mcp__claude-in-chrome__find / mcp__claude-in-chrome__form_input / mcp__claude-in-chrome__computer でフォーム操作
-
mcp__claude-in-chrome__get_page_text でページ内容取得
主要URL
ページ URL
コンテンツ新規作成 /management/topics/topics_edit/?topics_group_id={id}
コンテンツ編集 /management/topics/topics_edit/?topics_id={id}
コンテンツ一覧 /management/topics/topics_list/?topics_group_id={id}
URLパターンは /management/{module}/{action}/ 。全URL一覧は references/admin-ui-patterns.md を参照
エラーハンドリング
コード 原因 対処
401/403 セッション切れ/権限不足 ログインURL案内、再認証後リトライ
400 不正パラメータ llms.txt詳細で仕様確認、パラメータ修正
404 モジュール/コントローラ不在 discoverで存在確認
500 サーバーエラー リクエスト内容を確認、再試行
Network Error タブが別ドメイン Kurocoドメインのタブで実行しているか確認
詳細は references/error-handling.md を参照
セキュリティ注意事項
-
Cookie値を表示・ログ出力しないこと — セッション情報の漏洩防止
-
document.cookie でのトークン抽出は禁止 — HttpOnlyで取得不可かつ不要
-
変更操作は必ずユーザー確認後に実行 — insert/update/deleteは取り消しが困難
-
APIレスポンスのファイル保存はユーザー同意必須 — 個人情報を含む可能性
-
認証情報をjavascript_toolの出力に含めない — ヘッダーやCookieの内容を返さない
javascript_tool の安全な使い方
ブロックの仕組み
javascript_tool の返却値は chrome拡張のセキュリティフィルタを通過する。以下が検出されると [BLOCKED] に置き換えられる:
-
セッションCookie値、email /login_id 等のセンシティブなクエリパラメータ
-
メールアドレスを含むフィールド値(ext_colに格納されている場合も対象)
-
個人情報を含む大量テキスト
回避ルールと推奨パターン
ルール 理由
返却値は必要最小限に絞る ID・件数・名前のみ等、必要なフィールドだけ抽出
fetch() の生レスポンスをそのまま返さない Cookie関連データが混入する可能性
DOM全体のtextContentを返さない hidden inputやURL文字列にセンシティブ情報が含まれる
URLパラメータが多いページでは注意 URL自体にセンシティブなパラメータ名が含まれるとブロック対象
// ✅ 安全 — mng_apiからcolumns指定+必要フィールドのみ抽出 (async () => { const r = await fetch('/direct/rcms_api/mng_api/?mt=topics&ct=topics_group_list&columns=topics_group_id,group_nm', {credentials:'include'}); const data = await r.json(); return JSON.stringify(data.topics_group_list?.map(g => ({id: g.topics_group_id, name: g.group_nm}))); })();
// ✅ 安全 — メールアドレスは値を返さず判定結果だけ返す (async () => { const target = 'user@example.com'; const r = await fetch('/direct/rcms_api/mng_api/?mt=topics&ct=topics_list&topics_group_id[]=1&cnt=30&columns=topics_id,subject,ext_col_03&keyword=' + encodeURIComponent(target), {credentials:'include'}); const data = await r.json(); return JSON.stringify(data.topics_list?.filter(t => { return (t.ext_col_03 || []).some(v => v && v.includes(target)); }).map(t => ({id: t.topics_id, subject: t.subject}))); })();
ツール別の安全度
ツール ブロックリスク 用途
get_page_text
低 (拡張がフィルタ済みテキストを返す) ページ全文の読み取り
read_page
低 (アクセシビリティツリー、Cookie含まない) DOM構造の把握
javascript_tool
- mng_api JSON 低 (必要フィールドのみ抽出すれば安全) データ操作・API実行
javascript_tool
- fetch() → 生テキスト 高 避ける
javascript_tool
- DOM全文取得 中〜高 (ページ内容による) 特定要素のみ抽出に限定
他スキルとの連携
スキル 用途 使い分け
/kuroco-api-content
フロントエンドAPI設計・認証パターン、コンテンツCRUDパターン エンドユーザー向けAPI
/kuroco-frontend-integration
Nuxt.js/Next.js統合、AI自動デプロイ フロントエンド実装
/kuroco-docs
Kurocoドキュメント参照 公式ドキュメント検索
本スキルはブラウザ経由のmng_api実行と管理画面操作に特化。 フロントエンドAPI(*.g.kuroco.app )の操作には上記の関連スキルを使用すること。