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
Visit Server

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 可能較慢,建議課前先預熱模型。

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured