Overview
A skill for operating Kuroco's admin API (admin_api) via the claude-in-chrome MCP tool.
admin_api's 5 modes:
- whoami: Retrieve session information (GET) — returns member_id, name, group_ids, expiresAt
- discover: Explore available modules and controllers (GET)
- schema: Retrieve request/response schemas for controllers/services (GET)
- advise: When you describe what you want to do in natural language, the AI answers with the API to call and the procedure (POST)
- execute: Execute the API (GET/POST) —
columnsResponse columns can be selected via parameters
Authentication method: Browser session Cookie (__Host-rcms_api_access_token, HttpOnly).javascript_toolIf you execute fetch() with, the cookie is sent automatically, so token extraction is unnecessary.
Prerequisites:
- claude-in-chrome MCP is available (if not configured, see Step 0 in "Operation Flow" below)
- The user is logged in to the Kuroco admin screen (
https://*.*.kuroco-mng.app) - If the target site is unknown, confirm the site key or admin screen URL with the user to identify it
- All operations are executed with the permissions of the logged-in user
Minimal operation flow (read: 4-5 tool calls, write: 5-6 tool calls):
javascript_tool: Authentication check (MODE=whoami)navigate+get_page_text:/llms.txtto identify the module/controllernavigate+get_page_text:/direct/rcms_api/llms/?mt={module}to retrieve field names and parameter specifications- (when writing)
javascript_tool: Retrieve field types, required fields, and block editor structure with MODE=schemajavascript_tool: Execute the API (mt/ct format)Step 3 is mandatory.
/llms.txt(Overview) only contains the module list, and does not include ext_col field names. To grasp field names, module details are required. Step 4 is mandatory for write operations. The schema isdata.request.propertiesreturns field definitions in JSON Schema format.topics_group_idBy specifying, the required fields of ext_col/block editor become clear. discover mode is normally unnecessary. The two stages of llms.txt (overview → details) provide sufficient information.
Operation Flow
All API operations must follow this flow.
Decision before starting an operation: When receiving a request from the user such as "check ~", "search for ~", or "look at the data for ~", first determine whether it can be resolved by **data retrieval (API)**. Even if the admin screen UI is right in front of you, do not reflexively start clicking. Data that can be retrieved via API should be retrieved via API. Use UI browser operations only for operations that are impossible via API (file uploads, previews, GUI-specific setting changes, etc.).
Step 0: Check claude-in-chrome MCP
This skill mcp__claude-in-chrome__* Depends on the tool set. Before starting operations, check whether these tools are available.
How to check: mcp__claude-in-chrome__tabs_context_mcp .
- If successful → proceed to Step 1
- If the tool is not found / connection error → guide the user through setup:
ブラウザ操作に必要な claude-in-chrome MCP が利用できません。
以下の手順でセットアップしてください。
【必要なもの】
1. Google Chrome または Microsoft Edge
2. Claude in Chrome 拡張機能(v1.0.36以上)
→ Chrome Web Store からインストール:
https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn
3. Claude Code v2.0.73 以上
【有効化の手順】
- Claude Code セッション内で `/chrome` を実行
- または `claude --chrome` で起動
セットアップ完了後、もう一度お試しください。
Note: Chrome integration requires a direct Anthropic plan (Pro, Max, Teams, Enterprise). It is not available via third-party providers (Amazon Bedrock, Google Cloud Vertex AI, etc.).
Step 1: Identify the target site
mcp__claude-in-chrome__tabs_context_mcpand look for a tab matching the URL pattern *.*.kuroco-mng.app .
- If one tab is found → base URL from that tab's URL (
https://{site_key}.{env}.kuroco-mng.app) and use it in subsequent operations - If multiple Kuroco tabs are found → ask the user which site to operate on
- If no tab is found →
AskUserQuestiontools to check the site key or admin panel 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
}]
}
Identify the base URL from the user's answer, and open the admin panel withmcp__claude-in-chrome__tabs_create_mcp :
- If a URL is provided → extract the host part from the URL (e.g.:
https://demo.g.kuroco-mng.app) - If a site key is provided → construct
https://{site_key}.{env}.kuroco-mng.app(confirm the env with the user, default isg)
Note: All operations are executed with the permissions of the user logged in to the browser. Models or methods that user does not have access to cannot be operated.
Step 2: Authentication check (lightweight request)
mcp__claude-in-chrome__javascript_toolto execute the following:
(async () => {
const r = await fetch('/direct/rcms_api/admin_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});
})()
Important:
javascript_toolIn top-levelawaitcannot be used. Because it evaluates in the page context, when usingawaitalways write(async () => { ... })()Wrap with . At top levelawait,SyntaxError: await is only valid in async functions.
MODE=whoamiis a lightweight endpoint that returns session information (member_id, name1, name2, group_ids, expiresAt). It allows you to obtain the logged-in user's permission information at the same time as verifying authentication.
Step 3: Understand site structure via llms.txt (required)
navigate + get_page_text to read llms.txt. A single request yields the following:
- List of all modules and controllers
- Site map of content definitions, APIs, forms, etc.
- How to use admin_api and parameter specifications
- Workflow examples
navigate → /llms.txt
get_page_text → サイト全体の構造を取得
Note:
- Always check llms.txt before going through admin panel pages. Most structural information can be obtained here (discover mode is usually unnecessary)
- llms.txt is provided by KurocoGenerates dynamically based on the logged-in user's permissions. APIs outside the user's permissions are not displayed
/llms.txt(overview) contains only the module list. ext_col field names are obtained in the next Step 3.5
Step 3.5: Understand field names via module details (required)
Once the module to operate on is identified,AlwaysRead the module details and understand the field names.
navigate → /direct/rcms_api/llms/?mt={module}
get_page_text → ext_colのフィールド名、Available Columns、パラメータ仕様を取得
Do not skip this step. The field names for ext_col_01–20 (e.g., ext_col_03 = to, ext_col_04 = cc) are only described in the module details. Traversing the admin screen DOM or guessing the contents of API responses is inefficient and causes errors.
Step 4: Schema Retrieval (Required for Write Operations)
When performing write operations (INSERT/UPDATE), always retrieve the schema and check the field structure. In particular, for content definitions that have a block editor or extended fields (ext_col), required field names and types can only be determined from the schema.
Important: The schema response is in JSON Schema format.
data.requestThere is no field information directly under it.data.request.propertiescontains the field definitions, anddata.request.requiredcontains the required fields.
To retrieve fields specific to a content definition, specify topics_group_id :
// javascript_tool — topics_group_id指定でext_col含むフィールド一覧を取得
(async () => {
const r = await fetch('/direct/rcms_api/admin_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);
})();
Note:
topics_group_idIf you omit it, only generic fields are returned (ext_col is not included)topics_group_idIf you specify it, you can retrieve the field names for the block editor and extended items (ext_1,ext_14etc.), types, and required flags- list-type controllers (
topics_listetc.) return an empty schema, so specify a write controller (topics_edit)- Response
x-kuroco-typelets you determine the field type (wysiwyg,json,checkbox,fileetc.)
Step 5: API Execution
Once authentication confirmation and structure understanding are complete, execute the API according to theAPI execution patterns.
Step 6: Handling Authentication Failure / Session Expiration
If 401 or 403 is returned:
- Tell the user that login is required
- Login URL:
{base_url}/management/login/login/(base_url is obtained from the tab URL) - Wait until the user logs in
- Check authentication again after login
If 401/403 occurs during a multi-step operation:
- Stop the operation immediately
- Report to the user how far the operation succeeded
- Guide them through re-authentication
- After re-authentication, resume from the incomplete operation
Criteria for Choosing a Method (Most Important)
Principle: If the purpose is data retrieval, search, or filtering, use the API rather than the UI.
Even if the admin screen is open in the browser, clicking UI elements to find information is a human operation method, not an AI agent's operation method. The browser session cookie is also automatically sent with javascript_tool の fetch() , sothe authentication cost is the same for UI navigation and API calls。
| Purpose | Method | Reason |
|---|---|---|
| Retrieving, searching, and filtering data lists | API(admin_api) | Structured JSON, programmatically processable |
| Detailed confirmation of specific content | API(admin_api) | Can retrieve only necessary items by specifying columns |
| Understanding site structure and API specifications | llms.txt | Can grasp the whole picture in one go |
| File upload, preview, GUI-specific setting changes | UI browser operations | Only operations not possible via API |
Anti-pattern
| Common mistake | Problem | Recommended |
|---|---|---|
| Clicking UI elements on the admin screen to search and browse data | Merely imitating human operations. Slow, and results are not structured in HTML. Does not lead to improvement or automation | Retrieve JSON with admin_api's fetch(). Since the same session cookie can be used, there is no reason to go through the UI |
columnsGET request without specifying |
The response is huge and gets blocked | Alwayscolumns=必要カラムspecify (if it doesn't work,.map()to extract) |
fetch() to get HTML → parse with DOMParser |
The Vue.js rendering part becomes empty | Retrieve JSON with admin_api |
document.querySelector('main').textContent to get the full text |
Risk of Cookie blocks | Extract only the necessary data |
Top-level await use |
SyntaxError becomes |
Always (async () => { ... })() wrapped with |
| Returning field values containing email addresses as-is | [BLOCKED] becomes |
.includes() Return only the determination result with |
Object.keys(data.request) to find the fields of the schema |
Since it is in JSON Schema format, type,properties,required is all that is returned |
data.request.properties to get the field list |
When retrieving the schema, topics_group_id omit |
Only generic fields, and ext_col is not included | &topics_group_id={id} specify to get fields specific to the content definition |
API Execution Patterns
Parameter Format
In admin_api, mt(module) and ct(controller) format.
| parameter | Description | Example |
|---|---|---|
mt |
Module name (lowercase) | topics, member, inquiry |
ct |
Controller name | topics_list, topics_edit, member_list |
Note:
model=Topics&method=listDo not use the format. HTML may be returned. Alwaysmt/ctuse the format.
GET Requests (List Retrieval/Search)
// javascript_tool — columns + cnt で必要最小限のレスポンスを取得
(async () => {
const r = await fetch('/direct/rcms_api/admin_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 Principle: For GET requests, always
columnsspecify. On supported endpoints, server-side filtering is performed; even if unsupported, it is simply ignored, so there is no problem in always specifying it. If it does not work, on the client side.map()to extract.columnsis exclusive to execute mode (not applied to discover mode).
POST Requests (Create/Update/Delete)
// javascript_tool — MODE=INSERTで新規作成
(async () => {
const r = await fetch('/direct/rcms_api/admin_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);
})()
Important Rules
| rule | Description |
|---|---|
| credentials | For all requests, credentials: 'include' required |
| Parameter Format | Always mt/ct use format (model/method format not allowed) |
| GET array parameters | [] suffix required (e.g., topics_group_id[]=1) |
| POST array parameters | native JSON array (e.g., {"topics_group_id": [1]}) |
| Result count limit | If the response is large, cnt limit with parameter |
| columns specification | columns=col1,col2 minimize response columns with .Always specify on supported endpoints(countermeasure for javascript_tool output limits / response efficiency). Some endpoints do not support it, in which case extract on the client side |
| Confirmation of change operations | insert/update/deleteはConfirm with the user before executiondo it |
| Response truncation | javascript_toolBecause of output limits, extract only the necessary parts from large responses |
When the response structure is unknown
.map() before doing Object.keys() check the structure with . Do not guess property names and try multiple times; grasp the structure in one go:
(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);
})();
For details, see references/error-handling.md For details, see
API exploration
advise mode (AI-assisted, recommended)
If you explain what you want to do in natural language, the AI answers which APIs to call in which order. The response's endpoint, api_spec is auto-generated by the system (no hallucination).summary, description, body_example, note is generated by AI.
// javascript_tool — やりたいことからAPI手順を取得
(async () => {
const r = await fetch('/direct/rcms_api/admin_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 mode (structured JSON, usually unnecessary)
// javascript_tool — モジュール一覧取得(特定モジュールは &mt=topics を追加)
(async () => {
const r = await fetch('/direct/rcms_api/admin_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);
})()
How to use them separately
| Method | Purpose |
|---|---|
| llms.txt overview(recommended) | Grasp the API structure of the entire site (use first) |
| llms.txt details | Check the parameter specifications of a specific module |
| advise | AI suggests API procedures from what you want to do (useful when mt/ct are unknown) |
| discover | Programmatically enumerate modules/controllers (usually unnecessary) |
For details, see references/api-discovery.md For details, see
Admin panel browser operations
Used when API calls alone are insufficient (file uploads, previews, GUI setting changes, etc.).
Procedure
mcp__claude-in-chrome__navigateNavigate to the admin panel page withmcp__claude-in-chrome__read_pageGet the accessibility tree withmcp__claude-in-chrome__find/mcp__claude-in-chrome__form_input/mcp__claude-in-chrome__computerOperate forms withmcp__claude-in-chrome__get_page_textGet page content with
Main URLs
| Page | URL |
|---|---|
| Create new content | /management/topics/topics_edit/?topics_group_id={id} |
| Edit content | /management/topics/topics_edit/?topics_id={id} |
| Content list | /management/topics/topics_list/?topics_group_id={id} |
The URL pattern is
/management/{module}/{action}/. For the full URL list, refer to references/admin-ui-patterns.md Refer to
Error handling
| Code | Cause | Action |
|---|---|---|
| 401/403 | Session expired/insufficient permissions | Guide to login URL, retry after re-authentication |
| 400 | Invalid parameter | Check specifications in llms.txt details, fix parameters |
| 404 | Module/controller not found | Check existence with discover |
| 500 | Server error | Check request content, retry |
| Network Error | Tab is on a different domain | Check whether you are executing in a Kuroco domain tab |
For details, refer to references/error-handling.md Refer to
Security notes
- Do not display or log Cookie values — Prevent session information leakage
document.cookieExtracting tokens with — Not obtainable due to HttpOnly and unnecessary- Always perform change operations after user confirmation — insert/update/delete are difficult to undo
- Saving API response files requires user consent — May contain personal information
- Do not include credentials in javascript_tool output — Do not return header or Cookie contents
Safe usage of javascript_tool
Blocking mechanism
javascript_tool The return value of passes through the chrome extension's security filter. If the following are detected, it is replaced with [BLOCKED] :
- Session Cookie values,
email/login_idSensitive query parameters such as - Field values containing email addresses (also applies when stored in ext_col)
- Large amounts of text containing personal information
Bypass rules and recommended patterns
| Rule | Reason |
|---|---|
| Limit return values to the minimum necessary | Extract only necessary fields, such as IDs, counts, and names only |
| Do not return the raw fetch() response as-is | Cookie-related data may be mixed in |
| Do not return the textContent of the entire DOM | Sensitive information may be contained in hidden inputs or URL strings |
| Caution on pages with many URL parameters | If sensitive parameter names are included in the URL itself, it is subject to blocking |
// ✅ 安全 — admin_apiからcolumns指定+必要フィールドのみ抽出
(async () => {
const r = await fetch('/direct/rcms_api/admin_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/admin_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})));
})();
Safety level by tool
| Tool | Blocking risk | Use |
|---|---|---|
get_page_text |
Low (the extension returns filtered text) | Reading the full page text |
read_page |
Low (accessibility tree, does not include cookies) | Understanding the DOM structure |
javascript_tool + admin_api JSON |
Low (safe if only necessary fields are extracted) | Data manipulation / API execution |
javascript_tool + fetch() → raw text |
High | Avoid |
javascript_tool + full DOM retrieval |
Medium–High (depends on page content) | Limit to extracting only specific elements |
Cooperation with other skills
| Skill | Use | How to use them differently |
|---|---|---|
/kuroco-api-content |
Frontend API design/authentication patterns, content CRUD patterns | End-user-facing API |
/kuroco-frontend-integration |
Nuxt.js/Next.js integration, AI automated deployment | Frontend implementation |
/kuroco-docs |
Refer to Kuroco documentation | Search official documentation |
This skill specializes in executing admin_api via the browser and operating the admin screen. For operations on the frontend API (*.g.kuroco.app), use the related skills above.