Skip to main content
Glama

stcc-mcp — Triage Classification: Rules Are Deterministic, 0.6B Only Checks Criteria

Feed in a consultation record, and you get L1–L5 levels + disposition wording + per-criterion citations + which criteria are still missing. Classification is computed by a deterministic rules engine (225 STCC protocols / 849 branches / 4,168 criteria, shipped with the package), while Qwen3-0.6B answers only one question: given a record and one criterion, yes / no / unknown.

The model does not pick branches, set levels, or generate disposition wording — it makes no tool calls.

⚠️ This is not an emergency triage system, does not make diagnoses, and cannot replace a doctor. L1–L5 is a disposition ladder (call an ambulance / go to the ER now / see a doctor today / outpatient visit within two days / manage at home). In an emergency, call 120 directly.

Run It in Three Steps

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)"

Zero resident processes, zero Docker, no network calls. The engine is pure standard library — no third-party dependencies.

The First Run Will Most Likely Show tier: L1 + certain: false — That Is Correct

Feed in an ordinary consultation record and you will most likely get the most urgent level plus a string of unresolved. This is not a misclassification: the engine only dares to rule out a branch when every condition in it is no, and a real consultation never asks every criterion in a branch. For example, in a fever record the nurse asked about consciousness/respiration/stiff neck/skin rash, but never asked about dehydration signs (decreased urination, sunken eyes, reduced skin turgor, thirst), so that branch cannot be ruled out and the output stays at its upper-bound level.

unresolved is exactly the checklist of "ask these next and you can tighten the level." Add the answers to the record and rerun — unresolved shrinks monotonically; but the level only drops when a branch is fully ruled out — in testing, the same fever record, after filling in the dehydration signs, went from 8 unresolved criteria to 2, while the level stayed at L1, because the remaining trunk (the "elderly or immunocompromised… dehydration manifestations:" half-sentence) still gets unknown from the checker. What you should adjust at that point is the threshold knob below, not keep asking questions. See edge cases ①②.

Related MCP server: Quellgeist

Hook It Into an Agent (Claude Code / any MCP client):

pip install "stcc-mcp[mcp]" && stcc-mcp serve               # stdio MCP

Ollama does not support MCP, which is a non-issue for this design: the small model never makes tool calls; the orchestration layer calls Ollama (HTTP) and the rules engine (in-process) separately — the two never talk to each other. 0.6B autonomous tool-calling is a known failure zone; this architecture sidesteps it by design.

Output

Field

Meaning

tier

L1L5, upper safety bound: never lighter than the true severity

disposition

Wording for this branch's disposition (from the rules table, not generated by the model)

certain

true = evidence is sufficient to fix the level; false = this is the worst_case upper bound

citations

The criteria that determined the level + line numbers, auditable

unresolved

Which criteria are still missing — ask these to tighten the level

The mapping from level to action is defined by your orchestration layer; this package only provides the level and disposition wording.

The no Threshold Is a Knob

--no-threshold (default 0.63): P(no) ≥ τ ⇒ no, otherwise take the larger of yes / unknown. The full trade-off curve on the release distribution (n=3225):

τ

acc

false_no🔴

no_recall

0.63 (default)

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

For the same fever consultation record, just change τ:

$ 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

Lower τ ⇒ the checker is more willing to mark an asked-and-denied criterion as no ⇒ more branches get ruled out ⇒ the level drops. This does not make the model more accurate — it moves along the same trade-off curve to a different operating point — and the price is a higher missed-case risk.

false_no (a criterion that should be yes but is marked no) is the hard failure mode — a false no can wrongly rule out the true branch. A missed no only causes over-triage, which is a cost knob. The default was chosen on the dev set with false_no ≤ 0.0036 (the dev set has only 495 positive examples, so the resolution is 0.0020 — this is systematically conservative). So there is no hard-coded "optimal" value — the full curve is provided; pick your own operating point by your cost matrix. Reproduce with: python -m scripts.threshold_sweep --model <m> --split <s> --collect --report.

🔴 Known Limitations (Read Before Using)

① The input must be a record from a protocol-driven interview, not raw free text. On short self-reports the unknown rate is 94%; on real rich dialogues (IMCS-21, 748 words / 40 turns) it is still 88%. The reason is that the STCC front-loaded branches screen for red-flag emergencies (choking, cyanosis, no response), and naturally occurring speech by definition does not contain these situations, and doctors do not ask about them — this is a selection effect, and switching to richer corpora will not fix it.

② A real consultation never asks every criterion in a branch, so the level often sits at the branch's upper bound. That is worst_case working correctly — how tight the bound is depends entirely on how complete the interview is.

worst_case safety rests on "no false nos." The output is the most urgent branch that cannot be ruled out given the current evidence (a branch is ruled out only when every condition is no), therefore under-triage is structurally 0, and each additional no tightens the bound monotonically (two invariants enforced by tests/). When information is insufficient, it degrades to "send everyone to the ambulance" — that is a design choice (under-triage cost 10·d² vs. over-triage cost d), not a bug.

④ The grading itself is silver-level: the branch-level reference was drafted by a strong model and human-reviewed, but the final conclusion still lacks a human-gold standard.

Why unknown Is the Most Important State

STCC branch semantics: "any condition in this branch is yes ⇒ hit; all are no ⇒ move to the next branch." "Not mentioned" ≠ "said no": the former must trigger a follow-up question; only the latter lets the engine move on. Forcing unknown to no is fabricating a negative out of thin air and can drive the engine into the wrong branch.

Criterion Text

The criteria in the index are individually rewritten versions (5,214 / 5,214). Pure thresholds and single medical terms (e.g., "cough", "temperature >100.4°F") are kept as-is. The rewrite went through three gates: formal checks for numbers/negations/length/near-duplicates, oracle replay that matches the original bit-for-bit, and downstream checker metrics that do not regress.

Development

uv sync
uv run pytest -q                        # 27 条回归
uv run python -m scripts.mcp_selfcheck  # oracle 回放 4,168 条判据,<1 秒

scripts/mcp_selfcheck.py is the engine's fidelity self-check: set each criterion to yes one at a time, all others to no, and verify the branch and disposition the engine lands on. This is not a model evaluation — if it does not match, there is a hole in the compilation or evaluation logic.

Model

chenhaodev/stcc-checker-0.6b-GGUF (Q8_0 / Q4_K_M). Criterion-level false_no 0.0024, median latency ~250ms, end-to-end 1.25s per record.

Apache-2.0.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    F
    maintenance
    An 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.
  • A
    license
    A
    quality
    A
    maintenance
    First-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.
    1
    1
    MIT
  • A
    license
    C
    quality
    B
    maintenance
    Evidence-grounded biomedical retrieval and summarization through the Model Context Protocol, enabling queries for biomedical evidence with citation-backed results.
    2
    MIT

View all related MCP servers

Related MCP Connectors

  • 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.

  • Doctor-reviewed blood-test markers, conditions & symptoms as agent tools. EN/RU/HE. Hosted.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/devhc123/stcc-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server