esq-builder-mcp
# esq-builder-mcp
ESQ 1.0 题库包 MCP 工具链:把 [esq-question-bank-import] 技能的确定性环节(构建/校验/上传/词表分析)固化为 MCP 工具,供任意 MCP 客户端(ZCode / Claude Desktop / Codex 等)调用。
## 为什么
技能(SKILL.md)传的是流程知识,LLM 每次执行都可能踩坑(ASCII key、双花括号、上传路径 405……)。本 server 把这些坑固化进工具代码——调用方不会再遇到它们。
| 工具 | 作用 | 固化的坑 |
|:---|:---|:---|
| `esq_build_package` | 校验 + 打包 ESQ ZIP(可选 `auto_fix`) | externalKey 纯 ASCII 3-200 位;`{{blank:N}}` 双花括号;option/candidates key 单大写字母;correctOption 必须存在于选项;cloze 空位数=题数;manifest 必填字段 + semver |
| `esq_validate_package` | 校验 ESQ 包(默认内置校验器,可选官方 CLI 对账) | 双轨校验(见下) |
| `esq_upload_and_publish` | 上传 + 发布到刷题机后端 | 路径写死 `/api/question-banks/imports`(`/upload` 会 405);503 重试 3 次间隔 10s;publish 失败时提示用 job_id 单独重试 |
| `esq_parse_wordlist` | kajweb/dict JSONL 高频词解析(.jsonl 或 book zip) | 逐行 json.loads(整文件 load 报 Extra data);wordRank 排序 |
| `esq_hot_words` | 真题 passage 热点词统计 | 近两年过滤;去停用词;`[a-zA-Z][a-zA-Z'-]{3,}` |
### auto_fix:机械性坑自动修复
`esq_build_package(auto_fix=true)` 在校验前自动修复「纯机械」的坑,修复明细记录在返回值 `fixes` 数组(审计):
- 含中文/非法字符的 packageId/paperKey/unitKey/questionKey → `cn.xxx.y2021.u1` 风格重建,**answers 两级键自动同步改名**
- 单花括号 `{blank:N}` → 双花括号 `{{blank:N}}`
- 缺失的 `unit.sequence` 补 index+1;不达标 blockKey(如 2 位的 `p1`)归一为 `block-{index}`
判断性问题(空位数≠题数、答案不在选项中)**不会**被静默修复,仍走「拒绝 + 可行动错误」。默认 `false` 保持严格行为。
### 双轨校验
`esq_validate_package` 有两条通道,返回值 `validator` 字段标明所用通道:
- **默认:内置校验器**(`esq_validator.py`,vendor 自 backend/app/services/esq.py 校验子集,import 调用)——零外部依赖,PyPI/uvx/PyInstaller 分发可用;
- **对账:官方 CLI**——显式传 `validator_path` 或设 `ESQ_VALIDATOR_PATH` 时走 subprocess 调官方校验器。
两条通道的一致性由 `tests/test_validator_conformance.py` 守护(本机有刷题机仓库时自动执行;后端校验逻辑变更后先跑它再同步 vendored 副本)。
## 安装与运行
```bash
# PyPI(任意 MCP 客户端, 无需 clone)
uvx esq-builder-mcp # stdio 模式
# Windows 单文件 exe: 到 Releases 下载 esq-builder-mcp.exe, 客户端 command 直指该 exe
# 源码方式
cd D:/esq-builder-mcp
uv venv && uv pip install -e ".[dev]"
uv run esq-builder-mcp
```
## 发布新版本
1. bump `pyproject.toml` 的 `version`(PyPI 不允许同版本重传)
2. `git tag v0.1.1 && git push origin v0.1.1` → GitHub Actions 自动 build + 发布(Trusted Publishing,无 token)
3. Windows exe: `uv run python scripts/build_exe.py`,产物 `dist/esq-builder-mcp.exe`,附到对应 Release
> 一次性配置: PyPI 项目 Settings → Publishing 配 Trusted Publisher(Owner=mo9652962-ai / Repository=esq-builder-mcp / Workflow name=publish.yml / Environment=pypi)
## 注册到 MCP 客户端
ZCode(`~/.zcode/cli/config.json` → mcpServers)或其他客户端:
```json
{
"mcpServers": {
"esq-builder": {
"command": "uv",
"args": ["--directory", "D:/esq-builder-mcp", "run", "esq-builder-mcp"]
}
}
}
```
> Windows 下 MCP 命令参数一律用正斜杠路径(Codex config.toml 转义坑的同款规避)。
## 环境变量
| 变量 | 默认 | 说明 |
|:---|:---|:---|
| `ESQ_VALIDATOR_PATH` | (未设) | 设定后 `esq_validate_package` 改走官方校验器 CLI(对账/仲裁通道);默认内置校验器,不需要此变量 |
## 测试
```bash
uv run pytest -v # 35 项;含 vendored vs 官方 CLI 一致性对账(无刷题机环境自动 skip)
```
## 后续演进
- ~~**发布到 PyPI**~~ ✅ 已发布 [pypi.org/project/esq-builder-mcp](https://pypi.org/project/esq-builder-mcp),`uvx esq-builder-mcp` 一行接入(实测冷启动 stdio 握手 5 工具齐全)。
- **ESQ 1.1 examType**:manifest.papers[].examType 已在官方校验器支持,构造器暂未暴露。
- **Windows 单文件 exe**:走 PyInstaller(复用刷题机发布经验)。
## 与技能的关系
- 上游技能:`~/.agents/skills/esq-question-bank-import/SKILL.md`(流程与数据源)
- 本 server 是其「确定性环节」的工具化;AI 标注答案(基元律动)等 LLM 判断环节仍在技能侧。
## 演进记录
- 2026-09-28:校验改双轨(vendored 默认 + 官方 CLI 对账),解除对刷题机仓库路径的运行时依赖,PyPI 分发解锁;`esq_build_package` 增加 `auto_fix` 通道;`esq_parse_wordlist` 支持 book zip 输入。
TDQS
Scored across 5 tools
esq_build_package and esq_validate_package overlap slightly since build also validates, but the descriptions clarify that build produces a ZIP while validate is a standalone check used as a pre-upload step. esq_parse_wordlist and esq_hot_words both deal with word frequency but target clearly different inputs (wordlist JSONL vs passage text).
All tools share the esq_ prefix and mostly follow a verb_noun pattern (build_package, validate_package, upload_and_publish, parse_wordlist). esq_hot_words breaks the pattern as a bare noun phrase, a minor deviation.
Five tools is well-scoped for a package builder/publisher, and each tool earns its place in the build-validate-upload pipeline plus two auxiliary analysis utilities.
The core lifecycle (build, validate, upload/publish) is covered, and the word-frequency helpers round out the domain. Minor gaps exist for listing/managing previously built packages, but the primary workflow has no dead ends.