Local-Safe-EMR-MCP

Local-Safe-EMR-MCP

MCP server that provides local, de-identified access to a demo EMR database using a private LLM for de-identification, ensuring raw patient data stays local.

Category
访问服务器

README

Local-Safe-EMR-MCP

Local-Safe-EMR-MCP 是一個教學用 demo,展示如何用 MCP server 在本地端讀取含個資的醫療病例,並在資料回傳給外部 agent 前,先呼叫本地或私有 LLM API 完成去識別化。

這個專案刻意保持簡單:資料庫只有病例 ID 與一段病例文字;MCP server 只提供查詢工具;去識別化邏輯獨立放在 deidentify.py;另外提供一個 CLI debug proxy,用來觀察 MCP HTTP/JSON-RPC 通訊。

架構

Antigravity / MCP Client
        |
        | MCP over HTTP
        v
server.py  (Local MCP server)
        |
        | read case_id/raw_note
        v
SQLite demo database
        |
        | raw_note stays local
        v
deidentify.py
        |
        | OpenAI-compatible API
        v
Local/private LLM server
        |
        | deidentified_text
        v
MCP response to client

核心安全概念:

  • 原始病例只存在本機 SQLite。
  • MCP client 只能透過 tool 查詢病例。
  • get_deidentified_case 會先呼叫 deidentify.py 去識別化。
  • MCP response 只回傳脫敏文字。
  • demo 不保存 mapping,避免流程變複雜。

專案檔案

Local-Safe-EMR-MCP/
├─ server.py            # FastMCP server,提供 MCP tools
├─ deidentify.py        # 呼叫 OpenAI-compatible LLM 做去識別化
├─ seed_demo_data.py    # 建立 SQLite demo 病例資料
├─ mcp_debug_proxy.py   # CLI reverse proxy,用來觀察 MCP 通訊
├─ .env.example         # 環境變數範例
├─ pyproject.toml       # Python 依賴
└─ data/
   └─ hospital_demo.db  # SQLite demo database

Demo 資料庫

資料庫只有一張表:

CREATE TABLE cases (
    case_id TEXT PRIMARY KEY,
    raw_note TEXT NOT NULL
);

目前 seed script 會建立三筆病例:

CASE-001: 慢性腎臟病與用藥風險
CASE-002: 糖尿病、高血壓與血脂控制
CASE-003: 胸悶與急性冠心症風險

設定

複製環境變數範例:

Copy-Item .env.example .env

範例設定:

DATABASE_PATH=data/hospital_demo.db
MCP_TRANSPORT=http
MCP_HOST=127.0.0.1
MCP_PORT=9000

MCP_PROXY_HOST=127.0.0.1
MCP_PROXY_PORT=9001
MCP_PROXY_TARGET=http://127.0.0.1:9000
MCP_PROXY_MAX_PRINT_CHARS=4000

LLM_BASE_URL=http://192.168.1.107:8000/v1
LLM_API_KEY=EMPTY
LLM_MODEL=google/gemma-4-31B-it

LLM_BASE_URL 必須是 OpenAI-compatible API,例如 vLLM:

vllm serve google/gemma-4-31B-it --host 0.0.0.0 --port 8000 --dtype bfloat16 --gpu-memory-utilization 0.85

建立 Demo 資料

cd C:\Users\rui\Desktop\mcp課程\Local-Safe-EMR-MCP
.\.venv\Scripts\python.exe .\seed_demo_data.py

啟動 MCP Server

cd C:\Users\rui\Desktop\mcp課程\Local-Safe-EMR-MCP
.\.venv\Scripts\python.exe .\server.py

預設 MCP endpoint:

http://127.0.0.1:9000/mcp

MCP Tools

list_cases

列出可查詢的病例 ID。

回傳範例:

{
  "case_ids": ["CASE-001", "CASE-002", "CASE-003"]
}

get_deidentified_case

用病例 ID 查詢病例。MCP server 會讀取本地原始病例,呼叫 deidentify.py 去識別化,再回傳脫敏後文字。

參數:

{
  "case_id": "CASE-001"
}

回傳範例:

{
  "ok": true,
  "case_id": "CASE-001",
  "deidentified_text": "病患PATIENT_001,身分證 NATIONAL_ID_001,電話 PHONE_001...",
  "note": "Raw EMR text stayed local. Only de-identified text is returned."
}

Antigravity MCP 設定

一般使用時,直接連 MCP server:

{
  "mcpServers": {
    "local-safe-emr": {
      "serverUrl": "http://127.0.0.1:9000/mcp"
    }
  }
}

如果要觀察 MCP 通訊,改連 debug proxy:

{
  "mcpServers": {
    "local-safe-emr": {
      "serverUrl": "http://127.0.0.1:9001/mcp"
    }
  }
}

MCP 通訊教學 Proxy

mcp_debug_proxy.py 是一個 CLI reverse proxy,專門用來觀察 MCP over HTTP 的 JSON-RPC 通訊。

流向:

Antigravity -> http://127.0.0.1:9001/mcp
mcp_debug_proxy.py -> http://127.0.0.1:9000/mcp
server.py

啟動:

.\.venv\Scripts\python.exe .\mcp_debug_proxy.py --listen 9001 --target http://127.0.0.1:9000

預設輸出是精簡模式:

  • 不印 HTTP headers
  • 不印 SSE ping
  • JSON 單行顯示
  • 只顯示 MCP request/response body

範例輸出:

>>> POST /mcp
{"jsonrpc":"2.0","id":3,"method":"tools/list","params":{}}

<<< 200 /mcp
{"jsonrpc":"2.0","id":3,"result":{"tools":[...]}}

常用參數:

# 多行 JSON
.\.venv\Scripts\python.exe .\mcp_debug_proxy.py --pretty

# 顯示 headers
.\.venv\Scripts\python.exe .\mcp_debug_proxy.py --verbose

# 顯示 SSE ping
.\.venv\Scripts\python.exe .\mcp_debug_proxy.py --show-ping

MCP 通訊重點

MCP message 本身是 JSON-RPC 2.0:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_deidentified_case",
    "arguments": {
      "case_id": "CASE-001"
    }
  }
}

HTTP transport 則會使用:

POST /mcp
GET /mcp
Mcp-Session-Id
text/event-stream

常見流程:

initialize
notifications/initialized
tools/list
tools/call

因為 MCP HTTP transport 會使用 streaming/SSE,連線可能維持一段時間,不像一般 REST API 每次都立即結束。

教學建議

一般 demo:

Antigravity -> 127.0.0.1:9000/mcp -> MCP server

通訊觀察 demo:

Antigravity -> 127.0.0.1:9001/mcp -> debug proxy -> 127.0.0.1:9000/mcp

建議上課流程:

  1. 啟動 vLLM。
  2. 啟動 MCP server。
  3. 讓 Antigravity 直接連 9000,確認 tools 可用。
  4. 啟動 mcp_debug_proxy.py。
  5. 將 Antigravity 改連 9001。
  6. 呼叫 list_cases 與 get_deidentified_case,觀察 JSON-RPC。

注意事項

  • 這是教學 demo,不是正式醫療系統。
  • SQLite 內含模擬個資,請勿放真實病人資料。
  • 本專案不保存去識別化 mapping。
  • 若 LLM 回應慢,deidentify.py 的 HTTP timeout 目前設定為 180 秒。
  • 第一次呼叫 vLLM 可能較慢,建議課前先預熱模型。

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选