@cyanheads/pubmed-mcp-server 2.1.0 → 2.1.2

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 +3 -3
  2. package/dist/index.js +68 -58
  3. package/package.json +2 -2
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.2-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
 
@@ -23,7 +23,7 @@ Seven tools for working with PubMed and NCBI data:
23
23
  |:---|:---|
24
24
  | `pubmed_search` | Search PubMed with full query syntax, field-specific filters, date ranges, pagination, and optional brief summaries |
25
25
  | `pubmed_fetch` | Fetch full article metadata by PMIDs — abstract, authors, journal, MeSH terms, grants |
26
- | `pmc_fetch` | Fetch full-text articles from PubMed Central — body sections, references, and metadata for open-access articles |
26
+ | `pubmed_pmc_fetch` | Fetch full-text articles from PubMed Central — body sections, references, and metadata for open-access articles |
27
27
  | `pubmed_cite` | Generate formatted citations in APA 7th, MLA 9th, BibTeX, or RIS |
28
28
  | `pubmed_related` | Find similar articles, citing articles, or references for a given PMID |
29
29
  | `pubmed_spell` | Spell-check biomedical queries using NCBI's ESpell service |
@@ -56,7 +56,7 @@ Fetch full article metadata by PubMed IDs.
56
56
 
57
57
  ---
58
58
 
59
- ### `pmc_fetch`
59
+ ### `pubmed_pmc_fetch`
60
60
 
61
61
  Fetch full-text articles from PubMed Central (PMC).
62
62
 
package/dist/index.js CHANGED
@@ -15776,7 +15776,7 @@ var require_util = __commonJS((exports) => {
15776
15776
  }
15777
15777
  path = url2.path;
15778
15778
  }
15779
- var isAbsolute = exports.isAbsolute(path);
15779
+ var isAbsolute2 = exports.isAbsolute(path);
15780
15780
  var parts = [];
15781
15781
  var start = 0;
15782
15782
  var i = 0;
@@ -15811,7 +15811,7 @@ var require_util = __commonJS((exports) => {
15811
15811
  }
15812
15812
  path = parts.join("/");
15813
15813
  if (path === "") {
15814
- path = isAbsolute ? "/" : ".";
15814
+ path = isAbsolute2 ? "/" : ".";
15815
15815
  }
15816
15816
  if (url2) {
15817
15817
  url2.path = path;
@@ -15820,7 +15820,7 @@ var require_util = __commonJS((exports) => {
15820
15820
  return path;
15821
15821
  });
15822
15822
  exports.normalize = normalize;
15823
- function join(aRoot, aPath) {
15823
+ function join2(aRoot, aPath) {
15824
15824
  if (aRoot === "") {
15825
15825
  aRoot = ".";
15826
15826
  }
@@ -15852,7 +15852,7 @@ var require_util = __commonJS((exports) => {
15852
15852
  }
15853
15853
  return joined;
15854
15854
  }
15855
- exports.join = join;
15855
+ exports.join = join2;
15856
15856
  exports.isAbsolute = function(aPath) {
15857
15857
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
15858
15858
  };
@@ -16066,7 +16066,7 @@ var require_util = __commonJS((exports) => {
16066
16066
  parsed.path = parsed.path.substring(0, index + 1);
16067
16067
  }
16068
16068
  }
16069
- sourceURL = join(urlGenerate(parsed), sourceURL);
16069
+ sourceURL = join2(urlGenerate(parsed), sourceURL);
16070
16070
  }
16071
16071
  return normalize(sourceURL);
16072
16072
  }
@@ -17440,7 +17440,7 @@ var require_source_map = __commonJS((exports) => {
17440
17440
  // node_modules/postcss/lib/previous-map.js
17441
17441
  var require_previous_map = __commonJS((exports, module) => {
17442
17442
  var { existsSync, readFileSync } = __require("fs");
17443
- var { dirname, join } = __require("path");
17443
+ var { dirname: dirname2, join: join2 } = __require("path");
17444
17444
  var { SourceMapConsumer, SourceMapGenerator } = require_source_map();
17445
17445
  function fromBase64(str) {
17446
17446
  if (Buffer) {
@@ -17462,7 +17462,7 @@ var require_previous_map = __commonJS((exports, module) => {
17462
17462
  this.mapFile = opts.from;
17463
17463
  }
17464
17464
  if (this.mapFile)
17465
- this.root = dirname(this.mapFile);
17465
+ this.root = dirname2(this.mapFile);
17466
17466
  if (text)
17467
17467
  this.text = text;
17468
17468
  }
@@ -17507,7 +17507,7 @@ var require_previous_map = __commonJS((exports, module) => {
17507
17507
  }
17508
17508
  }
17509
17509
  loadFile(path) {
17510
- this.root = dirname(path);
17510
+ this.root = dirname2(path);
17511
17511
  if (existsSync(path)) {
17512
17512
  this.mapFile = path;
17513
17513
  return readFileSync(path, "utf-8").toString().trim();
@@ -17542,7 +17542,7 @@ var require_previous_map = __commonJS((exports, module) => {
17542
17542
  } else if (this.annotation) {
17543
17543
  let map2 = this.annotation;
17544
17544
  if (file2)
17545
- map2 = join(dirname(file2), map2);
17545
+ map2 = join2(dirname2(file2), map2);
17546
17546
  return this.loadFile(map2);
17547
17547
  }
17548
17548
  }
@@ -17562,15 +17562,15 @@ var require_previous_map = __commonJS((exports, module) => {
17562
17562
  // node_modules/postcss/lib/input.js
17563
17563
  var require_input = __commonJS((exports, module) => {
17564
17564
  var { nanoid: nanoid3 } = require_non_secure();
17565
- var { isAbsolute, resolve } = __require("path");
17565
+ var { isAbsolute: isAbsolute2, resolve } = __require("path");
17566
17566
  var { SourceMapConsumer, SourceMapGenerator } = require_source_map();
17567
- var { fileURLToPath, pathToFileURL } = __require("url");
17567
+ var { fileURLToPath: fileURLToPath2, pathToFileURL } = __require("url");
17568
17568
  var CssSyntaxError = require_css_syntax_error();
17569
17569
  var PreviousMap = require_previous_map();
17570
17570
  var terminalHighlight = require_terminal_highlight();
17571
17571
  var lineToIndexCache = Symbol("lineToIndexCache");
17572
17572
  var sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator);
17573
- var pathAvailable = Boolean(resolve && isAbsolute);
17573
+ var pathAvailable = Boolean(resolve && isAbsolute2);
17574
17574
  function getLineToIndex(input) {
17575
17575
  if (input[lineToIndexCache])
17576
17576
  return input[lineToIndexCache];
@@ -17605,7 +17605,7 @@ var require_input = __commonJS((exports, module) => {
17605
17605
  if (opts.document)
17606
17606
  this.document = opts.document.toString();
17607
17607
  if (opts.from) {
17608
- if (!pathAvailable || /^\w+:\/\//.test(opts.from) || isAbsolute(opts.from)) {
17608
+ if (!pathAvailable || /^\w+:\/\//.test(opts.from) || isAbsolute2(opts.from)) {
17609
17609
  this.file = opts.from;
17610
17610
  } else {
17611
17611
  this.file = resolve(opts.from);
@@ -17723,7 +17723,7 @@ var require_input = __commonJS((exports, module) => {
17723
17723
  to = consumer.originalPositionFor({ column: endColumn, line: endLine });
17724
17724
  }
17725
17725
  let fromUrl;
17726
- if (isAbsolute(from.source)) {
17726
+ if (isAbsolute2(from.source)) {
17727
17727
  fromUrl = pathToFileURL(from.source);
17728
17728
  } else {
17729
17729
  fromUrl = new URL(from.source, this.map.consumer().sourceRoot || pathToFileURL(this.map.mapFile));
@@ -17736,8 +17736,8 @@ var require_input = __commonJS((exports, module) => {
17736
17736
  url: fromUrl.toString()
17737
17737
  };
17738
17738
  if (fromUrl.protocol === "file:") {
17739
- if (fileURLToPath) {
17740
- result.file = fileURLToPath(fromUrl);
17739
+ if (fileURLToPath2) {
17740
+ result.file = fileURLToPath2(fromUrl);
17741
17741
  } else {
17742
17742
  throw new Error(`file: protocol is not available in this PostCSS build`);
17743
17743
  }
@@ -17963,12 +17963,12 @@ var require_fromJSON = __commonJS((exports, module) => {
17963
17963
 
17964
17964
  // node_modules/postcss/lib/map-generator.js
17965
17965
  var require_map_generator = __commonJS((exports, module) => {
17966
- var { dirname, relative, resolve, sep } = __require("path");
17966
+ var { dirname: dirname2, relative, resolve, sep } = __require("path");
17967
17967
  var { SourceMapConsumer, SourceMapGenerator } = require_source_map();
17968
17968
  var { pathToFileURL } = __require("url");
17969
17969
  var Input = require_input();
17970
17970
  var sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator);
17971
- var pathAvailable = Boolean(dirname && resolve && relative && sep);
17971
+ var pathAvailable = Boolean(dirname2 && resolve && relative && sep);
17972
17972
 
17973
17973
  class MapGenerator {
17974
17974
  constructor(stringify, root, opts, cssString) {
@@ -18005,7 +18005,7 @@ var require_map_generator = __commonJS((exports, module) => {
18005
18005
  applyPrevMaps() {
18006
18006
  for (let prev of this.previous()) {
18007
18007
  let from = this.toUrl(this.path(prev.file));
18008
- let root = prev.root || dirname(prev.file);
18008
+ let root = prev.root || dirname2(prev.file);
18009
18009
  let map2;
18010
18010
  if (this.mapOpts.sourcesContent === false) {
18011
18011
  map2 = new SourceMapConsumer(prev.text);
@@ -18212,9 +18212,9 @@ var require_map_generator = __commonJS((exports, module) => {
18212
18212
  let cached2 = this.memoizedPaths.get(file2);
18213
18213
  if (cached2)
18214
18214
  return cached2;
18215
- let from = this.opts.to ? dirname(this.opts.to) : ".";
18215
+ let from = this.opts.to ? dirname2(this.opts.to) : ".";
18216
18216
  if (typeof this.mapOpts.annotation === "string") {
18217
- from = dirname(resolve(from, this.mapOpts.annotation));
18217
+ from = dirname2(resolve(from, this.mapOpts.annotation));
18218
18218
  }
18219
18219
  let path = relative(from, file2);
18220
18220
  this.memoizedPaths.set(file2, path);
@@ -40573,7 +40573,7 @@ var require_register = __commonJS((exports) => {
40573
40573
  var require_import_in_the_middle = __commonJS((exports, module) => {
40574
40574
  var path2 = __require("path");
40575
40575
  var moduleDetailsFromPath = require_module_details_from_path();
40576
- var { fileURLToPath } = __require("url");
40576
+ var { fileURLToPath: fileURLToPath2 } = __require("url");
40577
40577
  var { MessageChannel } = __require("worker_threads");
40578
40578
  var { isBuiltin } = __require("module");
40579
40579
  if (!isBuiltin) {
@@ -40661,7 +40661,7 @@ var require_import_in_the_middle = __commonJS((exports, module) => {
40661
40661
  const stackTraceLimit = Error.stackTraceLimit;
40662
40662
  Error.stackTraceLimit = 0;
40663
40663
  try {
40664
- filePath = fileURLToPath(name2);
40664
+ filePath = fileURLToPath2(name2);
40665
40665
  name2 = filePath;
40666
40666
  } catch (e) {}
40667
40667
  Error.stackTraceLimit = stackTraceLimit;
@@ -91725,12 +91725,12 @@ var require_fetch2 = __commonJS((exports, module) => {
91725
91725
  // node_modules/@protobufjs/path/index.js
91726
91726
  var require_path = __commonJS((exports) => {
91727
91727
  var path2 = exports;
91728
- var isAbsolute = path2.isAbsolute = function isAbsolute(path3) {
91728
+ var isAbsolute2 = path2.isAbsolute = function isAbsolute(path3) {
91729
91729
  return /^(?:\/|\w+:)/.test(path3);
91730
91730
  };
91731
91731
  var normalize = path2.normalize = function normalize(path3) {
91732
91732
  path3 = path3.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
91733
- var parts = path3.split("/"), absolute = isAbsolute(path3), prefix = "";
91733
+ var parts = path3.split("/"), absolute = isAbsolute2(path3), prefix = "";
91734
91734
  if (absolute)
91735
91735
  prefix = parts.shift() + "/";
91736
91736
  for (var i2 = 0;i2 < parts.length; ) {
@@ -91751,7 +91751,7 @@ var require_path = __commonJS((exports) => {
91751
91751
  path2.resolve = function resolve(originPath, includePath, alreadyNormalized) {
91752
91752
  if (!alreadyNormalized)
91753
91753
  includePath = normalize(includePath);
91754
- if (isAbsolute(includePath))
91754
+ if (isAbsolute2(includePath))
91755
91755
  return includePath;
91756
91756
  if (!alreadyNormalized)
91757
91757
  originPath = normalize(originPath);
@@ -121965,6 +121965,8 @@ if (shouldShowDeprecationWarning())
121965
121965
 
121966
121966
  // src/config/index.ts
121967
121967
  var import_dotenv = __toESM(require_main4(), 1);
121968
+ import { dirname, isAbsolute, join } from "node:path";
121969
+ import { fileURLToPath } from "node:url";
121968
121970
 
121969
121971
  // node_modules/zod/v4/classic/external.js
121970
121972
  var exports_external = {};
@@ -135501,7 +135503,7 @@ config(en_default());
135501
135503
  // package.json
135502
135504
  var package_default = {
135503
135505
  name: "@cyanheads/pubmed-mcp-server",
135504
- version: "2.1.0",
135506
+ version: "2.1.2",
135505
135507
  mcpName: "io.github.cyanheads/pubmed-mcp-server",
135506
135508
  description: "MCP server for PubMed/NCBI E-utilities integration. Search articles, fetch metadata, generate citations, explore MeSH terms, and discover related research.",
135507
135509
  main: "dist/index.js",
@@ -135579,7 +135581,7 @@ var package_default = {
135579
135581
  rollup: "4.59.0"
135580
135582
  },
135581
135583
  devDependencies: {
135582
- "@cloudflare/workers-types": "^4.20260301.1",
135584
+ "@cloudflare/workers-types": "^4.20260305.1",
135583
135585
  "@biomejs/biome": "2.4.5",
135584
135586
  "@hono/mcp": "^0.2.4",
135585
135587
  "@traversable/registry": "^0.0.49",
@@ -136003,13 +136005,13 @@ var parseConfig = () => {
136003
136005
  ...rawConfig,
136004
136006
  pkg: parsedPkg,
136005
136007
  logsPath: hasFileSystemAccess ? (() => {
136006
- const depth = import.meta.url.includes("/dist/") ? ".." : "../..";
136007
- const p = new URL(depth, import.meta.url).pathname;
136008
- const root = p.endsWith("/") ? p.slice(0, -1) : p;
136008
+ const thisFile = fileURLToPath(import.meta.url);
136009
+ const depth = /[\\/]dist[\\/]/.test(thisFile) ? ".." : "../..";
136010
+ const root = join(dirname(thisFile), depth);
136009
136011
  const logsDir = rawConfig.logsPath ?? "logs";
136010
- if (logsDir.startsWith("/"))
136012
+ if (isAbsolute(logsDir))
136011
136013
  return logsDir;
136012
- return `${root}/${logsDir}`;
136014
+ return join(root, logsDir);
136013
136015
  })() : undefined,
136014
136016
  mcpServerName: env.MCP_SERVER_NAME ?? parsedPkg.name,
136015
136017
  mcpServerVersion: env.MCP_SERVER_VERSION ?? parsedPkg.version,
@@ -139126,8 +139128,8 @@ function extractTextValues(source, prefix = "") {
139126
139128
  const items = Array.isArray(source) ? source : [source];
139127
139129
  const messages = [];
139128
139130
  for (const item of items) {
139129
- if (typeof item === "string") {
139130
- messages.push(`${prefix}${item}`);
139131
+ if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
139132
+ messages.push(`${prefix}${String(item)}`);
139131
139133
  } else if (item && typeof item["#text"] === "string") {
139132
139134
  messages.push(`${prefix}${item["#text"]}`);
139133
139135
  }
@@ -139187,7 +139189,7 @@ class NcbiResponseHandler {
139187
139189
  });
139188
139190
  }
139189
139191
  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;
139192
+ const hasError = ERROR_PATHS.some((path) => resolvePath(parsedXml, path) !== undefined);
139191
139193
  if (hasError) {
139192
139194
  const errorMessages = this.extractNcbiErrorMessages(parsedXml);
139193
139195
  logger.error("NCBI API returned an error in XML response.", {
@@ -151008,7 +151010,7 @@ function parsePmcArticle(xmlArticle) {
151008
151010
  const keywords = extractKeywords(articleMeta?.["kwd-group"]);
151009
151011
  const sections = extractBodySections(xmlArticle.body);
151010
151012
  const references = extractReferences(xmlArticle.back);
151011
- const normalizedPmcId = pmcId.startsWith("PMC") ? pmcId : `PMC${pmcId}`;
151013
+ const normalizedPmcId = !pmcId ? "" : pmcId.startsWith("PMC") ? pmcId : `PMC${pmcId}`;
151012
151014
  return {
151013
151015
  pmcId: normalizedPmcId,
151014
151016
  ...pmid && { pmid },
@@ -151274,7 +151276,7 @@ function markdown() {
151274
151276
 
151275
151277
  // src/mcp-server/tools/definitions/pmc-fetch.tool.ts
151276
151278
  var ncbi2 = () => container.resolve(NcbiServiceToken);
151277
- var TOOL_NAME = "pmc_fetch";
151279
+ var TOOL_NAME = "pubmed_pmc_fetch";
151278
151280
  var TOOL_TITLE = "PMC Full-Text Fetch";
151279
151281
  var TOOL_DESCRIPTION = "Fetch full-text articles from PubMed Central (PMC). Returns complete article body text, sections, and references for open-access articles. Accepts PMC IDs directly or PubMed IDs (auto-resolved via ELink). Only articles available in PMC will return full text.";
151280
151282
  var TOOL_ANNOTATIONS = {
@@ -151383,7 +151385,7 @@ function filterSections(sections, sectionFilter) {
151383
151385
  });
151384
151386
  }
151385
151387
  async function logic(input, appContext, _sdkContext) {
151386
- logger.info("Executing pmc_fetch tool", {
151388
+ logger.info("Executing pubmed_pmc_fetch tool", {
151387
151389
  ...appContext,
151388
151390
  hasPmcids: !!input.pmcids,
151389
151391
  hasPmids: !!input.pmids,
@@ -151444,7 +151446,7 @@ async function logic(input, appContext, _sdkContext) {
151444
151446
  return rest;
151445
151447
  });
151446
151448
  }
151447
- logger.notice("pmc_fetch completed", {
151449
+ logger.notice("pubmed_pmc_fetch completed", {
151448
151450
  ...appContext,
151449
151451
  requested: pmcIds.length,
151450
151452
  returned: articles.length
@@ -151516,7 +151518,7 @@ var pmcFetchTool = {
151516
151518
  annotations: TOOL_ANNOTATIONS,
151517
151519
  description: TOOL_DESCRIPTION,
151518
151520
  inputSchema: InputSchema,
151519
- logic: withToolAuth(["tool:pmc_fetch:read"], logic),
151521
+ logic: withToolAuth(["tool:pubmed_pmc_fetch:read"], logic),
151520
151522
  name: TOOL_NAME,
151521
151523
  outputSchema: OutputSchema2,
151522
151524
  responseFormatter,
@@ -151531,30 +151533,35 @@ function splitPages(pages) {
151531
151533
  if (!pages)
151532
151534
  return {};
151533
151535
  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 } : {};
151536
+ const [start, end] = parts;
151537
+ if (start && end)
151538
+ return { start, end };
151539
+ return start ? { start } : {};
151544
151540
  }
151545
151541
  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{}");
151542
+ return text.replace(/[\\&%$#_{}~^]/g, (ch) => {
151543
+ switch (ch) {
151544
+ case "\\":
151545
+ return "\\textbackslash{}";
151546
+ case "~":
151547
+ return "\\textasciitilde{}";
151548
+ case "^":
151549
+ return "\\textasciicircum{}";
151550
+ default:
151551
+ return `\\${ch}`;
151552
+ }
151553
+ });
151547
151554
  }
151548
151555
  function formatAuthorApa(author) {
151549
151556
  if (author.collectiveName)
151550
151557
  return author.collectiveName;
151551
151558
  const last = author.lastName ?? "";
151552
- const initials = author.initials ?? author.firstName?.split(/[\s-]+/).map((part) => `${part[0]}.`).join(" ");
151553
- if (!last)
151554
- return initials ?? "";
151559
+ const initials = author.initials ?? author.firstName?.split(/[\s-]+/).filter(Boolean).map((part) => `${part[0]}.`).join(" ");
151555
151560
  if (!initials)
151556
151561
  return last;
151557
151562
  const formatted = initials.replace(/[^A-Za-z]/g, "").split("").map((c) => `${c}.`).join(" ");
151563
+ if (!last)
151564
+ return formatted;
151558
151565
  return `${last}, ${formatted}`;
151559
151566
  }
151560
151567
  function formatAuthorsApa(authors) {
@@ -151846,6 +151853,9 @@ function extractJournalInfo(journalXml, articleXml) {
151846
151853
  const issnType = getAttribute(issnElement, "IssnType");
151847
151854
  const issn = issnType === "Electronic" ? undefined : issnValue || undefined;
151848
151855
  const eIssn = issnType === "Electronic" ? issnValue || undefined : undefined;
151856
+ const month = getText(pubDate?.Month);
151857
+ const day = getText(pubDate?.Day);
151858
+ const medlineDate = getText(pubDate?.MedlineDate);
151849
151859
  return {
151850
151860
  title: getText(journalXml.Title),
151851
151861
  isoAbbreviation: getText(journalXml.ISOAbbreviation),
@@ -151856,9 +151866,9 @@ function extractJournalInfo(journalXml, articleXml) {
151856
151866
  pages: getText(articleXml?.Pagination?.MedlinePgn),
151857
151867
  publicationDate: {
151858
151868
  ...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) }
151869
+ ...month && { month },
151870
+ ...day && { day },
151871
+ ...medlineDate && { medlineDate }
151862
151872
  }
151863
151873
  };
151864
151874
  }
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.2",
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",
@@ -78,7 +78,7 @@
78
78
  "rollup": "4.59.0"
79
79
  },
80
80
  "devDependencies": {
81
- "@cloudflare/workers-types": "^4.20260301.1",
81
+ "@cloudflare/workers-types": "^4.20260305.1",
82
82
  "@biomejs/biome": "2.4.5",
83
83
  "@hono/mcp": "^0.2.4",
84
84
  "@traversable/registry": "^0.0.49",