pubmed_articles
Search PubMed's biomedical literature database, retrieve article metadata, and download PDFs for research and analysis.
Instructions
Unified tool for PubMed operations: search biomedical literature, retrieve article metadata, and download PDFs. Access over 35 million citations from the world's largest biomedical database. Use the method parameter to specify the operation type: search with keywords, advanced filtered search, get detailed metadata, or download full-text PDFs when available.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| method | Yes | The operation to perform: search_keywords (search with keywords), search_advanced (search with filters), get_article_metadata (get detailed metadata), or get_article_pdf (download full-text PDF) | |
| keywords | No | For search_keywords: Search query string with keywords, medical terms, drug names, diseases, or any biomedical research terms. Can include multiple terms separated by spaces (implicit AND logic) or use PubMed search operators like OR, AND, NOT. | |
| num_results | No | For search methods: Maximum number of results to return (default: 10). Note: PubMed API may have its own limits and may return fewer results than requested. | |
| pmid | No | For get_article_metadata and get_article_pdf: PubMed ID (PMID) of the article - the unique identifier for PubMed articles (e.g., "12345678" or 12345678) | |
| term | No | For search_advanced: General search term for title, abstract, and keywords | |
| title | No | For search_advanced: Search specifically in article titles | |
| author | No | For search_advanced: Author name(s) to search for (e.g., "Smith J", "John Smith") | |
| journal | No | For search_advanced: Journal name or abbreviation (e.g., "Nature", "N Engl J Med", "Science") | |
| start_date | No | For search_advanced: Start date for publication date range in format YYYY/MM/DD (e.g., "2020/01/01") | |
| end_date | No | For search_advanced: End date for publication date range in format YYYY/MM/DD (e.g., "2024/12/31") |
Implementation Reference
- src/index.js:89-184 (handler)The main handler for the 'pubmed_articles' tool in the CallToolRequestSchema handler. It checks the tool name, parses arguments, and dispatches to specific helper functions based on the 'method' parameter (search_keywords, search_advanced, get_article_metadata, get_article_pdf).server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name !== 'pubmed_articles') { throw new Error(`Unknown tool: ${name}`); } try { const { method, ...params } = args; switch (method) { case 'search_keywords': { const { keywords, num_results = 10 } = params; if (!keywords) { throw new Error('keywords parameter is required for search_keywords'); } const results = await searchKeywords(keywords, num_results); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2) } ] }; } case 'search_advanced': { const { num_results = 10, ...searchParams } = params; const advancedParams = { method, num_results, ...searchParams }; const results = await searchAdvanced(advancedParams); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2) } ] }; } case 'get_article_metadata': { const { pmid } = params; if (!pmid) { throw new Error('pmid parameter is required for get_article_metadata'); } const result = await getArticleMetadata(pmid); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } case 'get_article_pdf': { const { pmid } = params; if (!pmid) { throw new Error('pmid parameter is required for get_article_pdf'); } const result = await downloadFullTextPdf(pmid); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } default: throw new Error(`Unknown method: ${method}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text', text: JSON.stringify({ error: errorMessage }, null, 2) } ] }; } });
- src/index.js:30-82 (schema)Input schema definition for the 'pubmed_articles' tool, specifying parameters like method, keywords, pmid, etc., with descriptions and validation rules.inputSchema: { type: 'object', properties: { method: { type: 'string', enum: ['search_keywords', 'search_advanced', 'get_article_metadata', 'get_article_pdf'], description: 'The operation to perform: search_keywords (search with keywords), search_advanced (search with filters), get_article_metadata (get detailed metadata), or get_article_pdf (download full-text PDF)' }, keywords: { type: 'string', description: 'For search_keywords: Search query string with keywords, medical terms, drug names, diseases, or any biomedical research terms. Can include multiple terms separated by spaces (implicit AND logic) or use PubMed search operators like OR, AND, NOT.' }, num_results: { type: 'integer', default: 10, minimum: 1, description: 'For search methods: Maximum number of results to return (default: 10). Note: PubMed API may have its own limits and may return fewer results than requested.' }, pmid: { oneOf: [ { type: 'string' }, { type: 'integer' } ], description: 'For get_article_metadata and get_article_pdf: PubMed ID (PMID) of the article - the unique identifier for PubMed articles (e.g., "12345678" or 12345678)' }, term: { type: 'string', description: 'For search_advanced: General search term for title, abstract, and keywords' }, title: { type: 'string', description: 'For search_advanced: Search specifically in article titles' }, author: { type: 'string', description: 'For search_advanced: Author name(s) to search for (e.g., "Smith J", "John Smith")' }, journal: { type: 'string', description: 'For search_advanced: Journal name or abbreviation (e.g., "Nature", "N Engl J Med", "Science")' }, start_date: { type: 'string', description: 'For search_advanced: Start date for publication date range in format YYYY/MM/DD (e.g., "2020/01/01")' }, end_date: { type: 'string', description: 'For search_advanced: End date for publication date range in format YYYY/MM/DD (e.g., "2024/12/31")' } }, required: ['method'], additionalProperties: false }
- src/index.js:24-86 (registration)Registers the 'pubmed_articles' tool in the MCP server by returning it in the ListToolsRequestSchema handler.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'pubmed_articles', description: 'Unified tool for PubMed operations: search biomedical literature, retrieve article metadata, and download PDFs. Access over 35 million citations from the world\'s largest biomedical database. Use the method parameter to specify the operation type: search with keywords, advanced filtered search, get detailed metadata, or download full-text PDFs when available.', inputSchema: { type: 'object', properties: { method: { type: 'string', enum: ['search_keywords', 'search_advanced', 'get_article_metadata', 'get_article_pdf'], description: 'The operation to perform: search_keywords (search with keywords), search_advanced (search with filters), get_article_metadata (get detailed metadata), or get_article_pdf (download full-text PDF)' }, keywords: { type: 'string', description: 'For search_keywords: Search query string with keywords, medical terms, drug names, diseases, or any biomedical research terms. Can include multiple terms separated by spaces (implicit AND logic) or use PubMed search operators like OR, AND, NOT.' }, num_results: { type: 'integer', default: 10, minimum: 1, description: 'For search methods: Maximum number of results to return (default: 10). Note: PubMed API may have its own limits and may return fewer results than requested.' }, pmid: { oneOf: [ { type: 'string' }, { type: 'integer' } ], description: 'For get_article_metadata and get_article_pdf: PubMed ID (PMID) of the article - the unique identifier for PubMed articles (e.g., "12345678" or 12345678)' }, term: { type: 'string', description: 'For search_advanced: General search term for title, abstract, and keywords' }, title: { type: 'string', description: 'For search_advanced: Search specifically in article titles' }, author: { type: 'string', description: 'For search_advanced: Author name(s) to search for (e.g., "Smith J", "John Smith")' }, journal: { type: 'string', description: 'For search_advanced: Journal name or abbreviation (e.g., "Nature", "N Engl J Med", "Science")' }, start_date: { type: 'string', description: 'For search_advanced: Start date for publication date range in format YYYY/MM/DD (e.g., "2020/01/01")' }, end_date: { type: 'string', description: 'For search_advanced: End date for publication date range in format YYYY/MM/DD (e.g., "2024/12/31")' } }, required: ['method'], additionalProperties: false } } ] }; });
- src/pubmed-search.js:162-177 (helper)Helper function searchKeywords: performs keyword-based PubMed search, fetches PMIDs, retrieves metadata for each, and returns article list. Called by handler for 'search_keywords' method.async function searchKeywords(keywords, numResults = 10) { console.log(`Generated search URL for keywords: ${keywords}`); const searchUrl = generatePubMedSearchUrl(keywords, numResults); const pmids = await searchPubMed(searchUrl); const articles = []; for (const pmid of pmids) { const metadata = await getPubMedMetadata(pmid); if (metadata) { articles.push(metadata); } } return articles; }
- src/pubmed-search.js:43-160 (helper)Core helper getPubMedMetadata: fetches and parses PubMed article XML via EFetch API, extracts comprehensive metadata including title, authors, abstract, DOI, etc. Used by search functions and getArticleMetadata.async function getPubMedMetadata(pmid) { try { const url = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=${pmid}&retmode=xml`; const response = await axios.get(url, { timeout: 30000, headers: { 'User-Agent': 'PubMed-MCP-Server/1.0.0 (uh-joan@github.com)' } }); const result = await parseXML(response.data); const article = result?.PubmedArticleSet?.PubmedArticle?.[0]; if (!article) return null; const medlineCitation = article.MedlineCitation?.[0]; const pubmedData = article.PubmedData?.[0]; if (!medlineCitation) return null; const title = medlineCitation.Article?.[0]?.ArticleTitle?.[0] || 'No title available'; const journal = medlineCitation.Article?.[0]?.Journal?.[0]?.Title?.[0] || 'Unknown journal'; const authors = []; const authorList = medlineCitation.Article?.[0]?.AuthorList?.[0]?.Author; if (authorList) { for (const author of authorList) { const lastName = author.LastName?.[0] || ''; const foreName = author.ForeName?.[0] || ''; if (lastName) { authors.push(`${lastName}, ${foreName}`.trim()); } } } let publicationDate = 'Unknown date'; const pubDate = medlineCitation.Article?.[0]?.Journal?.[0]?.JournalIssue?.[0]?.PubDate?.[0]; if (pubDate) { const year = pubDate.Year?.[0] || ''; const month = pubDate.Month?.[0] || ''; const day = pubDate.Day?.[0] || ''; publicationDate = [year, month, day].filter(Boolean).join('-'); } const abstractTexts = medlineCitation.Article?.[0]?.Abstract?.[0]?.AbstractText; let abstract = ''; if (abstractTexts) { abstract = abstractTexts.map(text => { if (typeof text === 'string') return text; if (text._) return text._; return ''; }).join(' '); } let doi = ''; const articleIds = pubmedData?.ArticleIdList?.[0]?.ArticleId; if (articleIds) { for (const id of articleIds) { if (id.$ && id.$.IdType === 'doi') { doi = id._; break; } } } let pmcid = ''; if (articleIds) { for (const id of articleIds) { if (id.$ && id.$.IdType === 'pmc') { pmcid = id._; break; } } } const meshTerms = []; const meshHeadingList = medlineCitation.MeshHeadingList?.[0]?.MeshHeading; if (meshHeadingList) { for (const heading of meshHeadingList) { const descriptorName = heading.DescriptorName?.[0]?._; if (descriptorName) { meshTerms.push(descriptorName); } } } const keywords = []; const keywordList = medlineCitation.KeywordList?.[0]?.Keyword; if (keywordList) { for (const keyword of keywordList) { if (typeof keyword === 'string') { keywords.push(keyword); } else if (keyword._) { keywords.push(keyword._); } } } return { pmid, title, authors, journal, publication_date: publicationDate, abstract, doi, pmcid, keywords, mesh_terms: meshTerms, url: `https://pubmed.ncbi.nlm.nih.gov/${pmid}/` }; } catch (error) { console.error(`Error fetching metadata for PMID ${pmid}:`, error.message); return null; } }