Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

ICD-10-CM Medical Coding

БесплатноНе проверен

Provides ICD-10-CM medical coding tools with a RAG pipeline for clinical note analysis.

GitHubEmbed

Описание

Provides ICD-10-CM medical coding tools with a RAG pipeline for clinical note analysis.

README

A Model Context Protocol (MCP) server that provides AI agents with accurate ICD-10-CM medical coding capabilities through a 3-stage RAG pipeline.


What Is This Project?

This is an ICD-10-CM MCP (Model Context Protocol) server that lets any AI agent, Claude Desktop, LangGraph agent, or web application look up and assign accurate ICD-10-CM billing codes from plain-English clinical notes or medical queries.

ICD-10-CM codes are the standardized diagnostic codes used in healthcare for insurance claims, medical records, and billing. Instead of manually searching through massive code books, AI agents can use this server to:

  • Search for codes using natural language medical terms
  • Automatically code clinical notes by extracting diagnoses and matching them to the most accurate ICD-10 codes with clinical rationale

The Two Tools

This server exposes two tools that any MCP-compatible AI agent can call:

l 3-Stage RAG Pipeline

What it does: Takes a complete clinical note (lab report, discharge summary, progress note) and returns structured ICD-10 codes with rationale.

When to use: You have a full clinical document and need accurate billing codes.

Speed: ~15-30 seconds (calls LLM twice: planner + selector)

Example:

Input: Lab report showing elevated glucose, HbA1c 9.2%, creatinine 2.1, eGFR 38
Output: 
  - E11.22 (Type 2 diabetes mellitus with diabetic chronic kidney disease)
  -ic kidney disease, stage 3)
  - Clinical rationale for each code selection

2. search_icd10 — Fast Semantic Vector Search

What it does: Takes a plain-English medical query and returns the top matching ICD-10 codes.

When to use: Quick lookups when you know the condition but need the code.

Speed: ~2-3 seconds

Example:

Query: "type 2 diabetes with chronic kidney disease"
Returns: E11.22, E11.9, N18.3, etc. with descriptions and relevance scores

lly — The RAG Pipeline

The code_clinical_note tool uses a 3-stage RAG (Retrieval-Augmented Generation) pipeline to ensure accurate, clinically-sound ICD-10-CM code assignment.

Stage 1 — Planner (planner.py)

Goal: Extract clinical problems from the note and generate optimized search queries.

How it works:

  1. Takes the raw clinical note as input
  2. Sends it to an LLM via OpenRouter (default: openai/gpt-4o-mini) with a detailed system prompt that acts as a "clinical query planner"
  3. The LLM analyzes the note and extracts a structured list of clinical problems
    • Example problem", "Anemia in CKD"
  4. For each problem, the LLM generates 2–4 semantic search queries optimized for matching ICD-10-CM code titles in a vector database
    • Example queries for "Type 2 diabetes with CKD":
      • "type 2 diabetes mellitus with diabetic chronic kidney disease"
      • "T2DM with renal complications"
      • "diabetes mellitus type 2 with nephropathy"
  5. Returns structured JSON:
    {
      "problems": [
        {
          "problem": "Type 2 diabetes mellitus with chronic kidney disease",
          "confidence": "high",
          "queries": ["...", "...", "..."]
        }
      ]
    }
    

Why this matters: The planner ensures we search for the right things. A raw clinical note might say "elevated HbA1c 9.2% with reduced eGFR 38" — the planner translates this into proper medical terminology that matches ICD-10 code descriptions.

Stage 2 — Retriever (retriever.py)

Goal: Find the best candidate ICD-10 codes for each clinical problem using vector search and ranking fusion.

it works:**

  1. Batch Embedding: Takes all queries from the planner (across all problems) and batch-embeds them in a single API call to OpenRouter (default: openai/text-embedding-3-small)

    • This is much faster than embedding queries one-by-one
  2. Vector Search: For each problem, runs multiple Pinecone vector queries (one per query generated by the planner)

    • Each query retrieves top_k=16 results from the Pinecone index
    • The Pinecone index contains pre-embedded ICD-10-CM ctadata)
  3. Reciprocal Rank Fusion (RRF): Combines results from multiple queries using RRF scoring

    • RRF formula: score = Σ(1 / (k + rank)) where k=60
    • This ensures codes that appear in multiple query results get boosted
  4. Lexical Re-ranking: Adds a lexical similarity score to catch exact term matches

    • Token overlap: measures how many words from the query appear in the code title
    • SequenceMatcher: measures character-level similarity
    • Final score: 75% RRF + 25% lexical
  5. De-duplication: Returns up to 40 unique candidate codes per problem, sorted by final score

Why this matters: A single query might miss relevant codes. By generating multiple queries and fusing results, we cast a wider net while still prioritizing the most relevant codes. The lexical re-ranking ensures we don't miss codes with exact terminology matches.

Stage 3 — Selector (selector.py)

Goal: Select the most accurate ICD-10 codes from the candidates using clinical coding rules.

How it works:

  1. Takes the original clinical note + all candidate codes per problem
  2. Sends everything to an LLM via OpenRouter (default: openai/gpt-4o-mini) with a strict system prompt that applies ICD-10-CM coding rules:
    • Prefer most-specific combination codes (e.g., E11.22 over E11.9 + N18.3)
    • Enforce etiology-manifestation coding (code the underlying cause first)
    • Drop parent codes when child codes are present (e.g., if E11.22 is selected, don't also include E11) codes across problems** (each code appears only once)
    • Avoid "unspecified" codes when specific codes are available
  3. The LLM reviews each candidate and decides whether to include it, providing clinical rationale
  4. Returns final selected codes with rationale per problem:
    {
      "results": [
        {
          "problem": "Type 2 diabetes with CKD",
          "selected_codes": [
            {
              "code": "E11.22",
              "title": "Type 2 diabetes mellitus disease",
              "rationale": "Combination code captures both diabetes and CKD relationship"
            }
          ]
        }
      ]
    }
    

Why this matters: Vector search alone can return too many codes or miss coding rules. The selector applies clinical expertise to choose the right codes and explain why, ensuring the output is billable and clinically accurate.

MCP Protocol Layer (server.py)

Goal: Expose the pipeline as MCP tools that any AI agent can call.

How it works:

  • Built on the mcp Python SDK
  • Supports two transports:
    • stdio — for local Claude Desktop use (no network, runs as subprocess)
    • HTTP/SSE — for remote use by LangGraph, web apps, agents, n8n, etc.
  • Per-request OpenRouter API key injection via X-OpenRouter-API-Key header
    • Users bring their own OpenRouter key; the server never stores it
    • This allows the hosted server to be used by anyone without exposing API keys
  • Health check endpoint at /health for monitoring and uptime checks

Architecture:

Client (Claude Desktop, LangGraph, etc.)
    │
    ▼
MCP Server (stdio or HTTP/SSE)
    │
    ├─► Planner ──► OpenRouter LLM (extract problems + queries)
    │
    ├─► Retriever ──► OpenRouter Embeddings + Pinecone (vector search + RRF)
    │
    └─► Selector ──► OpenRouter LLM (select codes + rationale)

Prerequisites

Before using this MCP server, you need:

  1. Python 3.10 or higher installed on your system

    • Index name: icd10cm-2026
    • Namespace: icd10cm_2026
    • The index should contain embedded ICD-10-CM codes with metadata (code, title, parent_code, level)
  2. An OpenRouter API key — get one at openrouter.ai

  3. Environment variables (for local/self-hosted use):

    • PINECONE_API_KEY — your Pinecone API key
    • PINECONE_INDEX_NAME — default: icd10cm-2026
    • PINECONE_NAMESPACE — default: icd10cm_2026
    • OPENROUTER_API_KEY — your OpenRouter API key

Integration Examples — How to Use This MCP Server

This server can be integrated with any MCP-compatible AI agent or application. Below are integration guides for common use cases.

A. Claude Desktop (Remote Hosted Server)

Connect Claude Desktop to the hosted server at https://icd10-mcp.onrender.com/sse using the supergateway bridge.

Step 1: Copy the configuration from claude_desktop_config_example.json:

{
  "mcpServers": {
    "icd10-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "supergateway",
        "--sse",
        "https://icd10-mcp.onrender.com/sse",
        "--header",
        "X-OpenRouter-API-Key: sk-or-v1-YOUR_OPENROUTER_API_KEY_HERE"
      ]      
    }
  }
}

Step 2: Locate your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Step 3: Add the configuration to your Claude Desktop config file (merge with existing mcpServers if you have others)

Step 4: Replace sk-or-v1-YOUR_OPENROUTER_API_KEY_HERE with your actual OpenRouter API key

Step 5: Restart Claude Desktop

Step 6: Test it by asking Claude:

"Search for ICD-10 codes for hypertension with heart disease"

How it works:

  • supergateway is an NPM package that bridges SSE (Server-Sent Events) to stdio
  • Your OpenRouter API key is sent in the X-OpenRouter-API-Key header with each request
  • The hosted server at https://icd10-mcp.onrender.com/sse handles the requests
  • No need to run anything locally — the server is always available

B. LangGraph Agent

Connect a LangGraph agent to the hosted MCP server using the langchain-mcp-adapters package.

Installation:

pip install langchain-mcp-adapters

Example Code:

from langchain_mcp_adapters.client import MultiServerMCPClient
import asyncio

async def create_icd10_agent():
    """Create a LangGraph agent with ICD-10 MCP tools."""
    
    # Connect to the hosted MCP server
    client = MultiServerMCPClient({
        "icd10-mcp": {
    /sse",
            "transport": "sse",
            "headers": {
                "X-OpenRouter-API-Key": "sk-or-v1-YOUR_OPENROUTER_API_KEY_HERE"
            }
        }
    })
    
    # Get available tools
    tools = await client.get_tools()
    print(f"Available tools: {[t.name for t in tools]}")
    
    # Call a tool
    result = await client.call_tool(
        "search_icd10",
        arguments={"query": "type 2 diabetes", "top_k": 5}
    )
    print(f"Results: {result}")
    
    # Use tools in t
    # ... your LangGraph state machine code here ...
    
    return client

# Run the agent
asyncio.run(create_icd10_agent())

Using with LangGraph State Machine:

from langgraph.graph import StateGraph, END
from typing import TypedDict

class AgentState(TypedDict):
    clinical_note: str
    icd_codes: list

async def code_note_node(state: AgentState):
    """Node that calls the ICD-10 MCP server."""
    client = MultiServerMCPClient({
        "icd10-mcp": {
            "url": "https://icd10-mcp.onrender.com/sse",
            "transport": "sse",
            "headers": {"X-OpenRouter-API-Key": "sk-or-v1-YOUR_KEY"}
        }
    })
    
    result = await client.call_tool(
        "code_clinical_note",
        arguments={
            "note": state["clinical_note"],
            "max_codes_per_problem": 2
        }
    )
    
    return {"icd_codes": result}

# Build the graph
workflow = StateGraph(AgentState)
workflow.add_node("code_note", code_note_node)
workflow.set_entry_point("code_note")
dd_edge("code_note", END)

app = workflow.compile()

D. Direct HTTP / Any Web App or Backend

Call the MCP server directly via HTTP/SSE from any programming language.

Server Details:

  • Base URL: https://icd10-mcp.onrender.com
  • SSE Endpoint: GET /sse (for MCP protocol connection)
  • Messages Endpoint: POST /messages/ (for tool calls)
  • Health Check: GET /health
  • Required Header: X-OpenRouter-API-Key: sk-or-v1-YOUR_OPENROUTER_API_KEY

Python Example (using requests):

import requests
import json

MCP_SERVER_URL = "https://icd10-mcp.onrender.com"
OPENROUTER_API_KEY = "sk-or-v1-YOUR_KEY"

# Health check
response = requests.get(f"{MCP_SERVER_URL}/health")
print(response.json())

# Call search_icd10 tool
response = requests.post(
    f"{MCP_SERVER_URL}/messages/",
    json={
        "method": "tools/call",
        "params": {
            "name": "search_icd10",
            "arguments": {"query": "hypertension", "top_k": 5}
        }
    },
    headers={
        "X-OpenRouter-API-Key": OPENROUTER_API_KEY,
        "Content-Type": "application/json"
    }
)

result = response.json()
print(json.dumps(result, indent=2))

# Call code_clinical_note tool
clinical_note = """
Patient presents with elevated blood pressure 158/96 mmHg.
History of type 2 diabetes, HbA1c 9.2%.
Creatinine 2.1 mg/dL, eGFR 38 mL/min.
"""

response = requests.post(
    f"{MCP_SERVER_URL}/messages/",
    json={
        "method": "tools/call",
        "params": {
            "name": "code_clinical_note",
            "arguments": {
                "note": clinical_note,
                "max_codes_per_problem": 2
            }
        }
    },
    headers={
        "X-OpenRouter-API-Key": OPENROUTER_API_KEY,
        "Content-Type": "application/json"
    }
)

result = response.json()
print(json.dumps(result, indent=2))

JavaScript Example (using fetch):

const MCP_SERVER_URL = "https://icd10-mcp.onrender.com";
const OPENROUTER_API_KEY = "sk-or-v1-YOUR_KEY";

// Health check
fetch(`${MCP_SERVER_URL}/health`)
  .then(res => res.json())
  .then(data => console.log(data));

// Call search_icd10 tool
fetch(`${MCP_SERVER_URL}/messages/`, {
  method: "POST",
  headers: {
    "X-OpenRouter-API-Key": OPENROUTER_API_KEY,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    method: "tools/call",
    params: {
      name: "search_icd10",
      arguments: { query: "diabetes", top_k: 5 }
    }
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

// Call code_clinical_note tool
const clinicalNote = `
Patient presents with elevated blood pressure 158/96 mmHg.
History of type 2 diabetes, HbA1c 9.2%.
Creatinine 2.1 mg/dL, eGFR 38 mL/min.
`;

fetch(`${MCP_SERVER_URL}/messages/`, {
  method: "POST",
  headers: {
    "X-OpenRouter-API-Key": OPENROUTER_API_KEY,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    method: "tools/call",
    params: {
      name: "code_clinical_note",
      arguments: {
        note: clinicalNote,
        max_codes_per_problem: 2
      }
    }
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

E. Any AI Agent (Generic MCP Client)

Any MCP-compatible client can connect to this server using SSE (Server-Sent Events) transport.

Connection Details:

  • URL: https://icd10-mcp.onrender.com/sse
  • Transport: SSE (Server-Sent Events)
  • Required Header: X-OpenRouter-API-Key: sk-or-v1-YOUR_OPENROUTER_API_KEY
  • Tools Available: code_clinical_note, search_icd10

Generic Pattern:

import requests

# Connect to SSE endpoint
response = requests.get(
    "https://icd10-mcp.onrender.com/sse",
    headers={"X-OpenRouter-API-Key": "sk-or-v1-YOUR_KEY"},
    stream=True
)

# The server will send MCP protocol messages via SSE
# Your client should parse SSE events and handle MCP JSON-RPC messages

Environment Variables Reference

Variable Required Default Description
PINECONE_API_KEY Yes Your Pinecone API key
PINECONE_INDEX_NAME No icd10cm-2026 Name of your Pinecone index
PINECONE_NAMESPACE No icd10cm_2026 Namespace within the Pinecone index
OPENROUTER_API_KEY Yes* Your OpenRouter API key
PLANNER_MODEL No openai/gpt-4o-mini LLM model for the planner stage
SELECTOR_MODEL No openai/gpt-4o-mini LLM model for the selector stage
EMBED_MODEL No openai/text-embedding-3-small Embedding model for vector search
PORT No 8000 Port for HTTP/SSE server (HTTP mode only)

*Note: OPENROUTER_API_KEY is required for HTTP/SSE mode. Users provide their OpenRouter key via the X-OpenRouter-API-Key header with each request.

from github.com/ansh-bitontree/icd10-mcp

Установка ICD-10-CM Medical Coding

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/ansh-bitontree/icd10-mcp

FAQ

ICD-10-CM Medical Coding MCP бесплатный?

Да, ICD-10-CM Medical Coding MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для ICD-10-CM Medical Coding?

Нет, ICD-10-CM Medical Coding работает без API-ключей и переменных окружения.

ICD-10-CM Medical Coding — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить ICD-10-CM Medical Coding в Claude Desktop, Claude Code или Cursor?

Открой ICD-10-CM Medical Coding на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare ICD-10-CM Medical Coding with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai