Overview
Available since Healthcare NLP 6.3.0
The Model Context Protocol (MCP) De-identification Servers enable AI coding assistants (such as Cursor and VS Code Copilot) to access state-of-the-art clinical de-identification pipelines directly as tools. This integration allows you to sanitize clinical text instantly within your IDE while maintaining strict HIPAA compliance through local, secure execution.
Key Features
- Direct integration with Cursor and VS Code
- Local execution for HIPAA compliance
- Support for both masking and obfuscation modes
- Detection of 30+ PHI entity types
- Two deployment architectures for different use cases
Architecture Options
Two architectures are available to accommodate different deployment requirements:
Lightweight Architecture (v2) - Recommended
A thin, instant-startup Python server that connects your IDE to a robust backend de-identification service.
Specifications:
- Startup Time: < 1 second
- Memory: ~100MB (MCP server)
- Ports: 8001 (MCP) + 9000 (backend)
- Best For: Teams sharing a backend GPU server; frequent IDE restarts
Architecture Diagram:
IDE (Cursor/VSCode) → MCP Server v2 → Deid Service Container → Spark NLP Healthcare
Monolithic Architecture (v1)
Battery-included approach with the Spark NLP pipeline embedded directly inside the MCP server container.
Specifications:
- Startup Time: 2-5 minutes (pipeline loading)
- Memory: 8GB+ reserved
- Port: 8000
- Best For: Air-gapped environments; single-container deployments
Architecture Diagram:
IDE (Cursor/VSCode) → MCP Server v1 (containing embedded Spark NLP Pipeline)
Architecture Comparison
| Aspect | v1 Monolithic | v2 Lightweight |
|---|---|---|
| Port | 8000 | 8001 (MCP) + 9000 (backend) |
| Memory | 8GB+ reserved | ~100MB (MCP server only) |
| Startup Time | 2-5 minutes | Instant (<1 second) |
| Docker Required | Yes | MCP: No, Backend: Yes |
| Use Case | Standalone deployment | Shared backend, multiple clients |
Prerequisites
- Docker and Docker Compose installed
- Valid John Snow Labs Healthcare NLP license
- 8GB+ available memory for pipeline container
- Cursor or VS Code with GitHub Copilot
License Configuration
Both architectures require a valid John Snow Labs Healthcare NLP license provided via a spark_jsl.json file.
Required License Keys
{
"SPARK_NLP_LICENSE": "eyJ...",
"SECRET": "x.x.x-xxxxxxxxx"
}
| Key | Description |
|---|---|
SPARK_NLP_LICENSE |
JWT license token for Spark NLP Healthcare |
SECRET |
PyPI token for private package installation |
Optional License Keys
{
"SPARK_OCR_LICENSE": "eyJ...",
"AWS_ACCESS_KEY_ID": "AKIA...",
"AWS_SECRET_ACCESS_KEY": "...",
"AWS_SESSION_TOKEN": "..."
}
These keys are required for OCR capabilities or S3 model downloads.
Security: Docker Secrets
The license file is mounted as a Docker secret at /run/secrets/spark_jsl.json to keep credentials secure and prevent them from being baked into Docker images.
# docker-compose.yml
secrets:
spark_jsl:
file: ./spark_jsl.json
services:
deid-service:
secrets:
- source: spark_jsl
target: spark_jsl.json
Note: If you do not have a JSL Healthcare NLP license, visit johnsnowlabs.com to request a trial.
Installation Steps
Step 1: Clone the Repository
git clone https://github.com/JohnSnowLabs/spark-nlp-workshop.git
cd spark-nlp-workshop/agents/mcp_servers/deidentification
Step 2: Configure License File
Option A: Copy example and edit
cp spark_jsl.json.example spark_jsl.json
# Edit spark_jsl.json with your actual JSL license credentials
Option B: Copy existing license
cp /path/to/your/spark_jsl.json ./deid-service/spark_jsl.json
Step 3: Start Backend Service
cd deid-service
# Set JSL secret for Docker build
export JSL_SECRET=$(jq -r '.SECRET' spark_jsl.json)
# Build and start
docker compose up --build
Wait for the service to report “Application startup complete”. First startup takes 2-5 minutes for model download; subsequent starts are faster due to caching.
Test the backend:
curl -X POST http://localhost:9000/deidentify \
-H "Content-Type: application/json" \
-d '{"text":"Dr. John Lee treated patient Emma Wilson","mode":"both"}'
Step 4: Start MCP Server
Option A: Lightweight v2 (Recommended)
cd jsl-deid-mcp-server-v2
pip install -e .
python -m src.server
Server starts on http://localhost:8001/mcp
Option B: Monolithic v1
cd jsl-deid-mcp-server-v1
export JSL_SECRET=$(jq -r '.SECRET' spark_jsl.json)
docker compose up --build
Server starts on http://localhost:8000/mcp
Step 5: Configure IDE Client
Cursor Configuration
Add to ~/.cursor/mcp.json (macOS/Linux):
{
"mcpServers": {
"jsl-deid": {
"url": "http://localhost:8001/mcp",
"transport": "streamable-http"
}
}
}
Restart Cursor after updating the configuration.
VS Code Copilot Configuration
Add to project_folder/.vscode/mcp.json:
{
"mcp.servers": {
"jsl-deid": {
"url": "http://localhost:8001/mcp",
"type": "http"
}
}
}
Restart VS Code after updating the configuration.
Verification (Optional)
Initialize Session
curl -s -i -X POST http://localhost:8001/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}'
Call De-identification Tool
Replace <SESSION_ID> with the mcp-session-id from the initialize response header:
curl -s -X POST http://localhost:8001/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <SESSION_ID>" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "deidentify_text",
"arguments": {
"text": "Dr. John Lee treated patient Emma Wilson on 11/05/2024.",
"mode": "both"
}
},
"id": 2
}'
Usage
Sample Clinical Text
Dr. John Lee, from Royal Medical Clinic in Chicago, attended to the patient on 11/05/2024.
The patient's medical record number is 56467890.
The patient, Emma Wilson, is 50 years old, her Contact number: 444-456-7890.
Output Modes
Mode: masked
PHI entities replaced with labels:
Dr. <NAME>, from <HOSPITAL> in <CITY>, attended to the patient on <DATE>.
The patient's medical record number is <ID>.
The patient, <PATIENT>, is <AGE> years old, her Contact number: <PHONE>.
Mode: obfuscated
PHI entities replaced with realistic fake values:
Dr. Vivia Ammon, from Baltimore Va Medical Center in Healdton, attended to the patient on 06/06/2024.
The patient's medical record number is 25958147.
The patient, Marla Sakai, is 40 years old, her Contact number: 999-925-8147.
Mode: both
Returns both masked and obfuscated versions in a single response:
{
"masked": "Dr. <DOCTOR>, from <HOSPITAL> in <CITY>, attended to the patient on <DATE>.\nThe patient's medical record number is <MEDICALRECORD>.\nThe patient, <PATIENT>, is <AGE> years old, her Contact number: <PHONE>.",
"obfuscated": "Dr. Vivia Ammon, from Baltimore Va Medical Center in Healdton, attended to the patient on 06/06/2024.\nThe patient's medical record number is 25958147.\nThe patient, Marla Sakai, is 40 years old, her Contact number: 999-925-8147.",
"error": null
}
Using in Cursor
In the Cursor chat:
Use the Deid MCP to de-identify this clinical note with masked output.
"Dr. John Lee, from Royal Medical Clinic in Chicago, attended to the patient on 11/05/2024..."
Cursor will automatically invoke the deidentify_text tool and return the result.
Using in VS Code Copilot
In VS Code Copilot Chat:
Utilize the Deid MCP to anonymize this clinical note, employing both masked and obfuscated output modes.
"Dr. John Lee, from Royal Medical Clinic in Chicago, attended to the patient on 11/05/2024..."
Supported PHI Entity Types
The pipeline detects and processes 30+ PHI entity types including:
Personal Identifiers:
PATIENT,DOCTOR,USERNAMEAGE,DATESSN,DLN(Driver’s License),LICENSE
Contact Information:
PHONE,FAX,EMAIL,URL
Location Data:
HOSPITAL,CITY,STATE,COUNTRY,ZIPSTREET,LOCATION
Medical Identifiers:
MEDICALRECORD,HEALTHPLAN,ACCOUNTIDNUM,BIOID
Organization:
ORGANIZATION,PROFESSION
Vehicle/Device:
DEVICE,PLATE,VIN
The underlying pipeline is clinical_deidentification from Spark NLP Healthcare, which combines NER models, rule-based matchers, and contextual parsers for high-accuracy PHI detection.
Technical Details
Privacy by Design
The servers log request metadata (text size, mode, latency) but never log clinical content:
# What is logged
logger.info(f"Deidentify request: {len(text)} chars, mode={mode}")
logger.info(f"Deidentify completed: {elapsed_ms:.0f}ms")
# What is never logged
# logger.info(f"Processing: {text}") # NEVER
Streamable HTTP Transport
The implementation uses FastMCP’s streamable_http_app() with uvicorn for IDE compatibility, providing the HTTP-based transport expected by Cursor and VS Code Copilot.
Pipeline Warmup
On startup, the pipeline processes a sample text to trigger JVM JIT compilation and lazy initialization. This ensures consistent latency for actual requests:
- Without warmup: First request can take 10-30 seconds
- With warmup: Typical latency is 100-500ms depending on text length
Resources
- GitHub Repository: spark-nlp-workshop/agents/mcp_servers/deidentification
- Spark NLP Healthcare Documentation: nlp.johnsnowlabs.com
- Clinical De-identification Model: clinical_deidentification_docwise_benchmark_optimized
- MCP Protocol Specification: modelcontextprotocol.io
Future Additions
This de-identification MCP server is the first in a planned series of healthcare NLP tools for AI assistants:
- Data Curation MCP Server - Clinical entity extraction and structuring
- Medical Coding MCP Server - ICD-10, CPT code assignment
Getting Started
Clone the repository, configure your license, and bring clinical de-identification to your IDE. The v2 lightweight architecture enables you to start in under 10 minutes with post-installation response times of less than a second.