Skip to main content
Glama
rirko

shdc-appointment-mcp

by rirko
README.md
# medical-triage-followup Skill 详细说明

`medical-triage-followup` 是一个面向中文纯聊天窗口的医疗分诊、病例整理、随访跟踪和挂号辅助 Skill。它的定位不是替代医生做诊断,而是帮助 LLM 在对话中把用户的模糊健康问题逐步澄清为可执行的就医诉求,并在需要时编排 SHDC 预约 MCP 查询医院、科室、专家、专病门诊和可预约时间。

Skill 路径:

```text
medical-triage-followup/
```

## 适用场景

- 用户描述身体不适,但诉求模糊,例如“腿疼”“最近不舒服”“想看看该挂什么科”。
- 用户希望根据症状选择医院、科室、专家或专病门诊。
- 用户提供一个时间范围,希望汇总该时间段内可预约的专家、专病门诊、余号和费用。
- 用户上传门诊病历、检查报告、检验报告、出院小结、病案首页、报告图片、PDF、DOCX 或复制的病例文本。
- 用户需要把病例整理成病情时间线、随访提醒、复查计划、就诊前准备清单和医生问题清单。
- 用户没有完成线下初诊或建档,需要先查看医院自助挂号入口,而不是直接进入正式预约。

## 核心原则

1. 只做分诊和就医辅助,不做确定诊断。
2. 症状问诊阶段每轮只问一个最关键问题。
3. 中间不展示“当前理解”,只在最终分诊时总结。
4. 出现急诊红旗时立即中止普通分诊,建议急诊或 120。
5. 预约前必须确认用户是否已经完成线下初诊/建档。
6. 不绕过验证码、短信码、实名校验、就诊人校验或最终确认。
7. 不在聊天中暴露完整身份证号、手机号、住址、医疗卡号、token 或密码。
8. 病例处理保留临床含义,但输出时默认脱敏。

## 工作流概览

### 1. 症状澄清

当用户只给出模糊症状时,Skill 会引导 LLM 连续追问,例如:

- 最困扰你的症状是什么?
- 具体部位在哪里?
- 持续多久了?
- 是否有外伤、发热、胸闷、呼吸困难、麻木无力等伴随表现?
- 目前严重程度如何,是否影响行走、进食、睡眠或日常活动?

基础澄清最多 5 轮。如果用户引入新的关键线索,可以开启新的 5 轮澄清。每轮只问一个问题,避免一次性把用户压住。

### 2. 红旗判断

在普通分诊前,Skill 会先检查危险信号。典型红旗包括:

- 压榨性胸痛、胸痛伴大汗/呼吸困难/晕厥。
- 单侧肢体无力、口角歪斜、言语不清、突发剧烈头痛。
- 严重呼吸困难、喉头水肿、过敏伴喘憋或头晕。
- 严重外伤、畸形、不能负重、活动性出血。
- 呕血、黑便伴乏力、持续剧烈腹痛、疑似宫外孕。
- 高热伴意识改变、颈强直、紫癜、严重感染进展。
- 自伤或伤人风险。

如果红旗存在,Skill 应优先建议急诊或 120,而不是继续推荐普通门诊预约。

### 3. 分诊与挂号类型判断

当信息足够后,Skill 会输出:

- 症状总结
- 紧急程度
- 建议科室
- 推荐挂号类型:专家或专病
- MCP 查询关键词
- 不能确定的部分
- 是否可以继续帮用户查询预约

目前普通门诊访问不稳定,因此默认不推荐普通门诊。只有用户明确要求普通门诊时,才提示其可能不可靠,并优先提供专家或专病替代方案。

挂号类型映射:

```text
registerType=1 专家门诊
registerType=2 专病/专科专病门诊
registerType=3 普通门诊,默认不使用
```

### 4. MCP 预约查询

Skill 本身不直接访问医院网页,而是指导 LLM 使用 SHDC 预约 MCP。推荐调用顺序是:

1. `search_hospitals`
2. `search_departments`
3. `list_available_experts`
4. `list_expert_slots`
5. 如用户确认继续预约,再进入登录、就诊人、验证码、短信码、确认和提交流程。

如果用户给出时间范围,例如“本周末”“下周一上午”“6 月 28 日到 7 月 3 日”,Skill 要求 LLM 将其规范化为具体日期和上午/下午等时间段,并汇总范围内所有匹配专家或专病门诊的可用号源,而不是只返回一个医生。

### 5. 初诊/建档限制

如果用户是第一次使用,或没有完成目标医院的线下初诊/建档,Skill 要求停止正式注册和预约流程,只返回:

- 医院/院区
- 科室
- 门诊类型
- 专家或专病门诊项
- 可预约时间
- 剩余号数或状态
- 费用
- 对应医院的微信服务/自助挂号链接

在医院信息查询完成、正式帮用户挂号前,Skill 会提示:

```text
你是否还没有完成线下初诊/建档,或者希望自己通过医院微信服务挂号?
```

如果用户回答是,则优先附上 `hospital-wechat-links.md` 中记录的医院挂号入口。

## 病例处理能力

用户上传病例、报告或复制病例文本后,Skill 会按以下顺序处理:

1. 文本提取或 OCR 清洗。
2. 识别文书类型和来源。
3. 抽取主诉、现病史、既往史、诊断/印象、检查检验、影像结论、用药、手术/操作、医嘱和复诊计划。
4. 评估资料可信度。
5. 检查缺失信息。
6. 建立病情时间线。
7. 追踪异常检查值。
8. 从病例中触发红旗结果。
9. 生成就诊前准备清单。
10. 生成建议问医生的问题。
11. 输出 Markdown + JSON 随访卡。

### 资料可信度与缺失信息

可信度分为:

- `high`:官方报告清晰、文书结构完整、关键日期/结果/来源可见。
- `medium`:大部分内容可读,但部分日期、单位、页码、来源或 OCR 内容不完整。
- `low`:图片或文本质量差、核心诊断/结果缺失、只来自用户转述。

缺失信息只列影响下一步决策的问题,例如:

- 报告日期或检查日期缺失。
- 检验值没有单位或参考范围。
- 当前症状是否仍在持续不明确。
- 用药剂量、频次、开始/停止时间不明确。
- 医生复查建议或目标科室不明确。

### 病情时间线

时间线用于把多份病例合并为一个清楚的过程。事件类型包括:

- 症状出现
- 门诊/急诊/住院
- 检查或检验
- 影像报告
- 诊断或印象
- 治疗计划
- 手术或操作
- 用药变化
- 出院和复诊建议

如果日期被脱敏或缺失,使用“最早记录”“随后”“住院期间”“术后”“当前”等顺序标签,不编造具体日期。

### 异常检查值追踪

异常值判断优先依据报告本身:

- `异常报告`
- `危急报告`
- `异常提示`
- `H` / `L` / `A`
- `↑` / `↓`
- 可见参考范围
- 医生文字说明,如“明显升高”“降低”“需复查”

如果没有参考范围或异常标记,只记录数值,不自行判断异常。

### 病例触发红旗

病例中出现以下线索时,应优先提醒用户尽快就医或急诊:

- 检验系统显示危急报告或危急值。
- 影像提示急性出血、急性梗死、严重感染、明显进展。
- 癌栓、门静脉主干栓子、梗阻性黄疸、腹水合并发热等严重并发症线索。
- 医嘱写明“立即就医”“急诊”“尽快住院”“需紧急处理”。
- 病例记录中有胸闷加重、呼吸困难、意识改变、呕血黑便等危险症状。

注意:既往病史中的红旗不应自动等同于当前急诊。例如“脑出血恢复期”应标为重要既往风险,而不是直接判断为正在急性脑出血。

## 输出格式

### 分诊建议

```markdown
分诊建议
- 症状总结:
- 紧急程度:
- 建议科室:
- 推荐挂号类型:专家 / 专病
- 查询关键词:
- 理由:
- 不能确定:
- 预约协助:我可以继续帮你查询并预约,请告诉我你想预约的医院。
```

### 可预约信息

```markdown
可预约信息
- 医院/院区:
- 科室:
- 门诊类型:专家 / 专病
- 专家/门诊项:
- 可用时间:
- 剩余号数/状态:
- 费用:
- 自助挂号链接:
```

### 病例整理

```markdown
病例整理
- 资料可信度:
- 主要问题:
- 关键诊断/印象:
- 重要检查结果:
- 当前治疗/用药:
- 医嘱与复诊:

缺失信息
-

病情时间线
| 时间/顺序 | 事件 | 来源 | 可信度 |
|---|---|---|---|

异常检查值追踪
| 项目 | 结果 | 参考范围/标记 | 日期 | 建议追踪 |
|---|---|---|---|---|

病例触发红旗
-

就诊前准备
-

建议问医生的问题
1.
```

### 随访提醒卡

Skill 要求输出可见 Markdown 卡片和 JSON 卡片,便于后续聊天或其他应用继续接管。

JSON 卡片包含:

- `record_quality`
- `conditions`
- `timeline_events`
- `symptoms_to_track`
- `medications`
- `tests_to_follow`
- `record_red_flags`
- `next_visit`
- `pre_visit_checklist`
- `doctor_questions`
- `reminders`
- `open_questions`

## 文件结构

```text
medical-triage-followup/
├── SKILL.md
└── references/
    ├── abnormal-and-red-flag-tracking.md
    ├── appointment-availability-summary.md
    ├── case-extraction-template.md
    ├── diagnostic-cases.md
    ├── followup-card-template.md
    ├── hospital-wechat-links.md
    ├── medical-entity-types.md
    ├── medical-timeline-template.md
    ├── ocr-guidelines.md
    ├── pre-visit-and-doctor-questions.md
    ├── record-quality-and-gaps.md
    ├── triage-clarification.md
    └── triage-rules.md
```

## 关键 Reference 说明

- `triage-clarification.md`:定义症状多轮追问状态机。
- `triage-rules.md`:定义症状到科室、挂号类型和危险信号的规则。
- `diagnostic-cases.md`:可扩展案例库,用于辅助分诊,不作为确诊依据。
- `appointment-availability-summary.md`:定义时间范围内号源汇总方式。
- `hospital-wechat-links.md`:保存部分医院微信服务或自助挂号入口。
- `case-extraction-template.md`:病例抽取主模板。
- `record-quality-and-gaps.md`:资料可信度和缺失信息检查。
- `medical-timeline-template.md`:病情时间线模板。
- `abnormal-and-red-flag-tracking.md`:异常值追踪和病例红旗触发规则。
- `pre-visit-and-doctor-questions.md`:就诊前准备和医生问题清单。
- `followup-card-template.md`:Markdown + JSON 随访卡模板。

## 与 SHDC MCP 的关系

Skill 负责“理解用户、澄清症状、整理病例、判断科室、组织对话流程”;MCP 负责“实时查询医院、科室、专家、号源,以及完成登录、验证码、就诊人和预约提交等官方流程”。

二者的边界是:

- Skill 不直接提交挂号。
- Skill 不绕过官方验证码或短信码。
- Skill 不保存或展示完整隐私字段。
- MCP 不负责诊断症状;症状应先由 Skill 转成科室和查询关键词。

## 测试建议

症状澄清测试:

- 输入“我身体不舒服”,应先问最困扰的症状。
- 输入“腿疼”,应逐步询问部位、持续时间、外伤、严重程度和伴随症状。
- 输入胸痛伴大汗、偏瘫、呼吸困难等,应立即触发急诊建议。

预约查询测试:

- 用户给出医院和科室后,应能引导 MCP 查询专家和专病门诊。
- 用户给出“下周上午”之类时间范围,应汇总该范围内所有匹配号源。
- 未确认线下初诊/建档时,只返回可预约信息和自助挂号入口,不进入正式预约。

病例测试:

- 门诊病历应抽取主诉、现病史、诊断、计划和随访医嘱。
- MRI/CT 报告应抽取检查项目、所见、印象和需要复查的问题。
- 检验报告应保留数值、单位、参考范围和异常标记。
- 出院小结或病案首页应生成诊断、治疗、住院过程和复诊计划。
- 多份病例应合并成时间线,而不是互相覆盖。

本项目本地曾使用 `病例/` 目录下 4 个脱敏 DOCX 做验收,但该目录已被 `.gitignore` 排除,不上传 GitHub。

## 安全与合规边界

- 该 Skill 不能替代医生诊断、处方或急救判断。
- 对药物剂量、停药、换药,只能引用官方病历中的医嘱;如果病历没有写,应建议咨询医生。
- 对正常报告不能说“排除疾病”。
- 对恶性肿瘤、危急值、急性出血/梗死等结果,应保持谨慎,提示尽快专科或急诊评估。
- 对用户隐私字段默认脱敏,不在聊天中重复完整证件号、手机号、住址、病案号、条形码、二维码等。

## 维护方式

新增症状案例:

```text
编辑 medical-triage-followup/references/diagnostic-cases.md
```

新增医院自助挂号入口:

```text
编辑 medical-triage-followup/references/hospital-wechat-links.md
```

调整病例抽取字段:

```text
编辑 medical-triage-followup/references/case-extraction-template.md
同步检查 medical-triage-followup/references/followup-card-template.md
```

调整红旗或异常值规则:

```text
编辑 medical-triage-followup/references/abnormal-and-red-flag-tracking.md
```

更新后建议运行:

```bash
python C:\Users\RIRKO\.codex\skills\.system\skill-creator\scripts\quick_validate.py .\medical-triage-followup
```

在 Windows PowerShell 中如遇中文路径或输出乱码,建议设置:

```powershell
$env:PYTHONUTF8='1'
```

## 远程 MCP Handoff(2026-07-04)

本节记录最近一次远程 MCP 部署、验证和 xskills 网页客户端排查情况,供后续接手继续定位。

### 工作区边界

- 本地工作区:`D:\项目\shdc-appointment-mcp`,默认用于开发 skill 和 MCP 源码。
- 远程服务器:SSH 别名 `aliyun-mcp`,部署路径 `/opt/mcp`。
- 远程数据目录:`/opt/mcp/data`。
- 远程命令格式:`ssh aliyun-mcp "命令"`。
- 上传文件格式:`scp 本地文件 aliyun-mcp:/opt/mcp/目标路径`。
- 不要删除远程系统目录,不要执行 `git reset --hard`、`rm -rf /` 等破坏性命令。

### 当前远程服务

- 公网域名:`https://rirko.icu`
- 健康检查:`https://rirko.icu/healthz`
- MCP Endpoint:`https://rirko.icu/mcp`
- 协议:Streamable HTTP
- systemd 服务:`shdc-remote-mcp.service`
- 启动命令:`/opt/mcp/node/bin/node /opt/mcp/dist/httpIndex.js`
- Nginx 反代:`/mcp` 和 `/healthz` 代理到 `http://127.0.0.1:3000`
- 证书:certbot 已签发 HTTPS 证书,域名解析到 `47.239.148.19`

远程环境文件:

```text
/opt/mcp/remote-mcp.env
```

当前关键环境变量:

```text
HOST=127.0.0.1
PORT=3000
SHDC_MCP_DATA_DIR=/opt/mcp/data
HTTPS_PROXY=http://127.0.0.1:18080
HTTP_PROXY=http://127.0.0.1:18080
NO_PROXY=127.0.0.1,localhost
MCP_AUTH_TOKEN=<见 /opt/mcp/remote-mcp.env>
MCP_JSON_RESPONSE=true
```

获取当前 MCP token:

```bash
ssh aliyun-mcp "grep '^MCP_AUTH_TOKEN=' /opt/mcp/remote-mcp.env"
```

客户端请求头模板:

```text
Authorization=Bearer <MCP_AUTH_TOKEN>
Content-Type=application/json
Accept=application/json, text/event-stream
MCP-Protocol-Version=2025-06-18
```

部分客户端只需要:

```text
Authorization=Bearer <MCP_AUTH_TOKEN>
```

### 最近代码和部署状态

- 已新建 `remote-mcp/`,从原 MCP 复制并改成远程 Streamable HTTP 形式。
- 已部署到远程 `/opt/mcp`,远程服务通过 systemd 管理。
- 已加入健康档案、病历/报告解析保存、用药、过敏、药物冲突、忌口提醒、时间轴、治疗记录等 MCP tools。
- 已接入 DDInter 实验性网页适配器,用于药物-药物、药物-食物、药物-疾病、复方/重复用药相关提醒。
- 已修复远程 MCP 浏览器兼容性:`GET /mcp` 无 session 时返回 200 探针,CORS 放行 MCP 相关头。
- 已修复 `/opt/mcp/remote-mcp.env` 中错误写成 `nMCP_JSON_RESPONSE=truen` 的问题,当前为 `MCP_JSON_RESPONSE=true`。
- 本地有一个未成功 push 的提交:`0956e3f Improve browser MCP compatibility`。GitHub push 之前多次因网络 reset/empty reply 失败,后续需要重试。

检查本地状态:

```bash
git status --short --branch
```

### 已验证结果

浏览器直连:

- `https://rirko.icu/healthz` 正常。
- `https://rirko.icu/mcp` 返回 200 JSON 探针。
- 从 xskills 页面浏览器直接 GET `https://rirko.icu/mcp` 也返回 200,Nginx 日志记录到 referer 为 `https://xskills.acits.com.cn/`。

MCP 协议探针:

- `initialize` 返回 200。
- `notifications/initialized` 返回 202。
- `tools/list` 返回 200。
- `MCP_JSON_RESPONSE=true` 生效后,`POST initialize` 和 `tools/list` 返回 `application/json`,不再是 SSE 包装。

远程服务状态检查:

```bash
ssh aliyun-mcp "systemctl is-active nginx; systemctl is-active shdc-remote-mcp.service"
```

日志检查:

```bash
ssh aliyun-mcp "tail -300 /var/log/nginx/access.log | grep ' /mcp' | tail -50"
ssh aliyun-mcp "tail -80 /opt/mcp/remote-mcp.log"
```

### SHDC 访问与代理

远程服务器直接访问 SHDC 会遇到 WAF/403,因此当前方案是用本机作为代理出口。

本地代理脚本:

```text
remote-mcp/scripts/local-http-proxy.mjs
```

本地代理监听:

```text
127.0.0.1:18080
```

反向 SSH 隧道:

```bash
ssh -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=2 -R 127.0.0.1:18080:127.0.0.1:18080 aliyun-mcp
```

远程环境已配置:

```text
HTTPS_PROXY=http://127.0.0.1:18080
HTTP_PROXY=http://127.0.0.1:18080
NO_PROXY=127.0.0.1,localhost
```

验证代理链:

```bash
ssh aliyun-mcp "curl -x http://127.0.0.1:18080 -I https://yuyue.shdc.org.cn/"
```

健康的代理链应返回 200。若 SHDC 查询超时,通常需要重启本地代理和反向 SSH 隧道。

### xskills 网页客户端当前结论

xskills 页面新增/编辑 MCP 服务器时的配置:

```text
连接地址:https://rirko.icu/mcp
协议类型:streamableHTTP
请求头:Authorization=Bearer <MCP_AUTH_TOKEN>
标签:shdc,mcp,remote
描述:上海医联预约远程 MCP,支持健康档案和 SHDC 查询
```

如果需要完整请求头:

```text
Authorization=Bearer <MCP_AUTH_TOKEN>
Content-Type=application/json
Accept=application/json, text/event-stream
MCP-Protocol-Version=2025-06-18
```

当前 xskills 测试接口返回:

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "serverName": "aliyun-mcp",
    "success": false,
    "toolCount": 0,
    "error": "服务连接失败,请检查服务是否正常运行"
  },
  "success": true
}
```

排查结论:

- xskills 前端测试请求是 `POST https://xskills.acits.com.cn/api/v1/mcp-market/user/servers/62/test`。
- 该请求 `content-length: 0`,说明它测试的是后端已保存的 server 配置,不是页面当前输入框实时内容。
- xskills 测试失败时,`rirko.icu` 服务器日志没有看到 xskills 后端访问 `/mcp`。
- 浏览器从 xskills 页面直接访问 `https://rirko.icu/mcp` 成功,Nginx 记录 `GET /mcp 200`。
- 因此当前失败更像是 xskills 后端未真正连到 `https://rirko.icu/mcp`、后端 DNS/网络不可达、保存配置未生效,或平台测试逻辑不兼容,而不是远程 MCP 服务本身不可用。

后续建议:

1. 在 xskills 页面先保存修改,再测试连接。
2. 测试时先只保留一行请求头:`Authorization=Bearer <MCP_AUTH_TOKEN>`。
3. 若仍失败,继续检查 xskills 的 `test` 接口响应,并同时观察远程 Nginx 日志是否出现来自 xskills 后端 IP 的 `/mcp` 请求。
4. 若服务器仍无请求,需让 xskills 平台侧确认后端是否能解析并访问 `rirko.icu:443`。

### 已知问题

- `/opt/mcp/remote-mcp.log` 里有一次 shutdown 期间的 `RangeError: Maximum call stack size exceeded`,出现在 SDK transport close 链路递归关闭时;服务已由 systemd 自动拉起且当前 active。后续可以单独修复关闭流程,避免 `server.close()` 和 `transport.close()` 互相触发。
- GitHub push 最近失败,当前本地可能领先远程 1 个提交。需要网络稳定后重试 push。
- xskills 平台账号的登录 Bearer/Cookie 曾在排查截图中暴露,后续 handoff 不应继续传播该平台登录 token。

TDQS

B3/5.0

Scored across 40 tools

Disambiguation5/5

Each tool belongs to a clear domain (appointment, auth, health, etc.) with distinct actions. Even within health, tools like health_document_get vs health_document_export have clear differences documented. No two tools have overlapping purposes.

Naming Consistency4/5

Tools follow a consistent snake_case pattern with domain prefixes. Most use verb-last convention (e.g., health_allergy_list), but a few like list_patients use verb-first. This minor inconsistency does not impair readability.

Tool Count2/5

With 40 tools, the server is over-scoped. While each tool has a distinct purpose, the sheer number makes it cumbersome for an agent. Splitting into separate servers (e.g., appointments, health records) would improve coherence.

Completeness4/5

The tool surface covers authentication, registration, appointment booking, health records, and drug interactions. Missing update/delete for several health entities (e.g., allergy, document, timeline) are minor gaps that agents can work around.

Maintenance

ActivityStale
ResponsivenessNo issues