@cyanheads/pubmed-mcp-server 2.1.0 → 2.1.1

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +30 -22
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![npm](https://img.shields.io/npm/v/@cyanheads/pubmed-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pubmed-mcp-server) [![Version](https://img.shields.io/badge/Version-2.1.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://modelcontextprotocol.io/specification/2025-11-25)
10
+ [![npm](https://img.shields.io/npm/v/@cyanheads/pubmed-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pubmed-mcp-server) [![Version](https://img.shields.io/badge/Version-2.1.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://modelcontextprotocol.io/specification/2025-11-25)
11
11
 
12
12
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.27.1-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Status](https://img.shields.io/badge/Status-Stable-brightgreen.svg?style=flat-square)](https://github.com/cyanheads/pubmed-mcp-server/issues) [![TypeScript](https://img.shields.io/badge/TypeScript-^5.9.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
13
13
 
package/dist/index.js CHANGED
@@ -135501,7 +135501,7 @@ config(en_default());
135501
135501
  // package.json
135502
135502
  var package_default = {
135503
135503
  name: "@cyanheads/pubmed-mcp-server",
135504
- version: "2.1.0",
135504
+ version: "2.1.1",
135505
135505
  mcpName: "io.github.cyanheads/pubmed-mcp-server",
135506
135506
  description: "MCP server for PubMed/NCBI E-utilities integration. Search articles, fetch metadata, generate citations, explore MeSH terms, and discover related research.",
135507
135507
  main: "dist/index.js",
@@ -139126,8 +139126,8 @@ function extractTextValues(source, prefix = "") {
139126
139126
  const items = Array.isArray(source) ? source : [source];
139127
139127
  const messages = [];
139128
139128
  for (const item of items) {
139129
- if (typeof item === "string") {
139130
- messages.push(`${prefix}${item}`);
139129
+ if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
139130
+ messages.push(`${prefix}${String(item)}`);
139131
139131
  } else if (item && typeof item["#text"] === "string") {
139132
139132
  messages.push(`${prefix}${item["#text"]}`);
139133
139133
  }
@@ -139187,7 +139187,7 @@ class NcbiResponseHandler {
139187
139187
  });
139188
139188
  }
139189
139189
  const parsedXml = this.xmlParser.parse(responseText);
139190
- const hasError = resolvePath(parsedXml, "eLinkResult.ERROR") !== undefined || resolvePath(parsedXml, "eSummaryResult.ERROR") !== undefined || resolvePath(parsedXml, "PubmedArticleSet.ErrorList") !== undefined || resolvePath(parsedXml, "ERROR") !== undefined;
139190
+ const hasError = ERROR_PATHS.some((path) => resolvePath(parsedXml, path) !== undefined);
139191
139191
  if (hasError) {
139192
139192
  const errorMessages = this.extractNcbiErrorMessages(parsedXml);
139193
139193
  logger.error("NCBI API returned an error in XML response.", {
@@ -151008,7 +151008,7 @@ function parsePmcArticle(xmlArticle) {
151008
151008
  const keywords = extractKeywords(articleMeta?.["kwd-group"]);
151009
151009
  const sections = extractBodySections(xmlArticle.body);
151010
151010
  const references = extractReferences(xmlArticle.back);
151011
- const normalizedPmcId = pmcId.startsWith("PMC") ? pmcId : `PMC${pmcId}`;
151011
+ const normalizedPmcId = !pmcId ? "" : pmcId.startsWith("PMC") ? pmcId : `PMC${pmcId}`;
151012
151012
  return {
151013
151013
  pmcId: normalizedPmcId,
151014
151014
  ...pmid && { pmid },
@@ -151531,30 +151531,35 @@ function splitPages(pages) {
151531
151531
  if (!pages)
151532
151532
  return {};
151533
151533
  const parts = pages.split(/[-\u2013\u2014]/).map((p) => p.trim());
151534
- if (parts.length >= 2) {
151535
- const start2 = parts[0];
151536
- const end = parts[1];
151537
- return {
151538
- ...start2 !== undefined && { start: start2 },
151539
- ...end !== undefined && { end }
151540
- };
151541
- }
151542
- const start = parts[0];
151543
- return start !== undefined ? { start } : {};
151534
+ const [start, end] = parts;
151535
+ if (start && end)
151536
+ return { start, end };
151537
+ return start ? { start } : {};
151544
151538
  }
151545
151539
  function escapeBibtex(text) {
151546
- return text.replace(/\\/g, "\\textbackslash{}").replace(/&/g, "\\&").replace(/%/g, "\\%").replace(/\$/g, "\\$").replace(/#/g, "\\#").replace(/_/g, "\\_").replace(/\{/g, "\\{").replace(/\}/g, "\\}").replace(/~/g, "\\textasciitilde{}").replace(/\^/g, "\\textasciicircum{}");
151540
+ return text.replace(/[\\&%$#_{}~^]/g, (ch) => {
151541
+ switch (ch) {
151542
+ case "\\":
151543
+ return "\\textbackslash{}";
151544
+ case "~":
151545
+ return "\\textasciitilde{}";
151546
+ case "^":
151547
+ return "\\textasciicircum{}";
151548
+ default:
151549
+ return `\\${ch}`;
151550
+ }
151551
+ });
151547
151552
  }
151548
151553
  function formatAuthorApa(author) {
151549
151554
  if (author.collectiveName)
151550
151555
  return author.collectiveName;
151551
151556
  const last = author.lastName ?? "";
151552
- const initials = author.initials ?? author.firstName?.split(/[\s-]+/).map((part) => `${part[0]}.`).join(" ");
151553
- if (!last)
151554
- return initials ?? "";
151557
+ const initials = author.initials ?? author.firstName?.split(/[\s-]+/).filter(Boolean).map((part) => `${part[0]}.`).join(" ");
151555
151558
  if (!initials)
151556
151559
  return last;
151557
151560
  const formatted = initials.replace(/[^A-Za-z]/g, "").split("").map((c) => `${c}.`).join(" ");
151561
+ if (!last)
151562
+ return formatted;
151558
151563
  return `${last}, ${formatted}`;
151559
151564
  }
151560
151565
  function formatAuthorsApa(authors) {
@@ -151846,6 +151851,9 @@ function extractJournalInfo(journalXml, articleXml) {
151846
151851
  const issnType = getAttribute(issnElement, "IssnType");
151847
151852
  const issn = issnType === "Electronic" ? undefined : issnValue || undefined;
151848
151853
  const eIssn = issnType === "Electronic" ? issnValue || undefined : undefined;
151854
+ const month = getText(pubDate?.Month);
151855
+ const day = getText(pubDate?.Day);
151856
+ const medlineDate = getText(pubDate?.MedlineDate);
151849
151857
  return {
151850
151858
  title: getText(journalXml.Title),
151851
151859
  isoAbbreviation: getText(journalXml.ISOAbbreviation),
@@ -151856,9 +151864,9 @@ function extractJournalInfo(journalXml, articleXml) {
151856
151864
  pages: getText(articleXml?.Pagination?.MedlinePgn),
151857
151865
  publicationDate: {
151858
151866
  ...year && { year },
151859
- ...getText(pubDate?.Month) && { month: getText(pubDate?.Month) },
151860
- ...getText(pubDate?.Day) && { day: getText(pubDate?.Day) },
151861
- ...getText(pubDate?.MedlineDate) && { medlineDate: getText(pubDate?.MedlineDate) }
151867
+ ...month && { month },
151868
+ ...day && { day },
151869
+ ...medlineDate && { medlineDate }
151862
151870
  }
151863
151871
  };
151864
151872
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/pubmed-mcp-server",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "mcpName": "io.github.cyanheads/pubmed-mcp-server",
5
5
  "description": "MCP server for PubMed/NCBI E-utilities integration. Search articles, fetch metadata, generate citations, explore MeSH terms, and discover related research.",
6
6
  "main": "dist/index.js",