@pharmatools/pubcrawl 2.0.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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +45 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/cache.d.ts +19 -0
  8. package/dist/lib/cache.d.ts.map +1 -0
  9. package/dist/lib/cache.js +52 -0
  10. package/dist/lib/cache.js.map +1 -0
  11. package/dist/lib/dailymed.d.ts +9 -0
  12. package/dist/lib/dailymed.d.ts.map +1 -0
  13. package/dist/lib/dailymed.js +58 -0
  14. package/dist/lib/dailymed.js.map +1 -0
  15. package/dist/lib/emc.d.ts +13 -0
  16. package/dist/lib/emc.d.ts.map +1 -0
  17. package/dist/lib/emc.js +215 -0
  18. package/dist/lib/emc.js.map +1 -0
  19. package/dist/lib/label-mapping.d.ts +8 -0
  20. package/dist/lib/label-mapping.d.ts.map +1 -0
  21. package/dist/lib/label-mapping.js +23 -0
  22. package/dist/lib/label-mapping.js.map +1 -0
  23. package/dist/lib/ncbi.d.ts +37 -0
  24. package/dist/lib/ncbi.d.ts.map +1 -0
  25. package/dist/lib/ncbi.js +175 -0
  26. package/dist/lib/ncbi.js.map +1 -0
  27. package/dist/lib/openfda.d.ts +8 -0
  28. package/dist/lib/openfda.d.ts.map +1 -0
  29. package/dist/lib/openfda.js +83 -0
  30. package/dist/lib/openfda.js.map +1 -0
  31. package/dist/lib/xml-parser.d.ts +23 -0
  32. package/dist/lib/xml-parser.d.ts.map +1 -0
  33. package/dist/lib/xml-parser.js +273 -0
  34. package/dist/lib/xml-parser.js.map +1 -0
  35. package/dist/tools/abstract.d.ts +3 -0
  36. package/dist/tools/abstract.d.ts.map +1 -0
  37. package/dist/tools/abstract.js +107 -0
  38. package/dist/tools/abstract.js.map +1 -0
  39. package/dist/tools/cite.d.ts +3 -0
  40. package/dist/tools/cite.d.ts.map +1 -0
  41. package/dist/tools/cite.js +188 -0
  42. package/dist/tools/cite.js.map +1 -0
  43. package/dist/tools/compare-labels.d.ts +3 -0
  44. package/dist/tools/compare-labels.d.ts.map +1 -0
  45. package/dist/tools/compare-labels.js +126 -0
  46. package/dist/tools/compare-labels.js.map +1 -0
  47. package/dist/tools/fulltext.d.ts +3 -0
  48. package/dist/tools/fulltext.d.ts.map +1 -0
  49. package/dist/tools/fulltext.js +88 -0
  50. package/dist/tools/fulltext.js.map +1 -0
  51. package/dist/tools/related.d.ts +3 -0
  52. package/dist/tools/related.d.ts.map +1 -0
  53. package/dist/tools/related.js +63 -0
  54. package/dist/tools/related.js.map +1 -0
  55. package/dist/tools/search-indication.d.ts +3 -0
  56. package/dist/tools/search-indication.d.ts.map +1 -0
  57. package/dist/tools/search-indication.js +73 -0
  58. package/dist/tools/search-indication.js.map +1 -0
  59. package/dist/tools/search.d.ts +3 -0
  60. package/dist/tools/search.d.ts.map +1 -0
  61. package/dist/tools/search.js +69 -0
  62. package/dist/tools/search.js.map +1 -0
  63. package/dist/tools/smpc.d.ts +3 -0
  64. package/dist/tools/smpc.d.ts.map +1 -0
  65. package/dist/tools/smpc.js +52 -0
  66. package/dist/tools/smpc.js.map +1 -0
  67. package/dist/tools/trending.d.ts +3 -0
  68. package/dist/tools/trending.d.ts.map +1 -0
  69. package/dist/tools/trending.js +106 -0
  70. package/dist/tools/trending.js.map +1 -0
  71. package/dist/tools/uspi.d.ts +3 -0
  72. package/dist/tools/uspi.d.ts.map +1 -0
  73. package/dist/tools/uspi.js +117 -0
  74. package/dist/tools/uspi.js.map +1 -0
  75. package/dist/types.d.ts +93 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +2 -0
  78. package/dist/types.js.map +1 -0
  79. package/package.json +49 -0
  80. package/server.json +29 -0
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ import { efetch } from "../lib/ncbi.js";
3
+ import { parseXml, parseAuthors, parseAbstractSections, parseMeshTerms, parseKeywords, extractText, } from "../lib/xml-parser.js";
4
+ const schema = {
5
+ pmid: z.string().describe("PubMed ID"),
6
+ structured: z.boolean().default(true).describe("Return structured abstract sections"),
7
+ };
8
+ export function registerAbstractTool(server) {
9
+ server.tool("get_abstract", "Get the full structured abstract and metadata for a PubMed article. Returns abstract sections (background, methods, results, conclusions), keywords, MeSH terms, and PMC ID.", schema, async (params) => {
10
+ try {
11
+ const xml = await efetch({ id: params.pmid, rettype: "xml" });
12
+ const parsed = parseXml(xml);
13
+ const articles = parsed.PubmedArticleSet?.PubmedArticle;
14
+ if (!articles || (Array.isArray(articles) && articles.length === 0)) {
15
+ return {
16
+ content: [{ type: "text", text: `No article found for PMID ${params.pmid}` }],
17
+ isError: true,
18
+ };
19
+ }
20
+ const article = Array.isArray(articles) ? articles[0] : articles;
21
+ const medlineCitation = article.MedlineCitation;
22
+ const articleData = medlineCitation?.Article;
23
+ const pubmedData = article.PubmedData;
24
+ if (!articleData) {
25
+ return {
26
+ content: [{ type: "text", text: `No article data found for PMID ${params.pmid}` }],
27
+ isError: true,
28
+ };
29
+ }
30
+ // Extract authors
31
+ const authors = parseAuthors(articleData.AuthorList);
32
+ // Extract journal info
33
+ const journal = articleData.Journal;
34
+ const journalTitle = extractText(journal?.Title);
35
+ const journalIssue = journal?.JournalIssue;
36
+ const volume = journalIssue?.Volume ? String(journalIssue.Volume) : "";
37
+ const issue = journalIssue?.Issue ? String(journalIssue.Issue) : "";
38
+ const year = journalIssue?.PubDate?.Year
39
+ ? String(journalIssue.PubDate.Year)
40
+ : extractText(journalIssue?.PubDate?.MedlineDate).match(/\d{4}/)?.[0] ?? "";
41
+ const pages = articleData.Pagination?.MedlinePgn
42
+ ? String(articleData.Pagination.MedlinePgn)
43
+ : "";
44
+ // Extract abstract
45
+ const abstractSections = parseAbstractSections(articleData.Abstract);
46
+ // If not structured, join all sections
47
+ let finalSections = abstractSections;
48
+ if (!params.structured && abstractSections.length > 0) {
49
+ const fullText = abstractSections.map((s) => s.text).join(" ");
50
+ finalSections = [{ label: "", text: fullText }];
51
+ }
52
+ // Extract DOI
53
+ let doi = "";
54
+ const elocationIds = articleData.ELocationID;
55
+ if (elocationIds) {
56
+ const ids = Array.isArray(elocationIds) ? elocationIds : [elocationIds];
57
+ for (const eid of ids) {
58
+ if (typeof eid === "object" && eid["@_EIdType"] === "doi") {
59
+ doi = extractText(eid);
60
+ break;
61
+ }
62
+ }
63
+ }
64
+ // Extract PMC ID from article IDs
65
+ let pmcId = "";
66
+ const articleIdList = pubmedData?.ArticleIdList?.ArticleId;
67
+ if (articleIdList) {
68
+ const ids = Array.isArray(articleIdList) ? articleIdList : [articleIdList];
69
+ for (const id of ids) {
70
+ if (typeof id === "object" && id["@_IdType"] === "pmc") {
71
+ pmcId = extractText(id);
72
+ break;
73
+ }
74
+ }
75
+ }
76
+ // Extract MeSH terms and keywords
77
+ const meshTerms = parseMeshTerms(medlineCitation?.MeshHeadingList);
78
+ const keywords = parseKeywords(medlineCitation?.KeywordList);
79
+ const result = {
80
+ pmid: params.pmid,
81
+ title: extractText(articleData.ArticleTitle),
82
+ authors,
83
+ journal: journalTitle,
84
+ year,
85
+ doi,
86
+ volume,
87
+ issue,
88
+ pages,
89
+ abstract_sections: finalSections,
90
+ keywords,
91
+ mesh_terms: meshTerms,
92
+ pmc_id: pmcId,
93
+ };
94
+ return {
95
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
96
+ };
97
+ }
98
+ catch (error) {
99
+ const message = error instanceof Error ? error.message : String(error);
100
+ return {
101
+ content: [{ type: "text", text: `Error fetching abstract: ${message}` }],
102
+ isError: true,
103
+ };
104
+ }
105
+ });
106
+ }
107
+ //# sourceMappingURL=abstract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.js","sourceRoot":"","sources":["../../src/tools/abstract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerCiteTool(server: McpServer): void;
3
+ //# sourceMappingURL=cite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cite.d.ts","sourceRoot":"","sources":["../../src/tools/cite.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4IpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmFxD"}
@@ -0,0 +1,188 @@
1
+ import { z } from "zod";
2
+ import { efetch } from "../lib/ncbi.js";
3
+ import { parseXml, parseAuthors, extractText } from "../lib/xml-parser.js";
4
+ const schema = {
5
+ pmid: z.string().describe("PubMed ID"),
6
+ style: z.enum(["apa", "vancouver", "harvard", "bibtex"]).default("apa").describe("Citation style"),
7
+ };
8
+ function formatApa(info) {
9
+ const authorStr = info.authors.length === 0
10
+ ? ""
11
+ : info.authors.length <= 7
12
+ ? info.authors.map((a) => {
13
+ const parts = a.split(" ");
14
+ const last = parts[0];
15
+ const initials = parts.slice(1).map((p) => p[0] + ".").join(" ");
16
+ return `${last}, ${initials}`;
17
+ }).join(", ")
18
+ : info.authors.slice(0, 6).map((a) => {
19
+ const parts = a.split(" ");
20
+ const last = parts[0];
21
+ const initials = parts.slice(1).map((p) => p[0] + ".").join(" ");
22
+ return `${last}, ${initials}`;
23
+ }).join(", ") + ", ... " + (() => {
24
+ const last = info.authors[info.authors.length - 1];
25
+ const parts = last.split(" ");
26
+ const lastName = parts[0];
27
+ const initials = parts.slice(1).map((p) => p[0] + ".").join(" ");
28
+ return `${lastName}, ${initials}`;
29
+ })();
30
+ const yearPart = info.year ? ` (${info.year}).` : ".";
31
+ const titlePart = info.title.endsWith(".") ? ` ${info.title}` : ` ${info.title}.`;
32
+ const journalPart = ` *${info.journal}*`;
33
+ const volPart = info.volume ? `, *${info.volume}*` : "";
34
+ const issuePart = info.issue ? `(${info.issue})` : "";
35
+ const pagesPart = info.pages ? `, ${info.pages}` : "";
36
+ const doiPart = info.doi ? ` https://doi.org/${info.doi}` : "";
37
+ return `${authorStr}${yearPart}${titlePart}${journalPart}${volPart}${issuePart}${pagesPart}.${doiPart}`.trim();
38
+ }
39
+ function formatVancouver(info) {
40
+ const authorStr = info.authors.length === 0
41
+ ? ""
42
+ : info.authors.length <= 6
43
+ ? info.authors.map((a) => {
44
+ const parts = a.split(" ");
45
+ const last = parts[0];
46
+ const initials = parts.slice(1).map((p) => p[0]).join("");
47
+ return `${last} ${initials}`;
48
+ }).join(", ")
49
+ : info.authors.slice(0, 6).map((a) => {
50
+ const parts = a.split(" ");
51
+ const last = parts[0];
52
+ const initials = parts.slice(1).map((p) => p[0]).join("");
53
+ return `${last} ${initials}`;
54
+ }).join(", ") + ", et al";
55
+ const titlePart = info.title.endsWith(".") ? ` ${info.title}` : ` ${info.title}.`;
56
+ const journalPart = ` ${info.journal}.`;
57
+ const yearPart = info.year ? ` ${info.year}` : "";
58
+ const volPart = info.volume ? `;${info.volume}` : "";
59
+ const issuePart = info.issue ? `(${info.issue})` : "";
60
+ const pagesPart = info.pages ? `:${info.pages}` : "";
61
+ const doiPart = info.doi ? ` doi:${info.doi}` : "";
62
+ return `${authorStr}.${titlePart}${journalPart}${yearPart}${volPart}${issuePart}${pagesPart}.${doiPart}`.trim();
63
+ }
64
+ function formatHarvard(info) {
65
+ const authorStr = info.authors.length === 0
66
+ ? ""
67
+ : info.authors.length <= 3
68
+ ? info.authors.map((a) => {
69
+ const parts = a.split(" ");
70
+ const last = parts[0];
71
+ const initials = parts.slice(1).map((p) => p[0] + ".").join("");
72
+ return `${last}, ${initials}`;
73
+ }).join(", ")
74
+ : (() => {
75
+ const first = info.authors[0];
76
+ const parts = first.split(" ");
77
+ const last = parts[0];
78
+ const initials = parts.slice(1).map((p) => p[0] + ".").join("");
79
+ return `${last}, ${initials} et al.`;
80
+ })();
81
+ const yearPart = info.year ? ` ${info.year}.` : ".";
82
+ const titlePart = ` '${info.title}'.`;
83
+ const journalPart = ` *${info.journal}*`;
84
+ const volPart = info.volume ? `, ${info.volume}` : "";
85
+ const issuePart = info.issue ? `(${info.issue})` : "";
86
+ const pagesPart = info.pages ? `, pp. ${info.pages}` : "";
87
+ const doiPart = info.doi ? `. doi:${info.doi}` : "";
88
+ return `${authorStr}${yearPart}${titlePart}${journalPart}${volPart}${issuePart}${pagesPart}${doiPart}`.trim();
89
+ }
90
+ function formatBibtex(info) {
91
+ const key = info.authors.length > 0
92
+ ? info.authors[0].split(" ")[0].toLowerCase() + info.year
93
+ : `pmid${info.pmid}`;
94
+ const authorStr = info.authors.map((a) => {
95
+ const parts = a.split(" ");
96
+ return `${parts[0]}, ${parts.slice(1).join(" ")}`;
97
+ }).join(" and ");
98
+ const lines = [
99
+ `@article{${key},`,
100
+ ` author = {${authorStr}},`,
101
+ ` title = {${info.title}},`,
102
+ ` journal = {${info.journal}},`,
103
+ ` year = {${info.year}},`,
104
+ ];
105
+ if (info.volume)
106
+ lines.push(` volume = {${info.volume}},`);
107
+ if (info.issue)
108
+ lines.push(` number = {${info.issue}},`);
109
+ if (info.pages)
110
+ lines.push(` pages = {${info.pages}},`);
111
+ if (info.doi)
112
+ lines.push(` doi = {${info.doi}},`);
113
+ lines.push(` pmid = {${info.pmid}},`);
114
+ lines.push(`}`);
115
+ return lines.join("\n");
116
+ }
117
+ export function registerCiteTool(server) {
118
+ server.tool("format_citation", "Format a citation for a PubMed article in APA, Vancouver, Harvard, or BibTeX style.", schema, async (params) => {
119
+ try {
120
+ const xml = await efetch({ id: params.pmid, rettype: "xml" });
121
+ const parsed = parseXml(xml);
122
+ const articles = parsed.PubmedArticleSet?.PubmedArticle;
123
+ if (!articles || (Array.isArray(articles) && articles.length === 0)) {
124
+ return {
125
+ content: [{ type: "text", text: `No article found for PMID ${params.pmid}` }],
126
+ isError: true,
127
+ };
128
+ }
129
+ const article = Array.isArray(articles) ? articles[0] : articles;
130
+ const medlineCitation = article.MedlineCitation;
131
+ const articleData = medlineCitation?.Article;
132
+ if (!articleData) {
133
+ return {
134
+ content: [{ type: "text", text: `No article data for PMID ${params.pmid}` }],
135
+ isError: true,
136
+ };
137
+ }
138
+ const authors = parseAuthors(articleData.AuthorList);
139
+ const journal = articleData.Journal;
140
+ const journalIssue = journal?.JournalIssue;
141
+ let doi = "";
142
+ const elocationIds = articleData.ELocationID;
143
+ if (elocationIds) {
144
+ const ids = Array.isArray(elocationIds) ? elocationIds : [elocationIds];
145
+ for (const eid of ids) {
146
+ if (typeof eid === "object" && eid["@_EIdType"] === "doi") {
147
+ doi = extractText(eid);
148
+ break;
149
+ }
150
+ }
151
+ }
152
+ const info = {
153
+ authors,
154
+ title: extractText(articleData.ArticleTitle),
155
+ journal: extractText(journal?.Title) || extractText(journal?.ISOAbbreviation),
156
+ year: journalIssue?.PubDate?.Year
157
+ ? String(journalIssue.PubDate.Year)
158
+ : extractText(journalIssue?.PubDate?.MedlineDate).match(/\d{4}/)?.[0] ?? "",
159
+ volume: journalIssue?.Volume ? String(journalIssue.Volume) : "",
160
+ issue: journalIssue?.Issue ? String(journalIssue.Issue) : "",
161
+ pages: articleData.Pagination?.MedlinePgn ? String(articleData.Pagination.MedlinePgn) : "",
162
+ doi,
163
+ pmid: params.pmid,
164
+ };
165
+ const formatters = {
166
+ apa: formatApa,
167
+ vancouver: formatVancouver,
168
+ harvard: formatHarvard,
169
+ bibtex: formatBibtex,
170
+ };
171
+ const formatted = formatters[params.style](info);
172
+ return {
173
+ content: [{
174
+ type: "text",
175
+ text: JSON.stringify({ pmid: params.pmid, style: params.style, citation: formatted }, null, 2),
176
+ }],
177
+ };
178
+ }
179
+ catch (error) {
180
+ const message = error instanceof Error ? error.message : String(error);
181
+ return {
182
+ content: [{ type: "text", text: `Error formatting citation: ${message}` }],
183
+ isError: true,
184
+ };
185
+ }
186
+ });
187
+ }
188
+ //# sourceMappingURL=cite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cite.js","sourceRoot":"","sources":["../../src/tools/cite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerCompareLabelsTool(server: McpServer): void;
3
+ //# sourceMappingURL=compare-labels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-labels.d.ts","sourceRoot":"","sources":["../../src/tools/compare-labels.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgFpE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwEjE"}
@@ -0,0 +1,126 @@
1
+ import { z } from "zod";
2
+ import { searchDrugLabels, fetchSplXml } from "../lib/dailymed.js";
3
+ import { searchEmc, fetchSmpcHtml, parseSmpcSections } from "../lib/emc.js";
4
+ import { parseXml, parseSplSections } from "../lib/xml-parser.js";
5
+ import { filterSectionMap } from "../lib/label-mapping.js";
6
+ const schema = {
7
+ drug: z.string().describe("Drug name to compare across US and UK labelling"),
8
+ sections: z
9
+ .array(z.string())
10
+ .optional()
11
+ .describe("Specific topics to compare (e.g., ['indications', 'adverse reactions']). Compares all mapped sections if omitted."),
12
+ };
13
+ async function fetchUsSections(drugName, loincCodes) {
14
+ const searchResults = await searchDrugLabels(drugName);
15
+ if (searchResults.length === 0)
16
+ return { sections: new Map(), source: null };
17
+ const drugLower = drugName.toLowerCase();
18
+ const sorted = [...searchResults].sort((a, b) => {
19
+ const aMatch = a.title.toLowerCase().includes(drugLower) ? 1 : 0;
20
+ const bMatch = b.title.toLowerCase().includes(drugLower) ? 1 : 0;
21
+ if (aMatch !== bMatch)
22
+ return bMatch - aMatch;
23
+ return b.published_date.localeCompare(a.published_date);
24
+ });
25
+ const best = sorted[0];
26
+ const xml = await fetchSplXml(best.setid);
27
+ const parsed = parseXml(xml);
28
+ const docComponent = parsed?.document?.component;
29
+ const firstComponent = Array.isArray(docComponent) ? docComponent[0] : docComponent;
30
+ const structuredBody = firstComponent?.structuredBody;
31
+ const rawSections = parseSplSections(structuredBody, loincCodes);
32
+ const sectionMap = new Map();
33
+ for (const s of rawSections) {
34
+ sectionMap.set(s.code, { code: s.code, title: s.title, content: s.content });
35
+ }
36
+ return {
37
+ sections: sectionMap,
38
+ source: `https://dailymed.nlm.nih.gov/dailymed/drugInfo.cfm?setid=${best.setid}`,
39
+ };
40
+ }
41
+ async function fetchUkSections(drugName, ukCodes) {
42
+ const searchResults = await searchEmc(drugName);
43
+ if (searchResults.length === 0)
44
+ return { sections: new Map(), source: null };
45
+ const drugLower = drugName.toLowerCase();
46
+ const sorted = [...searchResults].sort((a, b) => {
47
+ const aMatch = a.name.toLowerCase().includes(drugLower) ? 1 : 0;
48
+ const bMatch = b.name.toLowerCase().includes(drugLower) ? 1 : 0;
49
+ return bMatch - aMatch;
50
+ });
51
+ const best = sorted[0];
52
+ const html = await fetchSmpcHtml(best.product_id);
53
+ const rawSections = parseSmpcSections(html, ukCodes);
54
+ const sectionMap = new Map();
55
+ for (const s of rawSections) {
56
+ sectionMap.set(s.code, { code: s.code, title: s.title, content: s.content });
57
+ }
58
+ return {
59
+ sections: sectionMap,
60
+ source: `https://www.medicines.org.uk/emc/product/${best.product_id}/smpc`,
61
+ };
62
+ }
63
+ export function registerCompareLabelsTool(server) {
64
+ server.tool("compare_labels", "Compare US FDA Prescribing Information vs UK/EU SmPC for a drug side-by-side. Maps equivalent sections (e.g., US Indications ↔ UK 4.1) and returns paired content.", schema, async (params) => {
65
+ try {
66
+ const mappings = filterSectionMap(params.sections);
67
+ if (mappings.length === 0) {
68
+ return {
69
+ content: [{
70
+ type: "text",
71
+ text: JSON.stringify({ error: "No matching section mappings found for the requested topics" }, null, 2),
72
+ }],
73
+ isError: true,
74
+ };
75
+ }
76
+ const loincCodes = mappings.map((m) => m.us_loinc);
77
+ const ukCodes = mappings.map((m) => m.uk_code);
78
+ // Fetch both in parallel — allow partial results
79
+ const [usResult, ukResult] = await Promise.allSettled([
80
+ fetchUsSections(params.drug, loincCodes),
81
+ fetchUkSections(params.drug, ukCodes),
82
+ ]);
83
+ const us = usResult.status === "fulfilled" ? usResult.value : { sections: new Map(), source: null };
84
+ const uk = ukResult.status === "fulfilled" ? ukResult.value : { sections: new Map(), source: null };
85
+ if (us.sections.size === 0 && uk.sections.size === 0) {
86
+ const errors = [];
87
+ if (usResult.status === "rejected")
88
+ errors.push(`US: ${usResult.reason}`);
89
+ if (ukResult.status === "rejected")
90
+ errors.push(`UK: ${ukResult.reason}`);
91
+ return {
92
+ content: [{
93
+ type: "text",
94
+ text: JSON.stringify({
95
+ error: `No labelling found for "${params.drug}" in either US or UK databases`,
96
+ details: errors.length > 0 ? errors : undefined,
97
+ }, null, 2),
98
+ }],
99
+ isError: true,
100
+ };
101
+ }
102
+ const comparisons = mappings.map((mapping) => ({
103
+ topic: mapping.topic,
104
+ us_section: us.sections.get(mapping.us_loinc) ?? null,
105
+ uk_section: uk.sections.get(mapping.uk_code) ?? null,
106
+ }));
107
+ const result = {
108
+ drug: params.drug,
109
+ comparisons,
110
+ us_source: us.source,
111
+ uk_source: uk.source,
112
+ };
113
+ return {
114
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
115
+ };
116
+ }
117
+ catch (error) {
118
+ const message = error instanceof Error ? error.message : String(error);
119
+ return {
120
+ content: [{ type: "text", text: `Error comparing labels: ${message}` }],
121
+ isError: true,
122
+ };
123
+ }
124
+ });
125
+ }
126
+ //# sourceMappingURL=compare-labels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-labels.js","sourceRoot":"","sources":["../../src/tools/compare-labels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerFullTextTool(server: McpServer): void;
3
+ //# sourceMappingURL=fulltext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fulltext.d.ts","sourceRoot":"","sources":["../../src/tools/fulltext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiG5D"}
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { efetch, pmidToPmcid } from "../lib/ncbi.js";
3
+ import { parseXml, parseJatsSections, parseFigureCaptions, parseTableCaptions, countReferences, extractText, } from "../lib/xml-parser.js";
4
+ const schema = {
5
+ pmid: z.string().optional().describe("PubMed ID"),
6
+ pmcid: z.string().optional().describe("PubMed Central ID (e.g., PMC1234567)"),
7
+ sections: z.array(z.string()).optional().describe("Filter to specific section titles"),
8
+ };
9
+ export function registerFullTextTool(server) {
10
+ server.tool("get_full_text", "Get the full text of an open-access article from PubMed Central. Returns article sections, figure/table captions, and reference count. Only works for articles available in PMC.", schema, async (params) => {
11
+ try {
12
+ if (!params.pmid && !params.pmcid) {
13
+ return {
14
+ content: [{ type: "text", text: "Either pmid or pmcid is required" }],
15
+ isError: true,
16
+ };
17
+ }
18
+ let pmcid = params.pmcid ?? null;
19
+ const pmid = params.pmid ?? "";
20
+ // Convert PMID to PMCID if needed
21
+ if (!pmcid && pmid) {
22
+ pmcid = await pmidToPmcid(pmid);
23
+ if (!pmcid) {
24
+ return {
25
+ content: [{
26
+ type: "text",
27
+ text: `No PMC full text available for PMID ${pmid}. The article may not be open access.`,
28
+ }],
29
+ isError: true,
30
+ };
31
+ }
32
+ }
33
+ // Strip PMC prefix for the API call
34
+ const pmcIdNum = pmcid.replace(/^PMC/i, "");
35
+ const xml = await efetch({
36
+ db: "pmc",
37
+ id: pmcIdNum,
38
+ rettype: "xml",
39
+ });
40
+ const parsed = parseXml(xml);
41
+ const pmcArticle = parsed["pmc-articleset"]?.article ?? parsed.article;
42
+ if (!pmcArticle) {
43
+ return {
44
+ content: [{ type: "text", text: `Could not parse full text for ${pmcid}` }],
45
+ isError: true,
46
+ };
47
+ }
48
+ const front = pmcArticle.front;
49
+ const body = pmcArticle.body;
50
+ const back = pmcArticle.back;
51
+ // Extract title
52
+ const articleMeta = front?.["article-meta"];
53
+ const title = articleMeta?.["title-group"]?.["article-title"]
54
+ ? extractText(articleMeta["title-group"]["article-title"])
55
+ : "";
56
+ // Parse sections
57
+ let sections = parseJatsSections(body);
58
+ // Filter to requested sections
59
+ if (params.sections && params.sections.length > 0) {
60
+ const requested = params.sections.map((s) => s.toLowerCase());
61
+ sections = sections.filter((s) => requested.some((r) => s.title.toLowerCase().includes(r)));
62
+ }
63
+ const figureCaptions = parseFigureCaptions(body);
64
+ const tableCaptions = parseTableCaptions(body);
65
+ const referenceCount = countReferences(back);
66
+ const result = {
67
+ pmid: pmid,
68
+ pmcid: pmcid,
69
+ title,
70
+ sections,
71
+ figure_captions: figureCaptions,
72
+ table_captions: tableCaptions,
73
+ reference_count: referenceCount,
74
+ };
75
+ return {
76
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
77
+ };
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ return {
82
+ content: [{ type: "text", text: `Error fetching full text: ${message}` }],
83
+ isError: true,
84
+ };
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=fulltext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fulltext.js","sourceRoot":"","sources":["../../src/tools/fulltext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRelatedTool(server: McpServer): void;
3
+ //# sourceMappingURL=related.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"related.d.ts","sourceRoot":"","sources":["../../src/tools/related.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgE3D"}