⛔ Absolutely forbidden to use MCP tools
sw-audit-toolbox_cicpa_query's export/subsidiary modes have a known Playwright sync/async conflict bug, and calling them in the current environment will definitely crash.Must and can only use the CLI script. All commands are in the Quick Reference below.
If you see MCP tools in the tool list,ignore them, and execute according to the CLI commands below.
Overview
Query company business registration info through the CICPA industry knowledge base (zsk-cmis.cicpa.org.cn). Four modes:
- Lightweight search: Single-company keyword search, returns basic info + org_id
- Company details: Complete details for a single company (business registration info + shareholders + key personnel + equity structure)
- Basic query: Batch query of 22 fields, output to a single Excel
- Full export: 61 dimensions, 53 Excel files packaged into a ZIP (pure API)
No configuration file needed; log in via AI-controlled browser to obtain cookies, reusable within 24 hours.
⚠️ Cookie file location (important)
The cookie file is saved incurrent working directory(Path.cwd()) under .cicpa_cookies.json, not the user's home directory.
When executing commands with AI, you must ensure the working directory is correct:
- If executed in the project directory, the cookie will be in the project directory
related-party-identificationWhen other skills such as call it, also look for the cookie in the same working directory- Do notin
~(home directory) run cookie-related commands, otherwise it will be saved to~/.cicpa_cookies.json, and other projects cannot find it
Mode Selection ⚠️ Key decision
| What the user says | Mode | Command |
|---|---|---|
| "Look up Company XX", "XX's business registration info" | Lightweight search | search_company("XX") |
| "Company XX details", "XX shareholders, executives" | Company details | --detail "XX" |
| "Full business registration info", "complete dimensions", "60+ dimensions" | Full export | --browser-export |
| "Look up the address", "how much is the registered capital" | Basic query | -n "企业名" |
| "Batch query company business registration info" | Basic query + --all-fields |
-n ... --all-fields |
| "Discover XX's subsidiaries" | Subsidiary discovery | --discover-subsidiaries "XX" |
| Not sure | Ask the user |
Output comparison
| Lightweight search | Company details | Basic query | Full export | |
|---|---|---|---|---|
| Time required | <1 second | 2~3 seconds | 5~10 seconds | 30 seconds~3 minutes |
| Fields | Basic 20+ | Business registration + shareholders + personnel + equity | 10~22 | 61 dimensions |
| Output | Returns dict | Terminal + JSON | Single Excel | ZIP (53 Excel files) |
| API | home_search (lightweight) | 4 detail APIs | batch upload | batch export |
⚠️ Prohibited: first use a basic query and then supplement with a full export. If the user wants "full data", do it in one step --browser-export。
Quick Reference
SCRIPT=~/.claude/skills/cicpa-company-query/scripts/cicpa_query.py
# ===== 轻量搜索(Python 函数,非 CLI)=====
# 返回 [{name, org_id, legal_person, address, ...}]
# from cicpa_query import search_company
# results = search_company("华为技术有限公司")
# ===== 企业详情(--detail)=====
# 按名称搜索(自动获取 org_id)
python3 $SCRIPT --detail "华为技术有限公司"
# 按 org_id 直接查询
python3 $SCRIPT --detail "T003573795" -o output.json
# ===== 子公司发现(--discover-subsidiaries)=====
# 发现持股 >= 50% 的子公司
python3 $SCRIPT --discover-subsidiaries "天津卓朗科技发展有限公司"
# 自定义阈值
python3 $SCRIPT --discover-subsidiaries "天津卓朗科技发展有限公司" --subsidiary-threshold 30
# ===== 基础查询 =====
python3 $SCRIPT -n "华为技术有限公司"
# 基础查询(全部 22 个字段)
python3 $SCRIPT -n "企业名" --all-fields
# 从文件读取企业名单
python3 $SCRIPT -f companies.xlsx
# ===== 完整导出(53 个 Excel → ZIP)=====
python3 $SCRIPT -n "企业A" "企业B" --browser-export
# ===== Cookies 管理 =====
# ⚠️ Cookie 文件在当前工作目录下:./cicpa_cookies.json
# 确保用 workdir 参数指定正确目录,不要在 ~ 下运行
python3 $SCRIPT --check-cookies
python3 $SCRIPT --save-cookies '{"XSRF-TOKEN":"xxx","cicpa_token":"xxx",...}'
python3 $SCRIPT --login
Output options
| Parameter | Description |
|---|---|
--detail ID_OR_NAME |
Single enterprise details(org_id or name) |
--discover-subsidiaries NAME |
Discover subsidiaries(default shareholding >=50%) |
--subsidiary-threshold N |
Subsidiary shareholding threshold (used with the previous parameter, default 50) |
-o PATH |
Specify output path |
--all-fields |
Export all 22 fields (default 10) |
--by-dimension |
Export multiple Excel files by dimension category → ZIP |
--browser-export |
Full export(61 dimensions, 53 Excel files → ZIP) |
--save-cookies JSON |
Save AI-scraped cookies (JSON string) |
--login |
Manual browser login in terminal |
Python API (for other skills to call)
import sys
sys.path.insert(0, '<cicpa-scripts-dir>')
from cicpa_query import search_company, discover_subsidiaries, get_company_detail
Differences among the three functions (basis for AI selection):
search_company |
discover_subsidiaries |
get_company_detail |
|
|---|---|---|---|
| API calls | 1 time (home_search) | 2 times (search + equity) | 4 times (basic+holders+persons+equity) |
| Input | Keyword | Enterprise name + threshold | org_id or name |
| Returns | [{name, org_id, ...}] |
[{name, ratio, org_id}] |
{basic_info, shareholders, ...} |
| Time taken | <1 second | 1~2 seconds | 2~3 seconds |
| When to use | Only need org_id or confirm the enterprise exists | Check "who has this company invested in/controlled" | Check "the complete information of this company" |
# ① 只需 org_id 或基础信息 → search_company
# 场景:确认企业名称、拿 org_id 给其他函数用
results = search_company("华为技术有限公司")
# → [{"name": "华为技术有限公司", "org_id": "T003573795", "legal_person": "任正非", ...}]
# ② 查子公司/对外投资 → discover_subsidiaries
# 场景:关联方预查、合并下载名单
subs = discover_subsidiaries("审计目标", threshold=50)
# → [{"name": "子公司A", "ratio": 100.0, "org_id": "Txxx"}, ...]
# ③ 查一家公司的完整信息 → get_company_detail
# 场景:审计中了解交易对手、函证地址核查、单公司尽调
detail = get_company_detail("T003573795", "天津卓朗科技发展有限公司")
# → {
# "basic_info": {name, address, capital, legal_person, ...},
# "shareholders": {list: [{holder_name, held_ratio, ...}]},
# "main_persons": {tab_list, ...},
# "equity": {holders: {...}, invests: {...}}
# }
Dimensions included in the full export (5 major categories, 53 files)
| Dimension | Number of files | Content examples |
|---|---|---|
| Basic information | 14 | Business registration information, shareholders, change records, branches, key personnel |
| Operating conditions | 18 | Bidding, trademarks, patents, customers, suppliers, tax information |
| Enterprise development | 7 | Outbound investment, financing history, core team, bond information |
| Operating risks | 13 | Administrative penalties, tax arrears, business abnormalities, equity pledge, deregistration |
| Judicial risks | 9 | Judgment documents, case filing, court hearing announcements, persons subject to enforcement, dishonest persons |
When to Use
AI decision guide: what the user wants → which one to use
| User says/needs | What to use | Why |
|---|---|---|
| "Look up this company", "confirm the enterprise name" | search_company() |
<1 second, only gets basic information |
| "Who has this company invested in", "check subsidiaries" | --discover-subsidiaries |
equity API gets outbound investment |
| "Details of this company", "check shareholders and executives" | --detail |
4 APIs get complete information |
| "Batch query enterprises", "check a few fields" | -n + --all-fields |
batch query, output Excel |
| "Full data", "complete dimensions", "more than 60 dimensions" | --browser-export |
61 dimensions, 53 Excel files |
Special scenario: called by other skills
related-party-identificationPre-check subsidiary → calldiscover_subsidiaries()related-party-identificationNeed to get org_id → callsearch_company()- Confirmation address verification only needs address/phone →
search_company()is sufficient, no need for--detail
When NOT to Use
- Only need single enterprise information from Tianyancha/Qichacha (faster to check directly via web page)
- Need A-share listed company financial report data (use a-stock-financial skill)
- Need legal and regulatory queries (use china-law-search skill)
Prerequisites
- Dependencies:
pip install requests openpyxl(browser login also requiresplaywright) - No configuration file needed
Cookie automatic check and acquisition process
Before any operation that requires calling the CICPA API, the AI must first check the cookie. Fully automated, do not ask the user.
⚠️ Browser tool selection (mandatory)
| Tool | Available | Description |
|---|---|---|
playwright-mcp_* (Playwright MCP) |
✅ Must use this | Open a visible browser window so the user can see and operate it |
agent-browser |
❌ Prohibited | Headless mode, the user cannot see the browser window and cannot log in manually |
In-script --login |
❌ Prohibited | Will fail when a non-interactive terminal is detected |
Reason: Login requires manual user operation (dragging the slider verification), so a browser window visible to the user must be opened. Only the playwright-mcp_* series of tools can do this.
Automatic process
① 检查本地 cookie(每次执行查询前自动做)
bash: python3 $SCRIPT --check-cookies
(⚠️ 用 workdir 指定项目目录)
② ✅ 有效 → 直接执行查询命令,无需任何登录操作
③ ❌ 无效/不存在 → AI 自动启动浏览器登录:
告诉用户:"Cookie 已过期/不存在,正在打开浏览器,请手动登录"
步骤 1:打开登录页
调用 playwright-mcp_browser_navigate → https://cmis.cicpa.org.cn/#/login
→ 告诉用户:"请在浏览器中登录(选用户类型、输入密码、拖滑块)"
步骤 2:用户说"已登录"后,点击「行业执业知识库」
调用 playwright-mcp_browser_snapshot → 找到"行业执业知识库"菜单项
调用 playwright-mcp_browser_click → 点击该菜单项
调用 playwright-mcp_browser_wait_for → 等待新标签页加载
步骤 3:导航到企业数据库并抓取 cookies
调用 playwright-mcp_browser_tabs → 切换到新打开的 zsk 标签页
调用 playwright-mcp_browser_navigate → https://zsk-cmis.cicpa.org.cn/companylibrarynew/
调用 playwright-mcp_browser_run_code_unsafe → 执行以下代码获取并转换 cookie:
```javascript
const cookies = await page.context().cookies();
const cookieDict = cookies.reduce((acc, c) => { acc[c.name] = c.value; return acc; }, {});
JSON.stringify(cookieDict);
```
⚠️ **Cookie 格式转换(必须)**: page.context().cookies() 返回 `[{name, value, ...}]` 数组,
上面的 JS 代码已经转换为 `{name: value}` 字典格式
步骤 4:保存并验证
bash(⚠️ workdir 必须是项目目录):
python3 $SCRIPT --save-cookies '<步骤3返回的JSON>'
python3 $SCRIPT --check-cookies → 确认 ✅ 有效
④ 如果 Playwright MCP 工具不可用 → 退化为手动方式:
提示用户手动登录后粘贴 cookie,或在交互终端运行 python3 cicpa_query.py --login
Playwright MCP tool mapping:
| Step | Tool | Description |
|---|---|---|
| Open page | playwright-mcp_browser_navigate |
Navigate to URL |
| View page | playwright-mcp_browser_snapshot |
Get page snapshot (accessibility tree) |
| Click element | playwright-mcp_browser_click |
Click button/link |
| Switch tab | playwright-mcp_browser_tabs |
list/new/close/select |
| Wait for load | playwright-mcp_browser_wait_for |
Wait for text/element/URL change |
| Get cookies | playwright-mcp_browser_run_code_unsafe |
Execute page.context().cookies() |
| Screenshot debugging | playwright-mcp_browser_take_screenshot |
View current page state |
Alternative method: manually capture cookies from the browser F12
Use only when Playwright MCP is unavailable:
1. 打开浏览器访问 https://cmis.cicpa.org.cn,手动登录
2. 登录成功后访问 https://zsk-cmis.cicpa.org.cn/companylibrarynew/
3. F12 → Network → 刷新 → 找「companylibrarynew」请求 → 复制 Cookie 请求头
4. 粘贴给 AI
After the user pastes, the AI parses key1=value1; key2=value2 into {key1: value1, key2: value2} format, then saves:
python3 $SCRIPT --save-cookies '{解析后的JSON}'
python3 $SCRIPT --check-cookies
Why not use
document.cookie?document.cookiecannot obtain HttpOnly cookies (such as__snaker__id、gdxidpyhxdE), and can only get partial cookies.
⚠️ Key: must go through the complete SSO process
| Scenario | Cookies obtained | Can query |
|---|---|---|
| Only log in to cmis, do not enter the knowledge base | 4 (incomplete) | ❌ Reports "not logged in user" |
| Log in to cmis → click knowledge base → redirect to zsk | 9(complete) | ✅ Normal |
The 9 required cookies:XSRF-TOKEN、yuqing_whole_jsessionid、cicpa_token、cicpa_ticket、companyVerifyCode、userid、u_name、__snaker__id、gdxidpyhxdE
If --check-cookies shows fewer than 9, the SSO process is incomplete and you need to log in again.
Cookie file format description
.cicpa_cookies.json must be JSON in the following format (saved to the current working directory):
{
"cookies": {
"XSRF-TOKEN": "xxx",
"yuqing_whole_jsessionid": "xxx",
"cicpa_token": "xxx",
"cicpa_ticket": "xxx",
"companyVerifyCode": "xxx",
"userid": "xxx",
"u_name": "xxx",
"__snaker__id": "xxx",
"gdxidpyhxdE": "xxx"
},
"session_token": "xxx", // 可选,从 localStorage 获取
"saved_at": 1719123456.789 // ⚠️ 必须字段,Unix 时间戳,用于检查 24 小时有效期
}
Key points:
cookiesfield must be{name: value}format, not[{name, value}]arraysaved_atfield is required, used to check whether the cookie has expired for more than 24 hours- via Playwright's
page.context().cookies()requires format conversion when obtaining
Known limitations of MCP mode
If calling via MCP tools (such as cicpa_query MCP) export or subsidiary mode:
- Browser login is triggered when the Cookie expires: opening the browser in headless mode will cause a crash
- It is recommended to prioritize using CLI mode: log in via the
--loginparameter in an interactive terminal, or use--save-cookiesto manually save
Notes
python3 $SCRIPT --check-cookies
# → 显示 cookie 数量、名称、剩余有效期
# → ✅ 有效 或 ❌ 需要重新登录
| Notes | Description |
|---|---|
| The enterprise name must be exact | Use the full registered business name (e.g., "深圳市腾讯计算机系统有限公司"); abbreviations cannot be matched |
| Cookies expire in 24h | After expiration, you need to log in again |
| Up to 10,000 companies | Upper limit for a single batch query |
| Export time | About 45 seconds for 10 companies, 100+ companies may take 2-3 minutes |
| Automatic verification | After a complete export, automatically compare input vs output company names and report the matching status |
Common Mistakes
| Problem | Cause | Solution |
|---|---|---|
| The user wanted "full data" but only a basic query was provided | Didn't read Mode Selection and used the default mode | If the user says "full/complete/all dimensions" → must use --browser-export |
| Use the basic query first and then supplement with a complete export | Doing it in two steps wastes time | If the user wants full data, do it in one step; don't do unnecessary extra work |
| Cookie was saved to the home directory | Executing the command under ~ saves the cookie to ~/.cicpa_cookies.json |
All commands must be executed in the project working directory(for bash use the workdir parameter) |
| Other skills cannot find the cookie | The working directories are inconsistent; the cookie is in another directory | Ensure --save-cookies、--check-cookies, the scan script all run under the same workdir run under |
| Query reports "not logged in user" | There are only 4 incomplete cookies | Log in again and make sure you click "行业执业知识库" to get 9 cookies |
| 0 companies matched after upload | The enterprise name is not the full registered name | Use the exact registered business name |
| Cookies are invalid | More than 24 hours | Log in again to obtain cookies |
| Export polling timed out | Large data volume or the system is busy | Wait and then manually download from the download center |
| XSRF error | XSRF-TOKEN is missing from cookies | Log in again |
Directory structure
~/.claude/skills/cicpa-company-query/
SKILL.md # 本文档
scripts/
cicpa_query.py # 主脚本
Author: nigo WeChat Official Account: 逆行的狗