@pipeworx/mcp-medicare-pricing 0.1.2 → 0.1.3

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.
package/README.md CHANGED
@@ -57,8 +57,26 @@ were checked and rejected:
57
57
  - **NCBI GTR** — knows Signatera and Guardant360 but its `cptcode` field is
58
58
  empty for them.
59
59
 
60
- So coverage is limited to ADLTs. A test outside the list gets
61
- `found: false, reason: not_on_adlt_list` and a pointer to `medicare_lab_rate`.
60
+ That made coverage ADLT-only, and fleet #2458 measured the cost: Oncotype DX
61
+ (81519, a Category I MAAA code, not an ADLT) routed here 5/5 and came back
62
+ `found: false`. Resolution now runs through three sources in order:
63
+
64
+ 1. **CMS ADLT list** (`src/adlt.ts`, below).
65
+ 2. **MAAA brand table** (`src/brand-codes.ts`) -- non-ADLT branded tests whose
66
+ proprietary name is tied to a code in CPT Appendix O and which each have a
67
+ brand-named or category MolDX billing article on the CMS MCD (Oncotype DX
68
+ breast/DCIS/colon/prostate, Prosigna, MammaPrint, EndoPredict, Breast
69
+ Cancer Index, Cologuard, Prolaris, Decipher, Afirma, ConfirmMDx, 4Kscore).
70
+ Only brand -> code -> lab FACTS are kept, never AMA descriptor text. Every
71
+ code was checked to carry a CLFS rate on 2026-09-26. To add a row: confirm
72
+ the pair in a public source, confirm `medicare_lab_rate` has a rate, and set
73
+ `coverage_topic` to a phrase from a live MolDX article title.
74
+ 3. **NCBI GTR, live** -- where the performing lab registered a CPT code
75
+ (e.g. Afirma -> 81546, Decipher -> 81542). Labelled lab-reported. Sparse:
76
+ Oncotype DX and Signatera carry no code there, which is why it is last.
77
+
78
+ A test found in none returns `found: false, reason: brand_not_found` with
79
+ `sources_checked` naming all three, and a pointer to `medicare_lab_rate`.
62
80
 
63
81
  **Copy, not proxy.** The list is a two-page PDF with no API, and the gateway
64
82
  has no PDF parser, so the rows are baked into `src/adlt.ts`. The PDF's "Test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-medicare-pricing",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "What does Medicare PAY — physician fee schedule, lab rates, and per-day unit",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -26,7 +26,7 @@
26
26
  "@cloudflare/workers-types": "^4.20260405.1"
27
27
  },
28
28
  "pipeworx": {
29
- "sourceHash": "v1-39abb67f2c97d76656d44948e3ff83744176d3ab644ad6bb0dfb4fe227df10b6",
30
- "sourceCommit": "6182c4cfebddb94950e060b5d2fca18f18ad1aca"
29
+ "sourceHash": "v1-4bc045e1de966c1a9bd8a24cb7841ad9803cdfe842f2b6db807b64562639bc33",
30
+ "sourceCommit": "6fe8fb3e01138dfc4ebe7d5c246503aab9278d06"
31
31
  }
32
32
  }
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/medicare-pricing",
4
4
  "title": "Medicare Pricing",
5
5
  "description": "What does Medicare PAY — physician fee schedule, lab rates, and per-day unit",
6
- "version": "0.1.2",
6
+ "version": "0.1.3",
7
7
  "websiteUrl": "https://pipeworx.io/packs/medicare-pricing",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-medicare-pricing",
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Branded lab tests that are NOT ADLTs but carry their own code (fleet #2458).
3
+ *
4
+ * #2426 resolved brand names only through the CMS ADLT list, so the most-asked
5
+ * branded test of all -- Oncotype DX, a Category I MAAA code (81519) -- came
6
+ * back found:false. Two more sources close the class:
7
+ *
8
+ * 1. THIS TABLE: the Category I MAAA tests whose proprietary name is tied to
9
+ * its code in CPT Appendix O, each also the subject of a brand-named MolDX
10
+ * billing-and-coding article on the CMS Medicare Coverage Database. What is
11
+ * kept is the FACT (brand -> code -> lab), never the AMA descriptor text,
12
+ * under the same rule as adlt.ts. Every code here was checked on
13
+ * 2026-09-26 to carry a rate on the loaded CLFS.
14
+ * 2. NCBI GTR (Genetic Testing Registry), fetched LIVE per request: labs
15
+ * register their tests there and many state the CPT code. US government
16
+ * work, keyless E-utilities. It is lab-reported, so the answer says so.
17
+ *
18
+ * `coverage_topic` is a phrase from the title of the test's MolDX policy (a
19
+ * brand-named billing article where one exists), matched live against the CMS
20
+ * Coverage API title list -- ours, not CMS's, checked 2026-09-26.
21
+ */
22
+
23
+ export interface BrandTest {
24
+ code: string;
25
+ lab: string;
26
+ test_name: string;
27
+ aliases: string[];
28
+ coverage_topic: string | null;
29
+ }
30
+
31
+ export const BRAND_SOURCE = 'CPT Appendix O (MAAA) proprietary-name-to-code pairs, each with a brand-named or category MolDX billing article on the CMS Medicare Coverage Database';
32
+ export const BRAND_DATA_AS_OF = '2026-09-26';
33
+
34
+ export const BRAND_TESTS: BrandTest[] = [
35
+ { code: '81519', lab: 'Genomic Health (Exact Sciences)', test_name: 'Oncotype DX Breast Recurrence Score', aliases: ['Oncotype DX', 'Oncotype DX Breast', 'Oncotype DX Breast Cancer Assay', 'Oncotype'], coverage_topic: 'Oncotype DX Breast Cancer Assay' },
36
+ { code: '0045U', lab: 'Genomic Health (Exact Sciences)', test_name: 'Oncotype DX Breast DCIS Score', aliases: ['Oncotype DX DCIS', 'Oncotype DCIS'], coverage_topic: 'Oncotype DX Breast Cancer for DCIS' },
37
+ { code: '81525', lab: 'Genomic Health (Exact Sciences)', test_name: 'Oncotype DX Colon Recurrence Score', aliases: ['Oncotype DX Colon', 'Oncotype DX Colon Cancer Assay'], coverage_topic: 'Oncotype DX Colon Cancer' },
38
+ { code: '0047U', lab: 'Genomic Health (Exact Sciences)', test_name: 'Oncotype DX Genomic Prostate Score', aliases: ['Oncotype DX Prostate', 'Genomic Prostate Score', 'Oncotype GPS'], coverage_topic: 'Prostate Cancer Genomic Classifier Assay' },
39
+ { code: '81518', lab: 'Biotheranostics (Hologic)', test_name: 'Breast Cancer Index', aliases: ['BCI'], coverage_topic: 'Breast Cancer Index' },
40
+ { code: '81520', lab: 'NanoString Technologies (Veracyte)', test_name: 'Prosigna', aliases: ['Prosigna Breast Cancer Prognostic Gene Signature Assay', 'PAM50'], coverage_topic: 'Prosigna' },
41
+ { code: '81521', lab: 'Agendia', test_name: 'MammaPrint', aliases: [], coverage_topic: 'MammaPrint' },
42
+ { code: '81522', lab: 'Myriad Genetics', test_name: 'EndoPredict', aliases: [], coverage_topic: 'EndoPredict' },
43
+ { code: '81528', lab: 'Exact Sciences', test_name: 'Cologuard', aliases: [], coverage_topic: null },
44
+ { code: '81541', lab: 'Myriad Genetics', test_name: 'Prolaris', aliases: [], coverage_topic: 'Prostate Cancer Genomic Classifier Assay' },
45
+ { code: '81542', lab: 'Veracyte (Decipher Biosciences)', test_name: 'Decipher Prostate', aliases: ['Decipher', 'Decipher Prostate Genomic Classifier'], coverage_topic: 'Prostate Cancer Genomic Classifier Assay' },
46
+ { code: '81546', lab: 'Veracyte', test_name: 'Afirma Genomic Sequencing Classifier', aliases: ['Afirma', 'Afirma GSC'], coverage_topic: 'Molecular Testing for Risk Stratification of Thyroid Nodules' },
47
+ { code: '81551', lab: 'MDxHealth', test_name: 'ConfirmMDx', aliases: ['ConfirmMDx for Prostate Cancer'], coverage_topic: 'Molecular Biomarkers to Risk-Stratify Patients at Increased Risk for Prostate Cancer' },
48
+ { code: '81539', lab: 'OPKO Health (BioReference)', test_name: '4Kscore', aliases: ['4K score', '4Kscore Test'], coverage_topic: 'Molecular Biomarkers to Risk-Stratify Patients at Increased Risk for Prostate Cancer' },
49
+ ];
50
+
51
+ export const norm = (s: string) => s.toLowerCase().replace(/[®™]/g, '').replace(/[^a-z0-9]/g, '');
52
+
53
+ type Named = { code: string; test_name: string; aliases: string[]; lab: string };
54
+
55
+ /**
56
+ * Match free text to rows: by code, then exact name/alias, then containment
57
+ * (either way, longest name wins so "Oncotype DX colon" is colon, not breast),
58
+ * then lab. A name hit beats a lab hit.
59
+ */
60
+ export function matchTests<T extends Named>(rows: T[], query: string): { matched_by: 'code' | 'test_name' | 'lab' | null; tests: T[] } {
61
+ const q = norm(query);
62
+ if (q.length < 3) return { matched_by: null, tests: [] };
63
+ const byCode = rows.filter((t) => norm(t.code) === q);
64
+ if (byCode.length) return { matched_by: 'code', tests: byCode };
65
+ const names = (t: T) => [t.test_name, ...t.aliases].map(norm);
66
+ const exact = rows.filter((t) => names(t).includes(q));
67
+ if (exact.length) return { matched_by: 'test_name', tests: exact };
68
+ const byName = rows.filter((t) => names(t).some((n) => n.length >= 4 && (n.includes(q) || q.includes(n))));
69
+ if (byName.length) {
70
+ const longest = Math.max(...byName.map((t) => Math.max(...names(t).filter((n) => q.includes(n)).map((n) => n.length), 0)));
71
+ const narrowed = longest > 0 ? byName.filter((t) => names(t).some((n) => n.length === longest && q.includes(n))) : byName;
72
+ return { matched_by: 'test_name', tests: narrowed };
73
+ }
74
+ const byLab = rows.filter((t) => q.length >= 4 && norm(t.lab).includes(q));
75
+ if (byLab.length) return { matched_by: 'lab', tests: byLab };
76
+ return { matched_by: null, tests: [] };
77
+ }
78
+
79
+ export interface GtrHit { code: string; test_name: string; lab: string; gtr_accession: string; url: string }
80
+
81
+ /**
82
+ * NCBI GTR, live: tests whose registered name matches the query AND whose lab
83
+ * stated a CPT code. null when NCBI did not answer (distinct from "no hit").
84
+ */
85
+ export async function gtrLookup(query: string, fetcher: typeof fetch): Promise<GtrHit[] | null> {
86
+ const q = norm(query);
87
+ if (q.length < 4) return [];
88
+ const base = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils';
89
+ const tool = '&tool=pipeworx&email=support%40pipeworx.io';
90
+ try {
91
+ const s = await fetcher(`${base}/esearch.fcgi?db=gtr&retmode=json&retmax=40&term=${encodeURIComponent(query)}${tool}`);
92
+ if (!s.ok) return null;
93
+ const ids = ((await s.json()) as { esearchresult?: { idlist?: string[] } }).esearchresult?.idlist ?? [];
94
+ if (!ids.length) return [];
95
+ const r = await fetcher(`${base}/esummary.fcgi?db=gtr&retmode=json&id=${ids.join(',')}${tool}`);
96
+ if (!r.ok) return null;
97
+ const res = ((await r.json()) as { result?: Record<string, any> }).result ?? {};
98
+ const hits: GtrHit[] = [];
99
+ for (const id of ids) {
100
+ const x = res[id];
101
+ if (!x || typeof x.testname !== 'string') continue;
102
+ const n = norm(x.testname);
103
+ if (!(n.includes(q) || (n.length >= 4 && q.includes(n)))) continue;
104
+ const codes = String(x.cptcode ?? '').split(/[^0-9A-Za-z]+/).map((c: string) => c.toUpperCase()).filter((c: string) => /^(\d{5}|\d{4}U)$/.test(c));
105
+ for (const code of codes) {
106
+ hits.push({ code, test_name: x.testname, lab: String(x.offerer ?? ''), gtr_accession: String(x.accession ?? ''), url: `https://www.ncbi.nlm.nih.gov/gtr/tests/${id}/` });
107
+ }
108
+ }
109
+ return hits;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
package/src/index.ts CHANGED
@@ -740,6 +740,7 @@ function collapse(s: string): string {
740
740
  */
741
741
 
742
742
  import { ADLT_DATA_AS_OF, ADLT_SOURCE_URL, SNAPSHOT_LAST_MODIFIED, matchAdlt, type AdltTest } from './adlt.js';
743
+ import { BRAND_DATA_AS_OF, BRAND_SOURCE, BRAND_TESTS, gtrLookup, matchTests, norm as normName } from './brand-codes.js';
743
744
 
744
745
  // Bound every fetch() in this pack to a fixed timeout — an upstream that
745
746
  // degrades without erroring would otherwise hold the Worker in `await fetch()`
@@ -896,7 +897,7 @@ const tools: McpToolExport['tools'] = [
896
897
  {
897
898
  name: 'medicare_lab_test_lookup',
898
899
  description:
899
- 'Resolve a branded molecular or genomic lab test by its commercial name (e.g. Signatera, Guardant360 CDx, FoundationOne CDx, FoundationOne Liquid CDx, Tempus xT CDx, DecisionDx-Melanoma, Envisia, Shield) to its CPT PLA / HCPCS billing code, the lab that runs it, what Medicare pays for it now on the Clinical Laboratory Fee Schedule, and the MolDX local coverage determinations (LCDs) and billing-and-coding articles for its test category. Answers "what does Medicare pay for Signatera", "what is the PLA code for Guardant360", "which MolDX LCD covers this test". Also accepts a lab name (e.g. "Natera") or a code. Covers the tests on the CMS list of Advanced Diagnostic Laboratory Tests (ADLTs), the only public list that ties a test\'s brand name to its code; a test not on it returns not_found with the reason. Sourced from CMS (ADLT list, Clinical Laboratory Fee Schedule, Medicare Coverage Database).',
900
+ 'Resolve a branded molecular or genomic lab test by its commercial name (e.g. Signatera, Guardant360 CDx, FoundationOne CDx, FoundationOne Liquid CDx, Tempus xT CDx, DecisionDx-Melanoma, Envisia, Shield) to its CPT PLA / HCPCS billing code, the lab that runs it, what Medicare pays for it now on the Clinical Laboratory Fee Schedule, and the MolDX local coverage determinations (LCDs) and billing-and-coding articles for its test category. Answers "what does Medicare pay for Signatera", "what is the PLA code for Guardant360", "which MolDX LCD covers this test". Also accepts a lab name (e.g. "Natera") or a code. Also covers non-ADLT branded MAAA tests (Oncotype DX, Prosigna, MammaPrint, EndoPredict, Breast Cancer Index, Cologuard, Prolaris, Decipher, Afirma, ConfirmMDx, 4Kscore) and any test whose lab registered its code in the NCBI Genetic Testing Registry. Resolves in order: the CMS list of Advanced Diagnostic Laboratory Tests (ADLTs), a brand-to-code table of MAAA tests with MolDX billing articles, then NCBI GTR live; a test found in none returns brand_not_found naming every source checked. Sourced from CMS (ADLT list, Clinical Laboratory Fee Schedule, Medicare Coverage Database) and NCBI GTR.',
900
901
  inputSchema: {
901
902
  type: 'object' as const,
902
903
  properties: {
@@ -1136,57 +1137,94 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
1136
1137
  const test = typeof args.test === 'string' ? args.test.trim() : '';
1137
1138
  if (!test) return { found: false, reason: 'no_test', hint: 'Pass test, e.g. "Signatera".' };
1138
1139
  const includeRetired = args.include_retired === true;
1139
- const { matched_by, tests } = matchAdlt(test);
1140
- const [snapshot, coverage] = await Promise.all([adltSnapshotCheck(), tests.some((t) => t.coverage_topic) ? coverageIndex() : Promise.resolve(null)]);
1140
+ // Sources in order (fleet #2458): the CMS ADLT list, then the MAAA brand
1141
+ // table, then NCBI GTR live. The first that resolves answers; a miss
1142
+ // names every source checked.
1143
+ type Row = { code: string; test_name: string; lab: string; coverage_topic: string | null; code_source: string; adlt?: AdltTest; gtr?: { accession: string; url: string } };
1144
+ const sourcesChecked: string[] = ['CMS ADLT list'];
1145
+ let matched_by: string | null = null;
1146
+ let rows: Row[] = [];
1147
+ let sourceLabel = 'CMS list of Advanced Diagnostic Laboratory Tests (ADLTs) under the Medicare CLFS';
1148
+ const adltHit = matchAdlt(test);
1149
+ if (adltHit.tests.length) {
1150
+ matched_by = adltHit.matched_by;
1151
+ rows = adltHit.tests.map((t) => ({ code: t.code, test_name: t.test_name, lab: t.lab, coverage_topic: t.coverage_topic, code_source: 'CMS ADLT list', adlt: t }));
1152
+ } else {
1153
+ sourcesChecked.push('MAAA brand table (CPT Appendix O pairs backed by MolDX billing articles)');
1154
+ const b = matchTests(BRAND_TESTS, test);
1155
+ if (b.tests.length) {
1156
+ matched_by = b.matched_by;
1157
+ sourceLabel = BRAND_SOURCE;
1158
+ rows = b.tests.map((t) => ({ code: t.code, test_name: t.test_name, lab: t.lab, coverage_topic: t.coverage_topic, code_source: 'MAAA brand table' }));
1159
+ } else {
1160
+ sourcesChecked.push('NCBI Genetic Testing Registry (live)');
1161
+ const g = await gtrLookup(test, ((u: string) => pwFetch(u)) as unknown as typeof fetch);
1162
+ if (g === null) sourcesChecked[sourcesChecked.length - 1] += ' — did not answer';
1163
+ else if (g.length) {
1164
+ matched_by = 'test_name';
1165
+ sourceLabel = 'NCBI Genetic Testing Registry (GTR), code as registered by the performing lab';
1166
+ const seen = new Set<string>();
1167
+ rows = g.filter((h) => !seen.has(h.code + h.lab) && seen.add(h.code + h.lab)).slice(0, 10)
1168
+ .map((h) => ({ code: h.code, test_name: h.test_name, lab: h.lab, coverage_topic: null, code_source: 'NCBI GTR (lab-reported)', gtr: { accession: h.gtr_accession, url: h.url } }));
1169
+ }
1170
+ }
1171
+ }
1172
+ const fromAdlt = rows.some((r) => r.adlt);
1173
+ const [snapshot, coverage] = await Promise.all([
1174
+ fromAdlt || !rows.length ? adltSnapshotCheck() : Promise.resolve({}),
1175
+ rows.some((t) => t.coverage_topic) ? coverageIndex() : Promise.resolve(null),
1176
+ ]);
1141
1177
  const provenance = {
1142
- source: 'CMS list of Advanced Diagnostic Laboratory Tests (ADLTs) under the Medicare CLFS; rates from the CMS Clinical Laboratory Fee Schedule; policies from the CMS Medicare Coverage Database',
1143
- source_url: ADLT_SOURCE_URL,
1144
- data_as_of: ADLT_DATA_AS_OF,
1178
+ source: `${sourceLabel}; rates from the CMS Clinical Laboratory Fee Schedule; policies from the CMS Medicare Coverage Database`,
1179
+ source_url: fromAdlt || !rows.length ? ADLT_SOURCE_URL : rows[0].gtr ? 'https://www.ncbi.nlm.nih.gov/gtr/' : 'https://www.cms.gov/medicare-coverage-database/',
1180
+ data_as_of: fromAdlt || !rows.length ? ADLT_DATA_AS_OF : rows[0].gtr ? new Date().toISOString().slice(0, 10) : BRAND_DATA_AS_OF,
1145
1181
  ...snapshot,
1146
1182
  };
1147
- if (!tests.length) {
1183
+ if (!rows.length) {
1148
1184
  return {
1149
1185
  found: false,
1150
- reason: 'not_on_adlt_list',
1186
+ reason: 'brand_not_found',
1151
1187
  test,
1152
- hint: 'This test is not on CMS\'s ADLT list, which is the only public list that maps a lab test\'s brand name to its billing code. Most PLA codes are not ADLTs; the full PLA code list with proprietary names is published by the AMA under copyright. If you have the code (it usually ends in U, e.g. "0340U"), medicare_lab_rate gives its rate; medicare_lcd_search finds coverage policies by topic.',
1188
+ sources_checked: sourcesChecked,
1189
+ hint: `No billing code found for "${test}" in: ${sourcesChecked.join('; ')}. The full PLA code list with proprietary names is published by the AMA under copyright and is not used here. If you have the code (PLA codes end in U, e.g. "0340U"), medicare_lab_rate gives its rate; medicare_lcd_search finds coverage policies by topic.`,
1153
1190
  ...provenance,
1154
1191
  };
1155
1192
  }
1156
- const results = await Promise.all(tests.map(async (t: AdltTest) => {
1193
+ const results = await Promise.all(rows.map(async (t) => {
1157
1194
  const rates = await pg<{ year: number; quarter: string; rate: number }>(cfg,
1158
1195
  `clfs_rates?hcpcs=eq.${t.code}&select=year,quarter,rate&order=year.desc,quarter.desc&limit=1`);
1159
1196
  // "Response to Comments" articles are the comment period's record, not policy.
1160
- const docs = t.coverage_topic && coverage
1161
- ? coverage.filter((d) => d.title.toLowerCase().includes(t.coverage_topic!.toLowerCase()) && !/^response to comments/i.test(d.title))
1197
+ const topic = t.coverage_topic ? normName(t.coverage_topic) : '';
1198
+ const docs = topic && coverage
1199
+ ? coverage.filter((d) => normName(d.title).includes(topic) && !/^response to comments/i.test(d.title))
1162
1200
  : [];
1163
1201
  const active = docs.filter((d) => !d.retired);
1164
1202
  const retired = docs.filter((d) => d.retired);
1203
+ const a = t.adlt;
1165
1204
  return {
1166
1205
  code: t.code,
1167
- ...(t.code_note ? { code_note: t.code_note } : {}),
1206
+ ...(a?.code_note ? { code_note: a.code_note } : {}),
1168
1207
  test_name: t.test_name,
1169
1208
  lab: t.lab,
1209
+ code_source: t.code_source,
1210
+ ...(t.gtr ? { gtr: t.gtr } : {}),
1170
1211
  current_clfs_rate: rates.length
1171
1212
  ? { rate_usd: rates[0].rate, fee_schedule_year: rates[0].year, quarter: rates[0].quarter, note: 'National rate; the CLFS is not adjusted by locality.' }
1172
1213
  : { rate_usd: null, note: `${t.code} has no rate on the loaded Clinical Laboratory Fee Schedule (it may be contractor-priced).` },
1173
- adlt: {
1174
- approval_date: t.adlt_approval_date,
1175
- existing_adlt: t.existing_adlt,
1176
- new_adlt_initial_period: t.new_adlt_initial_period,
1177
- initial_period_payment_usd: t.initial_period_payment_usd,
1178
- },
1214
+ adlt: a
1215
+ ? { approval_date: a.adlt_approval_date, existing_adlt: a.existing_adlt, new_adlt_initial_period: a.new_adlt_initial_period, initial_period_payment_usd: a.initial_period_payment_usd }
1216
+ : { is_adlt: false },
1179
1217
  coverage: t.coverage_topic
1180
1218
  ? {
1181
1219
  policy_topic: t.coverage_topic,
1182
- topic_note: 'Policies whose title matches this test\'s category (our topic mapping, not CMS\'s). Whether this specific test is listed is stated in the billing article\'s code table.',
1220
+ topic_note: 'Policies whose title matches this test or its category (our topic mapping, not CMS\'s). Whether this specific test is listed is stated in the billing article\'s code table.',
1183
1221
  active_documents: active.slice(0, 20),
1184
1222
  active_count: active.length,
1185
1223
  ...(includeRetired ? { retired_documents: retired.slice(0, 20) } : {}),
1186
1224
  retired_count: retired.length,
1187
1225
  ...(coverage === null ? { error: 'CMS Coverage API did not answer; retry, or use medicare_lcd_search with the policy_topic.' } : {}),
1188
1226
  }
1189
- : { policy_topic: null, note: 'No MolDX local policy title matches this test\'s category; it may be covered nationally (NCD) or case by case.' },
1227
+ : { policy_topic: null, note: 'No MolDX local policy title matched to this test; it may be covered nationally (NCD) or case by case — medicare_lcd_search can look.' },
1190
1228
  };
1191
1229
  }));
1192
1230
  return {
@@ -1194,7 +1232,8 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
1194
1232
  query: test,
1195
1233
  matched_by,
1196
1234
  tests: results,
1197
- no_descriptors_note: 'The AMA\'s CPT PLA descriptor text is not returned (AMA copyright); the test name and lab are CMS\'s.',
1235
+ sources_checked: sourcesChecked,
1236
+ no_descriptors_note: 'The AMA\'s CPT descriptor text is not returned (AMA copyright); only the code, test name and lab.',
1198
1237
  ...provenance,
1199
1238
  };
1200
1239
  }
package/src/server.ts CHANGED
@@ -9,7 +9,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
9
9
  import pack from './index.js';
10
10
 
11
11
  const server = new Server(
12
- { name: '@pipeworx/mcp-medicare-pricing', version: '0.1.2' },
12
+ { name: '@pipeworx/mcp-medicare-pricing', version: '0.1.3' },
13
13
  { capabilities: { tools: {} } },
14
14
  );
15
15