map_icd10_to_icd11
Convert ICD-10 codes to ICD-11 using authoritative WHO transition tables. Supports dotted and undotted formats, returning primary and alternative categories for clinical coding and billing migration.
Instructions
Authoritative ICD-10 → ICD-11 mapping using WHO transition tables (release 2025-01, bundled with the server).
Returns the primary 1:1 ICD-11 category for the ICD-10 code plus any alternative ICD-11 candidates that WHO documents (some ICD-10 concepts split into multiple ICD-11 entities). For each mapping, includes the ICD-11 code, title, chapter, and the Foundation URI / Linearization URI for navigating to the full entity definition.
Use this for clinical coding, billing migration, retrospective analysis, and any workflow that needs authoritative mapping rather than text-search candidates. Coverage: 11,243 ICD-10 categories (excludes chapters and blocks like "A00-A09" which aren't used in clinical coding).
Provide a code like "E11" (Type 2 diabetes), "I21" (Acute MI), or "A07.8" (4 alternatives in WHO's table). Both dotted ("A07.8") and undotted ("A078") forms are accepted.
Returns "no mapping" when the code isn't in the WHO category-level table — that's the honest answer rather than a fuzzy search fallback.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| icd10_code | Yes | ICD-10 code to query in the ICD-11 search index (e.g., E11, I21.0, J18.9) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The ICD-10 code as submitted (raw, before normalization). | |
| found | Yes | Whether the code is in the WHO ICD-10 → ICD-11 transition table. | |
| icd10 | Yes | Source ICD-10 entry from the WHO table. Null when found=false. | |
| primary | Yes | Primary 1:1 ICD-11 mapping. Null when found=false. | |
| alternatives | Yes | Additional ICD-11 candidates WHO documents for this ICD-10 code. Empty when the primary is the only documented mapping (or when found=false). 1,461 of the 11,243 indexed codes have non-empty alternatives. | |
| source | Yes |
Implementation Reference
- src/tools/crosswalk.ts:143-229 (handler)The main handler function for map_icd10_to_icd11. It parses params via MapICD10ToICD11ParamsSchema, looks up the ICD-10 code via the ICD10ToICD11MapClient, builds a structured output (MapICD10ToICD11Output) with primary and alternative ICD-11 mappings, formats a human-readable text response, and returns the result with structuredContent.
async function handleMapICD10ToICD11(args: Record<string, unknown>): Promise<CallToolResult> { try { const params = MapICD10ToICD11ParamsSchema.parse(args); const client = getICD10ToICD11MapClient(); const inputCode = params.icd10_code.trim(); const entry = client.lookup(inputCode); const structured: MapICD10ToICD11Output = { query: inputCode, found: entry !== null, icd10: entry?.icd10 ?? null, primary: entry?.primary ?? null, alternatives: entry?.alternatives ?? [], source: { publisher: 'WHO', version: client.getVersion(), release_date: client.getReleaseDate(), }, }; const lines: string[] = []; lines.push(`# ICD-10 → ICD-11 mapping for "${inputCode.toUpperCase()}"`); lines.push(''); if (!entry) { lines.push('## No authoritative mapping'); lines.push(''); lines.push( `The code "${inputCode}" is not in the WHO ICD-10 → ICD-11 transition table (release ${client.getVersion()}). This usually means one of:`, ); lines.push(''); lines.push( '- The code is a chapter or block (e.g. "A00-A09") — those aren\'t included; query a category instead.', ); lines.push('- The code is mis-typed or not a valid ICD-10 category.'); lines.push('- The code was removed in the WHO restructuring; try a parent category.'); lines.push(''); lines.push('**Alternative:** Use `icd11_search` with the condition name to explore ICD-11 directly.'); return { content: [{ type: 'text', text: lines.join('\n') }], structuredContent: structured, }; } lines.push( `**ICD-10:** ${entry.icd10.code} — ${entry.icd10.title} (chapter ${entry.icd10.chapter})`, ); lines.push(''); lines.push('## Primary ICD-11 mapping'); lines.push(''); lines.push(`- **Code:** ${entry.primary.code}`); lines.push(`- **Title:** ${entry.primary.title}`); lines.push(`- **Chapter:** ${entry.primary.chapter}`); lines.push(`- **Foundation URI:** ${entry.primary.foundationUri}`); lines.push(`- **Linearization (MMS) URI:** ${entry.primary.linearizationUri}`); lines.push(''); if (entry.alternatives.length > 0) { lines.push(`## Alternative ICD-11 candidates (${entry.alternatives.length})`); lines.push(''); lines.push('WHO documents multiple ICD-11 entities that may map to this ICD-10 concept. Review the alternatives below to pick the best match for your context.'); lines.push(''); lines.push('| Code | Title | Chapter |'); lines.push('|------|-------|---------|'); for (const alt of entry.alternatives) { lines.push(`| ${alt.code} | ${alt.title} | ${alt.chapter} |`); } lines.push(''); } else { lines.push('_No additional ICD-11 candidates beyond the primary mapping._'); lines.push(''); } lines.push('---'); lines.push( `Source: WHO ICD-10 → ICD-11 transition tables, release ${client.getVersion()} (${client.getReleaseDate()}). Authoritative mapping, not a text-search heuristic.`, ); return { content: [{ type: 'text', text: lines.join('\n') }], structuredContent: structured, }; } catch (error) { return handleToolError(error); } } - src/tools/crosswalk.ts:924-924 (registration)Registration of the map_icd10_to_icd11 tool with the toolRegistry, binding the tool definition to its handler function.
toolRegistry.register(mapICD10ToICD11Tool, handleMapICD10ToICD11); - src/types/index.ts:570-575 (schema)Input parameter schema for map_icd10_to_icd11: accepts a 'icd10_code' string (min length 1).
export const MapICD10ToICD11ParamsSchema = z.object({ icd10_code: z .string() .min(1) .describe('ICD-10 code to query in the ICD-11 search index (e.g., E11, I21.0, J18.9)'), }); - src/types/index.ts:669-694 (schema)Output schema for map_icd10_to_icd11: includes query, found boolean, icd10 source, primary ICD-11 mapping, alternatives array, and source metadata (publisher, version, release_date).
export const MapICD10ToICD11OutputSchema = z.object({ query: z.string().describe('The ICD-10 code as submitted (raw, before normalization).'), found: z .boolean() .describe('Whether the code is in the WHO ICD-10 → ICD-11 transition table.'), icd10: ICD10SourceSchema .nullable() .describe('Source ICD-10 entry from the WHO table. Null when found=false.'), primary: ICD11MappingSchema .nullable() .describe('Primary 1:1 ICD-11 mapping. Null when found=false.'), alternatives: z .array(ICD11MappingSchema) .describe( 'Additional ICD-11 candidates WHO documents for this ICD-10 code. Empty when the primary is the only documented mapping (or when found=false). 1,461 of the 11,243 indexed codes have non-empty alternatives.', ), source: z.object({ publisher: z.string().describe('Authoritative publisher (e.g. "WHO").'), version: z .string() .describe('Transition table release identifier (e.g. "2025-01").'), release_date: z.string().describe('ISO date string for the release.'), }), }); export type MapICD10ToICD11Output = z.infer<typeof MapICD10ToICD11OutputSchema>; - ICD10ToICD11MapClient class with lookup(), getVersion(), getReleaseDate(), getStats() methods. Uses an in-memory dataset from a bundled JSON file. The lookup() method normalizes ICD-10 codes (accepts dotted and undotted forms) and returns the WHO transition-table entry or null.
export class ICD10ToICD11MapClient { /** Returns the release version (e.g. "2025-01"). */ getVersion(): string { return ds.version; } /** Returns the release date as printed by WHO (e.g. "2025-Jan-24"). */ getReleaseDate(): string { return ds.released; } /** Returns the source URL the dataset was built from. */ getSourceUrl(): string { return ds.source; } /** * Look up an ICD-10 code. Returns the primary ICD-11 mapping plus any * alternatives (where WHO documents more than one ICD-11 candidate). * Returns `null` when the code isn't in the WHO category-level table — * chapters and blocks (e.g. "A00-A09") are NOT included in the bundled * dataset because they aren't used in clinical coding. */ lookup(icd10Code: string): ICD10ToICD11Entry | null { const normalized = normalizeCode(icd10Code); return ds.entries[normalized] ?? null; } /** Total number of ICD-10 categories with an authoritative mapping. */ size(): number { return Object.keys(ds.entries).length; } /** * Aggregate stats over the full bundled table. Used by the * terminology_diff tool to surface the structural diff between ICD-10 * and ICD-11 (1:1 vs splits) without forcing that consumer to walk the * raw dataset. */ getStats(): { total: number; oneToOne: number; split: number; avgAlternativesWhenSplit: number; } { let oneToOne = 0; let split = 0; let totalAltsInSplits = 0; for (const code of Object.keys(ds.entries)) { const entry = ds.entries[code]; if (entry.alternatives.length === 0) { oneToOne += 1; } else { split += 1; totalAltsInSplits += entry.alternatives.length; } } const avg = split > 0 ? Math.round((totalAltsInSplits / split) * 100) / 100 : 0; return { total: Object.keys(ds.entries).length, oneToOne, split, avgAlternativesWhenSplit: avg, }; } } let singleton: ICD10ToICD11MapClient | null = null; export function getICD10ToICD11MapClient(): ICD10ToICD11MapClient { if (!singleton) { singleton = new ICD10ToICD11MapClient(); } return singleton; }