generate_structured_handoff_note
Create deterministic SBAR-style handoff notes for synthetic cardiovascular cases in English, Spanish, or Portuguese after risk and missing-data review.
Instructions
Generate a deterministic SBAR-style handoff note for a synthetic case in English, Spanish, or Portuguese. Use after risk and missing-data review. NOT for clinical use.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| case_id | Yes | ||
| language | No | en |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| case_id | Yes | ||
| language | No | en | |
| style | No | SBAR | |
| note | Yes | ||
| text | Yes | ||
| disclaimer | No | NOT for clinical use. Synthetic demo data only. Clinician validation required. |
Implementation Reference
- server/tools/handoff_note.py:7-24 (handler)Core implementation of the generate_structured_handoff_note tool. Fetches synthetic case data, summarizes risk, identifies missing critical data, builds a HandoffNote with situation/background/assessment/recommendation/safety, and renders it as SBAR text. Returns HandoffNoteOutput.
def generate_structured_handoff_note(case_id: str, language: Language = "en") -> HandoffNoteOutput: case = get_synthetic_case(case_id) risk = summarize_cardiovascular_risk_signals(case.case_id) missing = analyze_missing_critical_data(case.case_id) recommendations = _recommendations(case.case_id) note = HandoffNote( situation=f"Synthetic {case.case_id}: {case.presenting_problem}.", background=( f"{case.age}-year-old {case.sex}; vitals: {_format_dict(case.vitals)}; " f"labs: {_format_dict(case.labs) if case.labs else 'none documented'}; ECG: {case.ecg}." ), assessment=_assessment(case.case_id, risk), recommendation=recommendations, safety=_safety(language), ) text = _render_sbar(note, missing_fields=[item.field for item in missing.missing], language=language) return HandoffNoteOutput(case_id=case.case_id, language=language, note=note, text=text) - server/models.py:54-68 (schema)Pydantic models for HandoffNote (situation, background, assessment, recommendation, safety) and HandoffNoteOutput (case_id, language, style='SBAR', note, text, disclaimer). Also defines Language type literal (en/es/pt).
class HandoffNote(BaseModel): situation: str background: str assessment: list[str] recommendation: list[str] safety: str class HandoffNoteOutput(BaseModel): case_id: str language: Language = "en" style: Literal["SBAR"] = "SBAR" note: HandoffNote text: str disclaimer: str = DISCLAIMER - server/main.py:24-31 (registration)Tool name 'generate_structured_handoff_note' listed in REGISTERED_TOOL_NAMES constant.
REGISTERED_TOOL_NAMES = [ "list_synthetic_cases", "get_fhir_case_bundle", "analyze_missing_critical_data", "summarize_cardiovascular_risk_signals", "generate_structured_handoff_note", "interpret_12_lead_ecg", ] - server/main.py:144-147 (registration)MCP server wrapper function that delegates to handoff_note_tool (the implementation from server/tools/handoff_note.py). Has docstring used as tool description.
def generate_structured_handoff_note(case_id: str, language: Language = "en") -> HandoffNoteOutput: """Generate a deterministic SBAR-style handoff note for a synthetic case in English, Spanish, or Portuguese. Use after risk and missing-data review. NOT for clinical use.""" return handoff_note_tool(case_id, language=language) - server/main.py:160-166 (registration)Tool registered via server.tool()(generate_structured_handoff_note) in register_tools().
def register_tools(server: FastMCP) -> None: server.tool()(list_synthetic_cases) server.tool()(get_fhir_case_bundle) server.tool()(analyze_missing_critical_data) server.tool()(summarize_cardiovascular_risk_signals) server.tool()(generate_structured_handoff_note) server.tool()(interpret_12_lead_ecg) - server/tools/handoff_note.py:107-123 (helper)_render_sbar helper: formats the SBAR text using localized labels and includes missing critical data. Used by the main handler.
def _render_sbar(note: HandoffNote, missing_fields: list[str], language: Language) -> str: situation, background, assessment, recommendation, safety = _labels(language) missing_text = _missing_text(missing_fields, language) assessment_text = " ".join(note.assessment) recommendation_text = " ".join(note.recommendation) missing_label = { "en": "Missing critical data", "es": "Datos criticos faltantes", "pt": "Dados criticos ausentes", }[language] return ( f"{situation}: {note.situation}\n" f"{background}: {note.background}\n" f"{assessment}: {assessment_text} {missing_label}: {missing_text}.\n" f"{recommendation}: {recommendation_text}\n" f"{safety}: {note.safety}" ) - server/tools/handoff_note.py:27-50 (helper)_recommendations helper: returns case-specific recommendation lists (A, B, D, or default).
def _recommendations(case_id: str) -> list[str]: if case_id == "A": return [ "Immediate clinician review for high-risk ACS/STEMI workflow.", "Repeat ECG and follow serial troponin availability.", "Document contraindications before antithrombotic or reperfusion decisions.", ] if case_id == "B": return [ "Evaluate heart failure and ACS differential with available local diagnostics.", "Prioritize BNP/NT-proBNP, troponin, echocardiography, and Chagas serology if appropriate.", "Escalate if oxygenation, blood pressure, or work of breathing worsens.", ] if case_id == "D": return [ "Request echocardiography to characterize LVEF, chamber size, and valvular disease.", "Obtain troponin and BNP/NT-proBNP if clinically indicated for dyspnea workup.", "Arrange outpatient cardiology follow-up and escalate if oxygenation, blood pressure, or symptoms worsen.", ] return [ "Clinician review for low-risk chest-pain disposition.", "Use return precautions and follow-up planning if discharge is selected.", "Reassess if symptoms recur, evolve, or red flags appear.", ] - server/tools/handoff_note.py:53-65 (helper)_assessment helper: returns case-specific assessment strings, with special handling for case D.
def _assessment(case_id: str, risk) -> list[str]: if case_id == "D": return [ ( "MEDIUM: LBBB + low-voltage structural cardiomyopathy pattern - " "uncalibrated ECG demo score supports structural cardiomyopathy workup, " "not autonomous etiology diagnosis." ) ] return [ f"{signal.level.upper()}: {signal.label} - {signal.rationale}" for signal in risk.signals ] - server/tools/handoff_note.py:72-86 (helper)_safety helper: returns localized safety disclaimer in en/es/pt.
def _safety(language: Language) -> str: if language == "es": return ( "NO para uso clinico. Solo datos demo sinteticos / publicos de-identificados. " "Un clinico licenciado debe validar todos los hallazgos y acciones." ) if language == "pt": return ( "NAO para uso clinico. Apenas dados demo sinteticos / publicos de-identificados. " "Um clinico licenciado deve validar todos os achados e acoes." ) return ( "NOT for clinical use. Synthetic / public de-identified demo data only. " "A licensed clinician must validate all findings and actions." ) - server/tools/handoff_note.py:89-94 (helper)_labels helper: returns localized SBAR section labels for en/es/pt.
def _labels(language: Language) -> tuple[str, str, str, str, str]: if language == "es": return ("Situacion", "Antecedentes", "Evaluacion", "Recomendacion", "Seguridad") if language == "pt": return ("Situacao", "Contexto", "Avaliacao", "Recomendacao", "Seguranca") return ("Situation", "Background", "Assessment", "Recommendation", "Safety") - server/tools/handoff_note.py:97-104 (helper)_missing_text helper: formats missing fields text localized by language.
def _missing_text(missing_fields: list[str], language: Language) -> str: if missing_fields: return ", ".join(missing_fields) if language == "es": return "ninguno critico en el caso demo" if language == "pt": return "nenhum critico no caso demo" return "none critical in synthetic case" - server/tools/handoff_note.py:68-69 (helper)_format_dict helper: formats a dict as 'key: value; key: value' string.
def _format_dict(values: dict[str, str]) -> str: return "; ".join(f"{key}: {value}" for key, value in values.items())