@cyanheads/medical-codes-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/AGENTS.md +375 -0
  2. package/CLAUDE.md +375 -0
  3. package/Dockerfile +124 -0
  4. package/LICENSE +201 -0
  5. package/README.md +328 -0
  6. package/changelog/0.1.x/0.1.0.md +24 -0
  7. package/changelog/template.md +127 -0
  8. package/data/medical-codes.db +0 -0
  9. package/dist/config/server-config.d.ts +23 -0
  10. package/dist/config/server-config.d.ts.map +1 -0
  11. package/dist/config/server-config.js +51 -0
  12. package/dist/config/server-config.js.map +1 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +54 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/mcp-server/tools/definitions/_render.d.ts +26 -0
  18. package/dist/mcp-server/tools/definitions/_render.d.ts.map +1 -0
  19. package/dist/mcp-server/tools/definitions/_render.js +45 -0
  20. package/dist/mcp-server/tools/definitions/_render.js.map +1 -0
  21. package/dist/mcp-server/tools/definitions/browse-hierarchy.tool.d.ts +51 -0
  22. package/dist/mcp-server/tools/definitions/browse-hierarchy.tool.d.ts.map +1 -0
  23. package/dist/mcp-server/tools/definitions/browse-hierarchy.tool.js +131 -0
  24. package/dist/mcp-server/tools/definitions/browse-hierarchy.tool.js.map +1 -0
  25. package/dist/mcp-server/tools/definitions/check-code.tool.d.ts +42 -0
  26. package/dist/mcp-server/tools/definitions/check-code.tool.d.ts.map +1 -0
  27. package/dist/mcp-server/tools/definitions/check-code.tool.js +91 -0
  28. package/dist/mcp-server/tools/definitions/check-code.tool.js.map +1 -0
  29. package/dist/mcp-server/tools/definitions/get-code.tool.d.ts +52 -0
  30. package/dist/mcp-server/tools/definitions/get-code.tool.d.ts.map +1 -0
  31. package/dist/mcp-server/tools/definitions/get-code.tool.js +165 -0
  32. package/dist/mcp-server/tools/definitions/get-code.tool.js.map +1 -0
  33. package/dist/mcp-server/tools/definitions/list-systems.tool.d.ts +21 -0
  34. package/dist/mcp-server/tools/definitions/list-systems.tool.d.ts.map +1 -0
  35. package/dist/mcp-server/tools/definitions/list-systems.tool.js +81 -0
  36. package/dist/mcp-server/tools/definitions/list-systems.tool.js.map +1 -0
  37. package/dist/mcp-server/tools/definitions/map-codes.tool.d.ts +55 -0
  38. package/dist/mcp-server/tools/definitions/map-codes.tool.d.ts.map +1 -0
  39. package/dist/mcp-server/tools/definitions/map-codes.tool.js +132 -0
  40. package/dist/mcp-server/tools/definitions/map-codes.tool.js.map +1 -0
  41. package/dist/mcp-server/tools/definitions/search-codes.tool.d.ts +48 -0
  42. package/dist/mcp-server/tools/definitions/search-codes.tool.d.ts.map +1 -0
  43. package/dist/mcp-server/tools/definitions/search-codes.tool.js +133 -0
  44. package/dist/mcp-server/tools/definitions/search-codes.tool.js.map +1 -0
  45. package/dist/services/code-index/code-index-service.d.ts +185 -0
  46. package/dist/services/code-index/code-index-service.d.ts.map +1 -0
  47. package/dist/services/code-index/code-index-service.js +530 -0
  48. package/dist/services/code-index/code-index-service.js.map +1 -0
  49. package/dist/services/code-index/detect.d.ts +23 -0
  50. package/dist/services/code-index/detect.d.ts.map +1 -0
  51. package/dist/services/code-index/detect.js +58 -0
  52. package/dist/services/code-index/detect.js.map +1 -0
  53. package/dist/services/code-index/schema.d.ts +55 -0
  54. package/dist/services/code-index/schema.d.ts.map +1 -0
  55. package/dist/services/code-index/schema.js +129 -0
  56. package/dist/services/code-index/schema.js.map +1 -0
  57. package/dist/services/code-index/types.d.ts +71 -0
  58. package/dist/services/code-index/types.d.ts.map +1 -0
  59. package/dist/services/code-index/types.js +24 -0
  60. package/dist/services/code-index/types.js.map +1 -0
  61. package/package.json +92 -0
  62. package/server.json +125 -0
@@ -0,0 +1,127 @@
1
+ ---
2
+ # FORMAT REFERENCE — do not edit. Copy this file to
3
+ # `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.8.x/0.8.6.md`)
4
+ # to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
5
+ # with a concrete date.
6
+
7
+ # Required. One-line GitHub Release-style headline. 350 character cap.
8
+ # Default short and scannable. Don't pad, don't stitch unrelated changes with
9
+ # semicolons — pick the headline. Quotes required: unquoted YAML treats `: `
10
+ # inside the value as a key separator and fails GitHub's strict parser.
11
+ summary: ""
12
+
13
+ # Set `true` when consumers must change code to upgrade: API removals,
14
+ # signature changes, config renames, behavior changes that break existing
15
+ # usage. Flagged as `Breaking` in the rollup.
16
+ breaking: false
17
+
18
+ # Set `true` if this release contains any security fix. Pairs with the
19
+ # `## Security` section below. Flagged as `Security` in the rollup so
20
+ # users can triage upgrade urgency at a glance.
21
+ security: false
22
+
23
+ # Optional free-form notes for maintenance agents processing this release.
24
+ # Not rendered in CHANGELOG — consumed by agents running `maintenance` on
25
+ # downstream servers. Use for adoption instructions that don't fit the
26
+ # human-facing sections: new files to create, fields to populate, one-time
27
+ # migration steps. Omit the field entirely when there's nothing to say.
28
+ # agent-notes: |
29
+ # <instructions for downstream maintenance agents>
30
+ ---
31
+
32
+ # <version> — YYYY-MM-DD
33
+
34
+ <!--
35
+ AUTHORING GUIDE — applies to the new per-version file you create from this
36
+ template.
37
+
38
+ Audience: someone scanning release notes to decide what affects them. Lead
39
+ each bullet with the symbol or concept name in **bold** so they can skip
40
+ what's irrelevant and zoom in on what's not.
41
+
42
+ Tone: terse, fact-dense, not verbose. Default to one sentence per bullet —
43
+ name the symbol, state what changed, stop. Use a second sentence only when
44
+ it carries weight. If a bullet feels long, it is.
45
+
46
+ Cut: mechanism walkthroughs (those belong in JSDoc, CLAUDE.md/AGENTS.md, or the
47
+ relevant skill), ceremonial framings ("This release introduces…",
48
+ backwards-compat paragraphs), file-by-file test enumerations, internal
49
+ implementation notes. Prefer code/symbol names over English re-explanations.
50
+
51
+ Narrative intro: skip by default. Add one short sentence only when the
52
+ release theme genuinely needs framing the bullets can't carry.
53
+
54
+ Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
55
+ Fixed, Security. Include only sections with entries; delete the rest
56
+ (including the commented-out scaffolding below). Don't ship empty headers.
57
+
58
+ Include: every distinct fact a reader needs to adopt or audit the release —
59
+ new exports, signatures, lint rule IDs, env vars, breaking changes, version
60
+ bumps on shipped skills. Nothing more.
61
+
62
+ Links: link issues, PRs, docs, or skills where they help a reader jump to
63
+ context. Once per item per entry — don't re-link the same issue in summary,
64
+ narrative, and bullet. Skip links for inline symbol names; code spans speak
65
+ for themselves.
66
+
67
+ Issue/PR URLs: use full URLs. GitHub's bare `#NN` auto-link only resolves
68
+ inside its own UI, not in npm reads or local editors.
69
+
70
+ [#38](https://github.com/cyanheads/mcp-ts-core/issues/38) ← issue
71
+ [#42](https://github.com/cyanheads/mcp-ts-core/pull/42) ← PR
72
+
73
+ Verify numbers exist before linking (`gh issue view NN`, `gh pr view NN`).
74
+ Never speculate on a future number — `#42` for an upcoming PR silently
75
+ resolves to whatever real item already owns 42, and timeline previews pull
76
+ in that unrelated item's metadata.
77
+
78
+ TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
79
+ via `gh release create --notes-from-tag`. The tag is a derivative of this
80
+ changelog entry — a condensed, scannable version, not a copy. Format:
81
+
82
+ <theme — omit version number, GitHub prepends it>
83
+ ← blank line
84
+ <1-2 sentence context: what this release does>
85
+ ← blank line
86
+ Dependency bumps: ← section header
87
+ ← blank line
88
+ - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
89
+ ← blank line
90
+ Changed: ← only sections with entries
91
+ ← blank line
92
+ - `format()` output includes `query` in text mode
93
+ ← blank line
94
+ Added:
95
+ ← blank line
96
+ - `manifest.json` scaffolded for MCPB bundle support
97
+ - Install badges (Claude Desktop, Cursor, VS Code)
98
+ ← blank line
99
+ <N> tests pass; `bun run devcheck` clean. ← footer
100
+
101
+ Never a flat comma-separated string. Always structured markdown with
102
+ sections. The tag must scan well as a rendered GitHub Release page.
103
+ -->
104
+
105
+ ## Added
106
+
107
+ -
108
+
109
+ ## Changed
110
+
111
+ -
112
+
113
+ <!-- ## Deprecated
114
+
115
+ - -->
116
+
117
+ <!-- ## Removed
118
+
119
+ - -->
120
+
121
+ ## Fixed
122
+
123
+ -
124
+
125
+ <!-- ## Security
126
+
127
+ - -->
Binary file
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview Server-specific configuration for medical-codes-mcp-server.
3
+ * Lazy-parsed from environment variables. Framework config (transport, logging,
4
+ * auth, storage) is owned by @cyanheads/mcp-ts-core and parsed separately.
5
+ *
6
+ * The server is offline and keyless — it reads a bundled SQLite + FTS5 database
7
+ * built at package-build time. The only runtime knobs are the DB path override
8
+ * and the result cap.
9
+ * @module config/server-config
10
+ */
11
+ import { z } from '@cyanheads/mcp-ts-core';
12
+ declare const ServerConfigSchema: z.ZodObject<{
13
+ dbPath: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
14
+ maxResults: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
15
+ }, z.core.$strip>;
16
+ export type ServerConfig = z.infer<typeof ServerConfigSchema>;
17
+ /**
18
+ * Lazily parse and cache the server config. Maps schema paths to env var names
19
+ * so a validation error names the variable (`MEDCODE_MAX_RESULTS`) not the path.
20
+ */
21
+ export declare function getServerConfig(): ServerConfig;
22
+ export {};
23
+ //# sourceMappingURL=server-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAgB3C,QAAA,MAAM,kBAAkB;;;iBAatB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;GAGG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAM9C"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @fileoverview Server-specific configuration for medical-codes-mcp-server.
3
+ * Lazy-parsed from environment variables. Framework config (transport, logging,
4
+ * auth, storage) is owned by @cyanheads/mcp-ts-core and parsed separately.
5
+ *
6
+ * The server is offline and keyless — it reads a bundled SQLite + FTS5 database
7
+ * built at package-build time. The only runtime knobs are the DB path override
8
+ * and the result cap.
9
+ * @module config/server-config
10
+ */
11
+ import { z } from '@cyanheads/mcp-ts-core';
12
+ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
13
+ /**
14
+ * Treats an unset env var (`undefined`), a set-but-empty env var (`""`), and an
15
+ * unsubstituted MCPB placeholder (`${user_config.X}`) identically as absent —
16
+ * so an empty `MEDCODE_DB_PATH=` falls back to the bundled default rather than
17
+ * resolving to an empty path.
18
+ */
19
+ const PLACEHOLDER_PATTERN = /^\$\{[^}]+\}$/;
20
+ const emptyAsUndefined = (v) => {
21
+ if (v === '')
22
+ return;
23
+ if (typeof v === 'string' && PLACEHOLDER_PATTERN.test(v))
24
+ return;
25
+ return v;
26
+ };
27
+ const ServerConfigSchema = z.object({
28
+ dbPath: z
29
+ .preprocess(emptyAsUndefined, z.string().optional())
30
+ .describe('Absolute path override for the bundled SQLite database. Defaults to the packaged data/medical-codes.db resolved relative to the build output.'),
31
+ maxResults: z.coerce
32
+ .number()
33
+ .int()
34
+ .min(1)
35
+ .max(200)
36
+ .default(50)
37
+ .describe('Cap on rows returned by search and browse tools (default 50, hard ceiling 200).'),
38
+ });
39
+ let _config;
40
+ /**
41
+ * Lazily parse and cache the server config. Maps schema paths to env var names
42
+ * so a validation error names the variable (`MEDCODE_MAX_RESULTS`) not the path.
43
+ */
44
+ export function getServerConfig() {
45
+ _config ??= parseEnvConfig(ServerConfigSchema, {
46
+ dbPath: 'MEDCODE_DB_PATH',
47
+ maxResults: 'MEDCODE_MAX_RESULTS',
48
+ });
49
+ return _config;
50
+ }
51
+ //# sourceMappingURL=server-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAC5C,MAAM,gBAAgB,GAAG,CAAC,CAAU,EAAE,EAAE;IACtC,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO;IACrB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO;IACjE,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC;SACN,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;SACnD,QAAQ,CACP,+IAA+I,CAChJ;IACH,UAAU,EAAE,CAAC,CAAC,MAAM;SACjB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,iFAAiF,CAAC;CAC/F,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,MAAM,EAAE,iBAAiB;QACzB,UAAU,EAAE,qBAAqB;KAClC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @fileoverview medical-codes-mcp-server MCP server entry point. Registers the
4
+ * six medcode_* tools and opens the bundled SQLite + FTS5 code index read-only
5
+ * in setup(). Offline, keyless, single-tenant — no runtime network I/O.
6
+ * @module index
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @fileoverview medical-codes-mcp-server MCP server entry point. Registers the
4
+ * six medcode_* tools and opens the bundled SQLite + FTS5 code index read-only
5
+ * in setup(). Offline, keyless, single-tenant — no runtime network I/O.
6
+ * @module index
7
+ */
8
+ import { createApp } from '@cyanheads/mcp-ts-core';
9
+ import { browseHierarchyTool } from './mcp-server/tools/definitions/browse-hierarchy.tool.js';
10
+ import { checkCodeTool } from './mcp-server/tools/definitions/check-code.tool.js';
11
+ import { getCodeTool } from './mcp-server/tools/definitions/get-code.tool.js';
12
+ import { listSystemsTool } from './mcp-server/tools/definitions/list-systems.tool.js';
13
+ import { mapCodesTool } from './mcp-server/tools/definitions/map-codes.tool.js';
14
+ import { searchCodesTool } from './mcp-server/tools/definitions/search-codes.tool.js';
15
+ import { initCodeIndexService } from './services/code-index/code-index-service.js';
16
+ await createApp({
17
+ name: 'medical-codes-mcp-server',
18
+ title: 'medical-codes-mcp-server',
19
+ tools: [
20
+ getCodeTool,
21
+ searchCodesTool,
22
+ checkCodeTool,
23
+ mapCodesTool,
24
+ browseHierarchyTool,
25
+ listSystemsTool,
26
+ ],
27
+ instructions: 'Offline US healthcare code lookup and crosswalk over a bundled SQLite index — keyless, no rate limit, deterministic. Bundled systems: ICD-10-CM (diagnoses), ICD-10-PCS (inpatient procedures), HCPCS Level II (supplies/drugs/services); RxNorm (drug crosswalks) lands in a later release. Decode a code with medcode_get_code (the 80% entry point; accepts a batch and auto-detects the system per code). Go description → code with medcode_search_codes. Validate billability with medcode_check_code — a non-billable or terminated code is a successful result with a whyNot, not an error. Walk the hierarchy with medcode_browse_hierarchy (prefix for ICD-10-CM/HCPCS, axis-based for ICD-10-PCS). Crosswalk parents/children with medcode_map_codes. Confirm which release is active with medcode_list_systems. ICD-10-CM/PCS are the US clinical modifications, not the ICD-10/ICD-11 base.',
28
+ landing: {
29
+ requireAuth: false,
30
+ tagline: 'Offline US healthcare code lookup and crosswalk — ICD-10-CM, ICD-10-PCS, and HCPCS Level II, keyless and deterministic.',
31
+ repoRoot: 'https://github.com/cyanheads/medical-codes-mcp-server',
32
+ links: [
33
+ {
34
+ label: 'ICD-10-CM (CDC/NCHS)',
35
+ href: 'https://www.cdc.gov/nchs/icd/icd-10-cm/index.html',
36
+ external: true,
37
+ },
38
+ {
39
+ label: 'ICD-10-PCS & HCPCS (CMS)',
40
+ href: 'https://www.cms.gov/medicare/coding-billing/icd-10-codes',
41
+ external: true,
42
+ },
43
+ {
44
+ label: 'RxNorm (NLM)',
45
+ href: 'https://www.nlm.nih.gov/research/umls/rxnorm/',
46
+ external: true,
47
+ },
48
+ ],
49
+ },
50
+ async setup() {
51
+ await initCodeIndexService();
52
+ },
53
+ });
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yDAAyD,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,MAAM,mDAAmD,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,kDAAkD,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AAEnF,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,0BAA0B;IACjC,KAAK,EAAE;QACL,WAAW;QACX,eAAe;QACf,aAAa;QACb,YAAY;QACZ,mBAAmB;QACnB,eAAe;KAChB;IACD,YAAY,EACV,02BAA02B;IAC52B,OAAO,EAAE;QACP,WAAW,EAAE,KAAK;QAClB,OAAO,EACL,yHAAyH;QAC3H,QAAQ,EAAE,uDAAuD;QACjE,KAAK,EAAE;YACL;gBACE,KAAK,EAAE,sBAAsB;gBAC7B,IAAI,EAAE,mDAAmD;gBACzD,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,KAAK,EAAE,0BAA0B;gBACjC,IAAI,EAAE,0DAA0D;gBAChE,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,+CAA+C;gBACrD,QAAQ,EAAE,IAAI;aACf;SACF;KACF;IACD,KAAK,CAAC,KAAK;QACT,MAAM,oBAAoB,EAAE,CAAC;IAC/B,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Shared markdown rendering for a decoded code. Centralizes the
3
+ * one place that must touch every field of the decoded-code shape so format()
4
+ * parity holds identically across medcode_get_code, medcode_search_codes, and
5
+ * medcode_browse_hierarchy (the linter walks each field; rendering them in one
6
+ * helper keeps the three tools in sync).
7
+ * @module mcp-server/tools/definitions/_render
8
+ */
9
+ /** The minimal decoded-code shape every render helper consumes. */
10
+ export interface RenderableCode {
11
+ billable: boolean;
12
+ chapter: string | null;
13
+ code: string;
14
+ description: string | null;
15
+ header: boolean;
16
+ shortDescription: string | null;
17
+ system: string;
18
+ }
19
+ /**
20
+ * Render a decoded code as a single bullet line touching every field:
21
+ * code, system, billable, header, chapter, description, shortDescription.
22
+ */
23
+ export declare function renderCodeLine(c: RenderableCode): string;
24
+ /** Render a decoded code as a heading block touching every field. */
25
+ export declare function renderCodeBlock(c: RenderableCode): string[];
26
+ //# sourceMappingURL=_render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_render.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAQxD;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,EAAE,CAS3D"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @fileoverview Shared markdown rendering for a decoded code. Centralizes the
3
+ * one place that must touch every field of the decoded-code shape so format()
4
+ * parity holds identically across medcode_get_code, medcode_search_codes, and
5
+ * medcode_browse_hierarchy (the linter walks each field; rendering them in one
6
+ * helper keeps the three tools in sync).
7
+ * @module mcp-server/tools/definitions/_render
8
+ */
9
+ import { SYSTEM_LABELS } from '../../../services/code-index/types.js';
10
+ /** Human label for a system id, falling back to the raw id. */
11
+ function label(system) {
12
+ return SYSTEM_LABELS[system] ?? system;
13
+ }
14
+ /**
15
+ * Billability phrase referencing both fields by their key names. The key names
16
+ * ("billable", "header") must appear literally so the format-parity linter — which
17
+ * checks for the key name of permissive boolean fields — sees them rendered.
18
+ */
19
+ function flags(c) {
20
+ return `billable: ${c.billable ? 'yes' : 'no'}, header: ${c.header ? 'yes' : 'no'}`;
21
+ }
22
+ /**
23
+ * Render a decoded code as a single bullet line touching every field:
24
+ * code, system, billable, header, chapter, description, shortDescription.
25
+ */
26
+ export function renderCodeLine(c) {
27
+ const desc = c.description ?? c.shortDescription ?? '(no description)';
28
+ const short = c.shortDescription && c.shortDescription !== c.description
29
+ ? ` _(short: ${c.shortDescription})_`
30
+ : '';
31
+ const chapter = c.chapter ? ` · chapter ${c.chapter}` : '';
32
+ return `- **${c.code}** (${label(c.system)}; ${flags(c)}${chapter}): ${desc}${short}`;
33
+ }
34
+ /** Render a decoded code as a heading block touching every field. */
35
+ export function renderCodeBlock(c) {
36
+ const lines = [
37
+ `## ${c.code} — ${label(c.system)}`,
38
+ `**${flags(c)}**${c.chapter ? ` · chapter ${c.chapter}` : ''}`,
39
+ ];
40
+ lines.push(c.description ?? c.shortDescription ?? '(no description)');
41
+ if (c.shortDescription && c.shortDescription !== c.description)
42
+ lines.push(`_Short:_ ${c.shortDescription}`);
43
+ return lines;
44
+ }
45
+ //# sourceMappingURL=_render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_render.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/_render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAa/D,+DAA+D;AAC/D,SAAS,KAAK,CAAC,MAAc;IAC3B,OAAO,aAAa,CAAC,MAAoC,CAAC,IAAI,MAAM,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,SAAS,KAAK,CAAC,CAAiB;IAC9B,OAAO,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACtF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAiB;IAC9C,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,gBAAgB,IAAI,kBAAkB,CAAC;IACvE,MAAM,KAAK,GACT,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,gBAAgB,KAAK,CAAC,CAAC,WAAW;QACxD,CAAC,CAAC,aAAa,CAAC,CAAC,gBAAgB,IAAI;QACrC,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC;AACxF,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,CAAiB;IAC/C,MAAM,KAAK,GAAG;QACZ,MAAM,CAAC,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE;QACnC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;KAC/D,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,gBAAgB,IAAI,kBAAkB,CAAC,CAAC;IACtE,IAAI,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,gBAAgB,KAAK,CAAC,CAAC,WAAW;QAC5D,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @fileoverview medcode_browse_hierarchy — walk a code system's hierarchy
3
+ * without a search term. Returns the children of a node, or the top-level
4
+ * entries when no node is given. ICD-10-CM/HCPCS browse the prefix hierarchy
5
+ * (chapter → category → code); ICD-10-PCS browses its axis structure (each of
6
+ * the 7 characters is an independent axis), returning valid next-position axis
7
+ * values rather than prefix children.
8
+ * @module mcp-server/tools/definitions/browse-hierarchy.tool
9
+ */
10
+ import { z } from '@cyanheads/mcp-ts-core';
11
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
12
+ export declare const browseHierarchyTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
13
+ system: z.ZodEnum<{
14
+ ICD10CM: "ICD10CM";
15
+ ICD10PCS: "ICD10PCS";
16
+ HCPCS: "HCPCS";
17
+ RXNORM: "RXNORM";
18
+ }>;
19
+ node: z.ZodOptional<z.ZodString>;
20
+ limit: z.ZodOptional<z.ZodNumber>;
21
+ }, z.core.$strip>, z.ZodObject<{
22
+ kind: z.ZodEnum<{
23
+ codes: "codes";
24
+ axes: "axes";
25
+ }>;
26
+ codes: z.ZodArray<z.ZodObject<{
27
+ system: z.ZodString;
28
+ code: z.ZodString;
29
+ description: z.ZodNullable<z.ZodString>;
30
+ shortDescription: z.ZodNullable<z.ZodString>;
31
+ billable: z.ZodBoolean;
32
+ header: z.ZodBoolean;
33
+ chapter: z.ZodNullable<z.ZodString>;
34
+ }, z.core.$strip>>;
35
+ axes: z.ZodArray<z.ZodObject<{
36
+ position: z.ZodNumber;
37
+ value: z.ZodString;
38
+ meaning: z.ZodString;
39
+ }, z.core.$strip>>;
40
+ }, z.core.$strip>, readonly [{
41
+ readonly reason: "unknown_node";
42
+ readonly code: JsonRpcErrorCode.NotFound;
43
+ readonly when: "The node does not exist in the system.";
44
+ readonly recovery: "Omit `node` to list top-level entries, or verify the node code.";
45
+ }], {
46
+ readonly truncated: z.ZodBoolean;
47
+ readonly shown: z.ZodNumber;
48
+ readonly cap: z.ZodNumber;
49
+ readonly notice: z.ZodOptional<z.ZodString>;
50
+ }>;
51
+ //# sourceMappingURL=browse-hierarchy.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browse-hierarchy.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-hierarchy.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA6BjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwH9B,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @fileoverview medcode_browse_hierarchy — walk a code system's hierarchy
3
+ * without a search term. Returns the children of a node, or the top-level
4
+ * entries when no node is given. ICD-10-CM/HCPCS browse the prefix hierarchy
5
+ * (chapter → category → code); ICD-10-PCS browses its axis structure (each of
6
+ * the 7 characters is an independent axis), returning valid next-position axis
7
+ * values rather than prefix children.
8
+ * @module mcp-server/tools/definitions/browse-hierarchy.tool
9
+ */
10
+ import { tool, z } from '@cyanheads/mcp-ts-core';
11
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
12
+ import { getServerConfig } from '../../../config/server-config.js';
13
+ import { getCodeIndexService } from '../../../services/code-index/code-index-service.js';
14
+ import { SYSTEM_IDS } from '../../../services/code-index/types.js';
15
+ import { renderCodeLine } from './_render.js';
16
+ const SOURCE_URL = 'https://github.com/cyanheads/medical-codes-mcp-server/blob/main/src/mcp-server/tools/definitions/browse-hierarchy.tool.ts';
17
+ const CodeNodeSchema = z
18
+ .object({
19
+ system: z.string().describe('The system the node belongs to.'),
20
+ code: z.string().describe('The child code in display form.'),
21
+ description: z.string().nullable().describe('Official long description, or null.'),
22
+ shortDescription: z.string().nullable().describe('Official short description, or null.'),
23
+ billable: z.boolean().describe('True when the code is a billable leaf.'),
24
+ header: z.boolean().describe('True when the code is a non-billable category/header.'),
25
+ chapter: z.string().nullable().describe('Chapter/range bucket, or null.'),
26
+ })
27
+ .describe('A child code in a prefix hierarchy (ICD-10-CM/HCPCS).');
28
+ const AxisNodeSchema = z
29
+ .object({
30
+ position: z.number().describe('The 1-based character position in the ICD-10-PCS code.'),
31
+ value: z.string().describe('The single-character axis value valid at this position.'),
32
+ meaning: z.string().describe('What this axis value means at this position.'),
33
+ })
34
+ .describe('A valid ICD-10-PCS axis value at a given character position.');
35
+ export const browseHierarchyTool = tool('medcode_browse_hierarchy', {
36
+ title: 'medical-codes-mcp-server',
37
+ description: "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), so browsing returns the valid values for the next character position, not prefix children. Lets an agent orient in an unfamiliar system or enumerate a category's specific codes.",
38
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
39
+ sourceUrl: SOURCE_URL,
40
+ input: z.object({
41
+ system: z.enum(SYSTEM_IDS).describe('The code system to browse.'),
42
+ node: z
43
+ .string()
44
+ .optional()
45
+ .describe('A node to expand. For ICD-10-CM/HCPCS, a code whose children to list. For ICD-10-PCS, a partial code whose next-position axis values to list. Omit for the top level.'),
46
+ limit: z
47
+ .number()
48
+ .int()
49
+ .min(1)
50
+ .max(200)
51
+ .optional()
52
+ .describe('Max entries to return. Defaults to MEDCODE_MAX_RESULTS (50), ceiling 200.'),
53
+ }),
54
+ output: z.object({
55
+ kind: z
56
+ .enum(['codes', 'axes'])
57
+ .describe('"codes" for prefix-hierarchy children (ICD-10-CM/HCPCS); "axes" for ICD-10-PCS axis values.'),
58
+ codes: z
59
+ .array(CodeNodeSchema)
60
+ .describe('Child codes under the requested node or top level. Empty when kind is "axes".'),
61
+ axes: z
62
+ .array(AxisNodeSchema)
63
+ .describe('Valid next-position axis values for a partial PCS code. Empty when kind is "codes".'),
64
+ }),
65
+ enrichment: {
66
+ truncated: z.boolean().describe('True when the returned list was capped at the limit.'),
67
+ shown: z.number().describe('Number of entries returned (codes or axes).'),
68
+ cap: z.number().describe('The limit that was applied.'),
69
+ notice: z
70
+ .string()
71
+ .optional()
72
+ .describe('Guidance when a node has no children/axes — suggests the top level or a valid node.'),
73
+ },
74
+ errors: [
75
+ {
76
+ reason: 'unknown_node',
77
+ code: JsonRpcErrorCode.NotFound,
78
+ when: 'The node does not exist in the system.',
79
+ recovery: 'Omit `node` to list top-level entries, or verify the node code.',
80
+ },
81
+ ],
82
+ handler(input, ctx) {
83
+ const limit = input.limit ?? getServerConfig().maxResults;
84
+ const result = getCodeIndexService().browse(input.system, input.node, limit);
85
+ if (result.kind === 'unknown_node') {
86
+ throw ctx.fail('unknown_node', `Node "${input.node}" does not exist in ${input.system}.`, {
87
+ ...ctx.recoveryFor('unknown_node'),
88
+ });
89
+ }
90
+ if (result.kind === 'axes') {
91
+ ctx.enrich({ truncated: result.axes.length >= limit, shown: result.axes.length, cap: limit });
92
+ if (result.axes.length === 0) {
93
+ ctx.enrich.notice(input.node
94
+ ? `ICD-10-PCS axis values for positions 2–7 are context-dependent (their meaning ` +
95
+ `varies by the section, body system, and operation that precede them), so they ` +
96
+ `are not enumerable from a flat partial code. Omit \`node\` to list the 17 ` +
97
+ `sections, or decode a complete 7-character code with medcode_get_code for its ` +
98
+ `full axis breakdown.`
99
+ : `No ICD-10-PCS sections are bundled in this release.`);
100
+ }
101
+ ctx.log.info('Browsed PCS axes', { node: input.node ?? null, count: result.axes.length });
102
+ return { kind: 'axes', codes: [], axes: result.axes };
103
+ }
104
+ ctx.enrich({ truncated: result.codes.length >= limit, shown: result.codes.length, cap: limit });
105
+ if (result.codes.length === 0) {
106
+ ctx.enrich.notice(`No children under "${input.node ?? '(top level)'}" in ${input.system}. ` +
107
+ 'Omit `node` for the top level, or browse a parent category.');
108
+ }
109
+ ctx.log.info('Browsed hierarchy', { node: input.node ?? null, count: result.codes.length });
110
+ return { kind: 'codes', codes: result.codes, axes: [] };
111
+ },
112
+ // Render both arrays unconditionally — one is always empty at runtime, but the
113
+ // format-parity linter synthesizes a single sample with both populated, so each
114
+ // branch's fields must be reachable in one pass (kind discrimination would hide
115
+ // half of them from the linter).
116
+ format: (result) => {
117
+ const lines = [`## Browse result (${result.kind})`, ''];
118
+ if (result.codes.length > 0 || result.kind === 'codes') {
119
+ lines.push(`### ${result.codes.length} child code(s)`);
120
+ for (const c of result.codes)
121
+ lines.push(renderCodeLine(c));
122
+ }
123
+ if (result.axes.length > 0 || result.kind === 'axes') {
124
+ lines.push('### ICD-10-PCS axis values', '', '| Position | Value | Meaning |', '|---:|:---|:---|');
125
+ for (const a of result.axes)
126
+ lines.push(`| ${a.position} | ${a.value} | ${a.meaning} |`);
127
+ }
128
+ return [{ type: 'text', text: lines.join('\n') }];
129
+ },
130
+ });
131
+ //# sourceMappingURL=browse-hierarchy.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browse-hierarchy.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-hierarchy.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,UAAU,GACd,2HAA2H,CAAC;AAE9H,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC5D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;IAClF,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACxF,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACxE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;IACrF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;CAC1E,CAAC;KACD,QAAQ,CAAC,uDAAuD,CAAC,CAAC;AAErE,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;IACvF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;IACrF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;CAC7E,CAAC;KACD,QAAQ,CAAC,8DAA8D,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC,0BAA0B,EAAE;IAClE,KAAK,EAAE,0BAA0B;IACjC,WAAW,EACT,mqBAAmqB;IACrqB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;IAC/E,SAAS,EAAE,UAAU;IAErB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QACjE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,uKAAuK,CACxK;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2EAA2E,CAAC;KACzF,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;aACvB,QAAQ,CACP,6FAA6F,CAC9F;QACH,KAAK,EAAE,CAAC;aACL,KAAK,CAAC,cAAc,CAAC;aACrB,QAAQ,CAAC,+EAA+E,CAAC;QAC5F,IAAI,EAAE,CAAC;aACJ,KAAK,CAAC,cAAc,CAAC;aACrB,QAAQ,CACP,qFAAqF,CACtF;KACJ,CAAC;IAEF,UAAU,EAAE;QACV,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;QACvF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QACzE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACvD,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,qFAAqF,CACtF;KACJ;IAED,MAAM,EAAE;QACN;YACE,MAAM,EAAE,cAAc;YACtB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,wCAAwC;YAC9C,QAAQ,EAAE,iEAAiE;SAC5E;KACF;IAED,OAAO,CAAC,KAAK,EAAE,GAAG;QAChB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,UAAU,CAAC;QAC1D,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE7E,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACnC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,KAAK,CAAC,IAAI,uBAAuB,KAAK,CAAC,MAAM,GAAG,EAAE;gBACxF,GAAG,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9F,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,MAAM,CAAC,MAAM,CACf,KAAK,CAAC,IAAI;oBACR,CAAC,CAAC,gFAAgF;wBAC9E,gFAAgF;wBAChF,4EAA4E;wBAC5E,gFAAgF;wBAChF,sBAAsB;oBAC1B,CAAC,CAAC,qDAAqD,CAC1D,CAAC;YACJ,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1F,OAAO,EAAE,IAAI,EAAE,MAAe,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACjE,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAChG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,MAAM,CACf,sBAAsB,KAAK,CAAC,IAAI,IAAI,aAAa,QAAQ,KAAK,CAAC,MAAM,IAAI;gBACvE,6DAA6D,CAChE,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5F,OAAO,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACnE,CAAC;IAED,+EAA+E;IAC/E,gFAAgF;IAChF,gFAAgF;IAChF,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,CAAC,qBAAqB,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACvD,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,gBAAgB,CAAC,CAAC;YACvD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,CACR,4BAA4B,EAC5B,EAAE,EACF,gCAAgC,EAChC,kBAAkB,CACnB,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @fileoverview medcode_check_code — validate whether a code exists, is current,
3
+ * and is billable in the active release. Returns a discriminated status with a
4
+ * why-not for non-billable or terminated codes. Validity vs. existence is split:
5
+ * a non-billable or terminated code is a SUCCESS result with a whyNot (the
6
+ * recovery detail a coder needs), not an error. Only a code absent from every
7
+ * detected system is an `unknown_code` failure.
8
+ * @module mcp-server/tools/definitions/check-code.tool
9
+ */
10
+ import { z } from '@cyanheads/mcp-ts-core';
11
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
12
+ export declare const checkCodeTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
13
+ code: z.ZodString;
14
+ system: z.ZodOptional<z.ZodEnum<{
15
+ ICD10CM: "ICD10CM";
16
+ ICD10PCS: "ICD10PCS";
17
+ HCPCS: "HCPCS";
18
+ RXNORM: "RXNORM";
19
+ }>>;
20
+ }, z.core.$strip>, z.ZodObject<{
21
+ system: z.ZodString;
22
+ code: z.ZodString;
23
+ status: z.ZodEnum<{
24
+ valid_billable: "valid_billable";
25
+ valid_not_billable: "valid_not_billable";
26
+ valid_header: "valid_header";
27
+ terminated: "terminated";
28
+ }>;
29
+ billable: z.ZodBoolean;
30
+ whyNot: z.ZodNullable<z.ZodString>;
31
+ }, z.core.$strip>, readonly [{
32
+ readonly reason: "unknown_code";
33
+ readonly code: JsonRpcErrorCode.NotFound;
34
+ readonly when: "The code does not exist in the named or detected system.";
35
+ readonly recovery: "Check the code, or search by description with medcode_search_codes.";
36
+ }, {
37
+ readonly reason: "ambiguous_system";
38
+ readonly code: JsonRpcErrorCode.InvalidParams;
39
+ readonly when: "The code is present in more than one bundled system and no `system` was given.";
40
+ readonly recovery: "Re-call with an explicit `system` to disambiguate.";
41
+ }], undefined>;
42
+ //# sourceMappingURL=check-code.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-code.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/check-code.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyFxB,CAAC"}