stcc-mcp
stcc-mcp — 电话分诊分级:规则确定性算,0.6B 只核对判据
一段问诊记录进去,出 L1–L5 档位 + 处置措辞 + 逐条引文 + 还缺哪几条判据。
分级由确定性规则引擎算出(225 份 STCC 协议 / 849 分支 / 4,168 条判据,随包分发),
Qwen3-0.6B 只回答一件事:给定记录和一条判据,yes / no / unknown。
模型不选分支、不定档位、不生成处置措辞、不做 tool call。
⚠️ 不是急诊分诊系统,不做诊断,不能替代医生。L1–L5 是处置阶梯 (叫救护车 / 立即急诊 / 今天就医 / 近两日门诊 / 居家观察)。紧急情况直接拨 120。
三步跑起来
pip install stcc-mcp # 或 uvx stcc-mcp …
ollama pull hf.co/chenhaodev/stcc-checker-0.6b-GGUF:Q8_0 # 640MB 核对器
stcc-mcp doctor # 自检:索引 / Ollama / 模型
stcc-mcp triage --protocol Chest_Pain.md "$(cat 记录.txt)"零常驻进程、零 Docker、不联网。引擎是纯标准库,无第三方依赖。
第一次运行大概率会看到 tier: L1 + certain: false —— 这是对的
拿一段普通问诊记录进去,很可能得到最紧急档加一串 unresolved。不是判错:
引擎只有在某支全部条件都为 no 时才敢排除它,而一次真实问诊不会把一支的判据问完。
例如轻症发热的记录里护士问了意识/呼吸/颈硬/皮疹,却从没问过脱水体征
(排尿减少、眼窝凹陷、皮肤张力差、口渴),于是该支排除不掉,输出停在它的档位上界。
unresolved 就是"再问这几条就能收紧"的清单。 把答案补进记录重跑,
unresolved 会单调变短;但档位只有在某支被完全排除时才会降——
实测同一份发热记录补齐脱水体征后 unresolved 8→2,档位仍停在 L1,
因为剩下的主干(老年人或免疫低下者…脱水表现: 这种半截话)核对器给的是 unknown。
这时候该动的是下面那个阈值旋钮,不是继续问。详见边界 ①②。
接进 agent(Claude Code / 任何 MCP client):
pip install "stcc-mcp[mcp]" && stcc-mcp serve # stdio MCPOllama 不支持 MCP,而这对本形态不是问题:小模型从不 tool call, 编排层分别去调 Ollama(HTTP)和规则引擎(进程内),两者互不相识。 0.6B 自主 tool-calling 是已知重灾区,这个架构从设计上绕开了它。
Related MCP server: Quellgeist
输出
字段 | 含义 |
|
|
| 该分支的处置措辞(来自规则表,不是模型生成) |
|
|
| 判定依据的判据 + 行号,可审计 |
| 还缺哪几条判据 —— 补问它们就能收紧档位 |
档位到行动的映射由你的编排层定;本包只给档位与处置措辞。
判 no 的门槛是一个旋钮
--no-threshold(默认 0.63):P(no) ≥ τ ⇒ no,否则在 yes/unknown 里取大者。
同一个模型在发布分布(n=3225)上的整条取舍曲线:
τ | acc |
|
|
0.63(默认) | 0.9426 | 0.0000 | 0.9027 |
0.50 | 0.9457 | 0.0000 | 0.9189 |
0.40 | 0.9495 | 0.0024 | 0.9378 |
0.30 | 0.9498 | 0.0084 | 0.9432 |
0.10 | 0.9516 | 0.0120 | 0.9635 |
同一段发热问诊记录,只改 τ:
$ stcc-mcp triage --protocol Fever_Adult.md --no-threshold 0.63 "$(cat 记录.txt)"
tier L1 · 拨打救护车 · unresolved 2
$ stcc-mcp triage --protocol Fever_Adult.md --no-threshold 0.40 "$(cat 记录.txt)"
tier L3 · 2小时内接受医疗护理 · unresolved 5τ 调低 ⇒ 核对器更敢把"问过且被否认"的判据判成 no ⇒ 分支被排除 ⇒ 档位下降。
这不是让模型更准,是在同一条取舍曲线上换工作点——换来的是漏诊风险上升。
false_no(该成立却判成 no)是硬门——假 no 会把真值分支从安全收敛里排除掉。
少判 no 只造成过分诊,是成本旋钮。
⚠️ 默认 τ=0.63 是经验工作点,不是统计上"控制住了"的阈值。
按 Neyman-Pearson 范式(Tong et al., Sci Adv 2018, arXiv:1608.03109),
要以 95% 置信把 false_no 控制在 0.0036 以下,dev 需 ≥831 条正例;我们只有 495——
即便最保守的阈值,真实 false_no 超标概率仍有 16.8%,495 条只能可靠控制到 α≈0.006。
文献还点名了我们用的那种选法(直接限制经验 type I error ≤ α)不构成控制。
⇒ 当工作点用,别当保证用;曲线一起给出,按自己的代价矩阵挑点。
python -m scripts.threshold_sweep --pick-tau 会自己报可行性。
复现:python -m scripts.threshold_sweep --model <m> --split <s> --collect --report。
🔴 已知边界(先读这段再决定用不用)
① 「该用哪份协议」这一步本包不提供。
--protocol 是必填参数,需要调用方给——完整链路里这一环是空的:
一段问诊记录 ──[?? 谁来选协议 ??]──► protocol_id ──► 本包(引擎 + 核对器)──► L1–L5
↑ 缺这一环推荐形态:编排层用一个大模型看中文标题菜单来选(stcc-mcp protocols 可打印,225 份)。
上一轮(run1,221 份协议的菜单,34 条真实自述)实测:大模型菜单选择
@1 = 0.85(原文直选)/ 0.94(先抽一句主诉再选)· @2 = 1.00;
而用判据文本做向量检索定协议只有 @1 = 0.18 —— 同一句判据(如"恶心或呕吐")
跨几十份协议出现,判据级索引天然定不了协议,这条路已证伪,别再走。
选错协议时引擎的 referral / indeterminate 状态是自纠网,但那是网,不是替代。
② 输入必须是「已按协议问过一轮」的记录,不是原始自述。
短主诉 unknown 率 94%;真实富对话(IMCS-21,748 字 / 40 轮)仍有 88%。
原因是 STCC 前置分支筛的是急症红旗(噎着、发紫、无反应),
而自然产生的语料按定义不含这些情形、医生也不会去问——这是选择效应,换更富的语料无效。
③ 一次真实问诊不会把一支的判据全问完,于是档位停在该支上界。
这是 worst_case 在正确工作,但上界松紧完全由问诊完备性决定。
④ worst_case 的安全性以「不产生假 no」为前提。
输出是在现有证据下排除不掉的最紧急一档(某支只有全部条件为 no 才算排除),
因此欠分诊恒为 0、证据每多一个 no 就单调收紧(两条不变量由 tests/ 守着)。
信息不足时它会退化成"人人叫救护车"——这是设计取向(欠分诊 10·d² vs 过分诊 d),不是 bug。
⑤ 分级本身是 silver:分支级参照由强模型定稿 + 人工复核,终局结论仍缺一个真人护士 gold。
unknown 为什么是第一等状态
STCC 分支语义是「本支任一条件为是 ⇒ 命中;全部为否 ⇒ 转下一支」。
"没提到" ≠ "说了没有":前者必须触发追问,后者才能转分支。
把 unknown 压成 no 等于凭空伪造阴性,会让引擎走到错误的分支。
判据文本
索引里的判据是逐条独立改写版(5,214/5,214)。纯阈值与单个医学术语 (「咳嗽」「体温>100.4°F」)按事实保留。改写过三道闸: 数值/否定/长度/雷同的形式校验、oracle 回放与原版逐位一致、下游 checker 指标不掉。
冒烟:用发布物验,不是用仓库源码验
pip install --no-cache-dir stcc-mcp
cd /tmp && python <本仓>/scripts/smoke_published.py # 命令行契约
python <本仓>/scripts/smoke_published.py --skip-cli --links README.md # 文档里每个 URL断言的是文档承诺过的东西:协议菜单 225 条、协议名写错→退出码 2 + 可执行提示、
输入过短→rejected 且不给档位、依赖不可达→退出码 3 + 不吐 traceback、README 里每个链接可达。
CI 见 .github/workflows/smoke.yml(repo 测源码、published 从 PyPI 装再测、
e2e 装 Ollama 拉发布模型跑三分类与端到端)。
为什么单独搞这一层:本项目发布后靠人肉抓到 7 个"传上去了但用不了"的东西 (死链、没发布的命令、返回空串、废弃的 CLI、账号名写错、默认模型名只在开发机成立、 依赖没起时抛裸 traceback)。它们都不会让上传失败,也都不会被单测抓到—— 单测跑仓库源码,用户跑发布物。
开发
uv sync
uv run pytest -q # 27 条回归
uv run python -m scripts.mcp_selfcheck # oracle 回放 4,168 条判据,<1 秒scripts/mcp_selfcheck.py 是引擎的忠实度自检:逐条判据置 yes、其余置 no,
核对引擎走到的分支与处置。这不是模型评测——对不上就是编译或求值有洞。
模型
chenhaodev/stcc-checker-0.6b-GGUF
(Q8_0 / Q4_K_M)。判据级 false_no 0.0024、延迟中位 ~250ms、端到端 1.25s/条。
Apache-2.0.
This server cannot be deployed
Maintenance
Related MCP Connectors
Medical RAG: semantic search for clinical guidelines, drug interactions, diagnoses & EHR data.
Medical RAG: semantic search for clinical guidelines, drug interactions, diagnoses & EHR data.
Physician-reviewed medical opinions and prescriptions for AI agents.
Author rules from policy docs, then decide: a Rete engine gives the verdict, an LLM explains why.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn agentic AI system that enables healthcare professionals to log patient symptoms, retrieve similar clinical cases, and search medical documents using RAG. It integrates a Chroma vector database with the Model Context Protocol to provide real-time clinical decision support.-
- AlicenseAqualityCmaintenanceFirst-line incident triage you can trust: ranked root-cause hypotheses where every claim cites a real evidence handle — and the agent abstains rather than guess.11MIT
- AlicenseAqualityAmaintenanceAuthor rules from policy docs, then decide: a Rete engine gives the verdict, an LLM explains why.9MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-integrated prescription review with incomplete laboratory evidence, using deterministic rules and language-model guardrails to enforce approval authority boundaries.MIT