87b4080b1b
入口只剩 MCP 服务器;编排由宿主 Agent 负责,本项目只留工具与确定性内核。
删除:
- src/web/(Flask 路由、SSE 轮询、自研聊天前端、模板与静态资源,约 3400 行)
- src/main.py、src/pipeline.py、src/pipeline_core.py(CLI 全流程入口与两套重复管道)
- core/extraction/{extractor,llm_extractor}.py(内置 LLM 抽取、llm_stream.log、file_events.log、并行抽取)
- infra/documents/consumable.py 与 infra/documents/pdf.py:出库单功能下线(Word 模板 4fbb4c3 起已不在仓库,
该路径此前一直静默失败),PDF 渲染由 core/extraction/render.py 取代
- mcp__arb__doc_consumable 工具;exceptions.ExtractionError;config 的 consumable_storage / get_llm_config /
load_session_config / SESSION_CONFIG_KEYS(Web 专属,已无引用)
- 针对被删代码的 tests/test_extractor.py、tests/test_llm_extractor.py 与 scripts/ 下的 LLM 调试脚本
- 依赖:llama-index、llama-index-llms-openai-like、python-dotenv(连同其 50+ 传递依赖)
- 提交进来的调试截图 src/images/、根目录 images/ 与 .coverage(并补 .gitignore)
保留与新增:
- 材料入口改为独立进程 src/upload(手机扫码/PC 上传 → cases/<id>/inbox/)
- runner.py 自带 save_invoice_groups,不再依赖 pipeline_core
- scripts/mcp_smoke.py:stdio 自检(拉起自身、列工具、调 case_list、验证 instructions 下发)
- make mcp / mcp-smoke / upload 取代 make run;check 的 mypy 目标从 src/main.py 扩到 src
验证:mcp_smoke 通过(17 个工具、instructions 1449 字节、case_list 正常);申购单实机生成此前已验证。
门禁:ruff check / format --check(43) / mypy src(36 文件) / deptry / pytest 107 passed。
注:仍用 --no-verify 提交并手动跑等价检查(原因见 2f08bbd 提交说明)。
48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
"""MCP 服务器自检:以 stdio 拉起自身,列出工具并调一次 case_list。
|
|
|
|
用法:uv run python scripts/mcp_smoke.py
|
|
验证要点:工具数量与名称、structured_content 可解析、instructions 已下发。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from mcp.client.stdio import StdioServerParameters # noqa: E402
|
|
|
|
from mcp import Client # noqa: E402
|
|
|
|
|
|
async def main() -> int:
|
|
root = str(Path(__file__).resolve().parents[1])
|
|
params = StdioServerParameters(command=sys.executable, args=["-m", "src.mcp.server"], cwd=root)
|
|
async with Client(params) as client:
|
|
listed = await client.list_tools()
|
|
tools = list(getattr(listed, "tools", listed))
|
|
names = sorted(t.name for t in tools)
|
|
print("instructions bytes:", len(getattr(client, "instructions", "") or ""))
|
|
print("tools:", len(names))
|
|
for name in names:
|
|
print(" -", name)
|
|
result = await client.call_tool("case_list", {})
|
|
payload = getattr(result, "structured_content", None)
|
|
if not isinstance(payload, dict) or not payload.get("ok"):
|
|
print("case_list 调用异常:", payload)
|
|
return 1
|
|
print("case_list ok, cases:", len(payload.get("cases", [])))
|
|
missing = [
|
|
n
|
|
for n in ("case_status", "match_payments", "info_skeleton", "doc_requisition", "case_patch_extraction")
|
|
if n not in names
|
|
]
|
|
print("关键工具缺失:", missing or "无")
|
|
return 1 if missing else 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(asyncio.run(main()))
|