Skip to content

io.github.cyanheads/medical-codes-mcp-server

by cyanheads · remote · local (npm) · no sign-in to list tools · v0.4.1 · published by GitHub user cyanheads

Offline US medical code lookup and crosswalk — ICD-10-CM/PCS, HCPCS Level II, RxNorm. Keyless.

Changes · 2

6 tools: 2 change things and 4 only read.

Scanned Oct 21, 2026

2 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http medical-codes https://medical-codes.caseyjhand.com/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn1 info
  • The server marks "medcode_check_code" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "validate": a word for reading.

    What this check looks for
  • The description is 2,628 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...ss directions, and a `system` other than RXNORM on the drug and class directions."

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

6 tools

Changes things 2Claude Code: ask
  • medcode_check_codeValidate whether a US medical code exists, is current, and is billable in the active bundled release.1 finding

    Why it is in this group

    • The description's first verb is "validate": a word for reading.
    • The input takes a statement or command to run (input.code), which can change anything it can reach.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "medcode_check_code" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "validate": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Validate whether a US medical code exists, is current, and is billable in the active bundled release. Returns a discriminated status — valid_billable, valid_not_billable, valid_header, valid, or terminated — with a `whyNot` explaining non-billable and terminated cases (e.g. "valid ICD-10-CM category but not billable — submit a more specific child code"). This is the detail a coder needs before submitting a claim. RxNorm has no billing concept, so a current RxNorm concept is `valid` with `billable: null` and no billing verdict. Auto-detects the system from the code's shape; pass an explicit `system` to disambiguate. A non-billable or terminated code is a successful result with a whyNot, not an error — only a code absent from the named or detected system raises unknown_code, which names the other bundled system when one holds the code. A code string that also exists in another bundled system carries `alsoInSystems` naming it, since the verdict applies only to the system that answered.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • medcode_map_codesCrosswalk a US medical code or drug across systems and within a hierarchy.1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Info

      The description is 2,628 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...ss directions, and a `system` other than RXNORM on the drug and class directions."

      What this check looks for
    Description, as the server wrote it
    Crosswalk a US medical code or drug across systems and within a hierarchy. Hierarchy directions: `parents` and `children` walk a code's prefix hierarchy one level per call — immediate parent/children only (depth-1); call iteratively for the full ancestor or descendant path (ICD-10-CM/HCPCS; ICD-10-PCS codes have no prefix parent, and RxNorm concepts no code hierarchy). A resolvable source with no edge in the requested direction is a successful empty result with a notice, not an error. A source code string that also exists in another bundled system carries `alsoInSystems` naming it, since only the resolved system's hierarchy was walked. Drug directions (RxNorm): `name_to_rxcui` (drug name → RXCUI), `ndc_to_rxcui` and `rxcui_to_ndc` (NDC ↔ RXCUI; NDCs accepted hyphenated in an FDA segment configuration — 4-4-2, 5-3-2, 5-4-1, or the 11-digit 5-4-2 — or as bare 10/11 digits; `ndc_to_rxcui` names the product it decoded to), `rxcui_to_ingredients` and `rxcui_to_brands` (RXCUI → ingredient/brand RXCUIs, each with the target's RxNorm name and its `conceptType` — read that before counting a combination product's ingredients). Drug-class directions (RxClass): `rxcui_to_classes` (RXCUI → its classes: pharmacologic class, mechanism of action, physiologic effect, pharmacokinetics, therapeutic category, chemical structure, the diseases it may treat, prevent, diagnose, or induce or is contraindicated with, VA class, DEA controlled-substance schedule, CDC vaccine code; a drug product also carries its ingredients' classes, naming the ingredient in `via`, while DEA schedules are recorded only on drug products and VA classes almost only there, so map a product for those) and `class_to_rxcuis` (class ID → its direct member RXCUIs, each with its RxNorm name and `conceptType`). Each class hit carries `classType`, `source` (the RxClass source asserting it), and `relation` — a `ci_` relation is a contraindication, not an indication; narrow either direction with `classType`. Every result carries `source` provenance (which system or edge answered) so a chained call (e.g. into openfda with a resolved NDC) uses the right identifier. The `children`, `name_to_rxcui`, `rxcui_to_ndc`, `rxcui_to_classes`, and `class_to_rxcuis` directions can return large sets and paginate: a `nextCursor` in the response is passed back as `cursor` (with an optional `limit` page size) to walk the full set. A field the direction does not use is rejected with `field_not_applicable`: `limit` and `cursor` on the point directions, `classType` outside the class directions, and a `system` other than RXNORM on the drug and class directions.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
Only reads 4Claude Code: allow
  • medcode_browse_hierarchyWalk a US medical code system's hierarchy for discovery without a search term.No findings

    Why it is in this group

    • The name "medcode_browse_hierarchy" says "browse": a word for reading.
    Description, as the server wrote it
    Walk a US medical code system's hierarchy for discovery without a search term. With no `node`, returns the top-level entries (ICD-10-CM categories, HCPCS range buckets, or ICD-10-PCS first-axis values). With a `node`, returns its immediate children. ICD-10-CM and HCPCS use a prefix hierarchy (a shorter code is the parent of a longer one); ICD-10-PCS is axis-based — each of its 7 characters is an independent axis (section, body system, root operation, body part, approach, device, qualifier), but only the top-level Section axis is browsable (omit `node`): positions 2–7 are context-dependent on the preceding axis path and are not enumerable from a flat partial code. Lets an agent orient in an unfamiliar system or enumerate a category's specific codes. A large child set paginates: when the response carries a `nextCursor`, pass it back as `cursor` to fetch the next page.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • medcode_get_codeDecode one or more US medical codes to their official descriptions across ICD-10-CM (diagnoses), ICD-10-PCS (inpatient procedures), HCPCS Level II (supplies/drugs/services), and Rx…No findings

    Why it is in this group

    • The name "medcode_get_code" says "get": a word for reading.
    Description, as the server wrote it
    Decode one or more US medical codes to their official descriptions across ICD-10-CM (diagnoses), ICD-10-PCS (inpatient procedures), HCPCS Level II (supplies/drugs/services), and RxNorm (drugs, by RXCUI). Also decodes a National Drug Code (NDC) directly to its RxNorm product offline, tagged `source: "NDC"` — hyphenated in an FDA segment configuration (4-4-2, 5-3-2, 5-4-1, or the 11-digit 5-4-2) or as bare 10/11 digits; any other segment widths are malformed and stay unresolved. Auto-detects the system from each code's shape; pass an explicit `system` only when a value is genuinely ambiguous. Accepts 1–50 codes and returns partial success: resolved codes in `found`, unresolved in `notFound` with a per-code reason, so one bad code never fails the batch. Set `includeHierarchy` to attach each code's parent and immediate children (with a `childrenTruncated` flag when a code has more children than the cap returns — walk the full set via medcode_browse_hierarchy or medcode_map_codes). The resolved `system` is echoed on every result for chaining into a billability check or a medcode_map_codes parents/children walk; a bare integer that resolves nowhere is named as a possible CPT / HCPCS Level I code, which is out of scope, except a bare 10/11-digit one, which is named as an NDC no bundled drug maps to; a code string that also exists in another bundled system carries `alsoInSystems` naming it, so a single answer to a colliding code is never mistaken for the only one.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • medcode_list_systemsList the bundled US medical code systems with their release identifiers, effective dates, and code counts, and the RxClass drug-class layer the class crosswalks read, with each sou…No findings

    Why it is in this group

    • The name "medcode_list_systems" says "list": a word for reading.
    Description, as the server wrote it
    List the bundled US medical code systems with their release identifiers, effective dates, and code counts, and the RxClass drug-class layer the class crosswalks read, with each source’s version. Confirms which ICD-10-CM fiscal year, ICD-10-PCS fiscal year, HCPCS Level II release, RxNorm normalized set, and RxClass sources are active before acting on any decode, search, or crosswalk result. The corpus is offline and built at package-build time — this call reports exactly which release is baked into the running server. ICD-10-CM/PCS are the US clinical modifications, not the ICD-10/ICD-11 base.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • medcode_search_codesFind US medical codes whose official descriptions match a described concept, via full-text search over the bundled index.No findings

    Why it is in this group

    • The name "medcode_search_codes" says "search": a word for reading.
    Description, as the server wrote it
    Find US medical codes whose official descriptions match a described concept, via full-text search over the bundled index. Every search term must appear — matched first as a token prefix, then as a substring so inflected and compound forms are also found (a "neuropathy" search surfaces "mononeuropathy"/"polyneuropathy" siblings too, not only a standalone "neuropathy" token). An RxNorm concept matches on its drug name alone, never its term type (SBD, IN, …) — narrow by type with `chapter`. Filter by `system` (ICD10CM/ICD10PCS/HCPCS/RXNORM), `billableOnly` to exclude headers/categories, and `chapter`. Use when you have a clinical description and need the code — the reverse of medcode_get_code. Results echo the resolved system per row for chaining, rank exact prefix matches ahead of substring-only matches with a deterministic tie-break, and disclose truncation with a `nextCursor`: pass it back as `cursor` to page through the full ranked set.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.4.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http medical-codes https://medical-codes.caseyjhand.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__medical-codes__medcode_get_code",
      "mcp__medical-codes__medcode_search_codes",
      "mcp__medical-codes__medcode_browse_hierarchy",
      "mcp__medical-codes__medcode_list_systems"
    ],
    "ask": [
      "mcp__medical-codes__medcode_check_code",
      "mcp__medical-codes__medcode_map_codes"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as medical-codes. Review it before you use it.