Diagnostic reasoning engine that runs the validated spine loop with pluggable reasoner. Opens cases, records answers to discriminating questions, and proposes diagnoses. State lives in SQLite casebook; server is stateless between calls.
Spine MCP has well-structured tool definitions with clear, domain-specific descriptions (avg 180 chars). All 7 tools have input schemas with typed parameters and descriptions. However, output schemas are not formally documented, responses are inferred from code (render_md, diagnosis object structure). Parameter descriptions lack constraint details (e.g., case_id range, name format). Error handling is present but generic ('reasoner unavailable'). No tool annotations (readOnlyHint/destructiveHint). Naming is verb-noun consistent (spine_open, spine_answer, spine_get, spine_save, spine_list, spine_load, spine_config) but lacks clarity on mutual exclusivity (answers vs answer in spine_answer).
Record the human's answer(s) to the pending question(s) and advance exactly one diagnostic turn. Pass `answers` as a list aligned to the questions, or a single `answer` string; blanks are recorded as 'unknown'. Returns the next question(s), OR a proposed diagnosis: status='fix-proposed' with a cheap confirm_test (plus escalate/casualty when they apply). It is NEVER 'resolved' here — confirming the fix is a separate step.
Get or set Spine configuration: save_dir (where portable spines live), auto_save (mirror cases to persistent files), and model/backend/critic settings. Returns the current config.
Read-only snapshot of a case's full spine grid — frame, bones (with in/out/confirmed status), evidence log, any proposed diagnosis, and the pending questions — plus a ready-to-display markdown view (render_md).
List all saved spines in the save dir (portable case files). Returns metadata: name, symptom, domain, status, when saved.
Load a saved spine by name into the working casebook and return its case ID. The case resumes in the working casebook; you can continue diagnosing or inspect it with spine_get.
Output schemas not formally documented. Response structures (diagnosis object, render_md field, bones array) are inferred from code, not declared in tool definitions. LLMs cannot reliably plan downstream operations without explicit output schema.
spine_answer has ambiguous parameter design: both 'answers' (list) and 'answer' (string) are optional with no mutual exclusivity documented. LLMs may pass both or neither, causing undefined behavior. Should enforce one or the other.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). spine_save, spine_load, spine_answer are WRITE operations but lack destructiveHint. spine_get, spine_list are READ_ONLY but lack readOnlyHint. Agents cannot infer safety without annotations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
Open a new diagnostic case and run the orient turn (a reframe + the candidate cause-branches, never a premature diagnosis). Returns the frame, the bones, and the first discriminating question(s) to put to the on-site human. The server does all the reasoning; the host just relays questions and answers.
Save a case as a named, portable spine in the save dir. Working casebooks are EPHEMERAL by default (gone when the session ends) — this is how you keep one. `name` defaults to a slug of the case's symptom. Set the save dir first with spine_config(save_dir=...) if it isn't configured yet.
Parameter constraints missing. case_id has no range or validation hint. name parameter in spine_save/spine_load lacks format guidance (slug rules, length limits). domain in spine_open is optional but no guidance on valid values or discovery.
Error responses are generic ('reasoner unavailable', 'no pending question'). No recovery guidance. Should include actionable next steps: 'Reasoner unavailable. Retry in 30s or check SPINE_BACKEND env var.' or 'No pending question. Call spine_open() to start a new case or spine_get() to inspect current state.'