Skip to main content
Glama
flyanima

Open Search MCP

by flyanima

pubmed_article_details

Retrieve detailed information about a specific PubMed article by providing its PMID, enabling quick access to essential research data and metadata for academic or scientific purposes.

Instructions

Get detailed information about a specific PubMed article

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pmidYesPubMed ID (PMID) of the article

Implementation Reference

  • The execute function implementing the core logic for fetching detailed PubMed article information using ESummary and optionally EFetch APIs.
    execute: async (args: any) => { const { pmid } = args; try { // 获取文章摘要信息 const summaryParams = { db: 'pubmed', id: pmid, retmode: 'json' }; const summaryResult = await client.makeRequest('esummary.fcgi', summaryParams); if (!summaryResult.result || !summaryResult.result[pmid]) { return { success: false, error: `Article with PMID ${pmid} not found` }; } const article = summaryResult.result[pmid]; // 尝试获取全文摘要 let fullAbstract = null; try { const fetchParams = { db: 'pubmed', id: pmid, retmode: 'xml', rettype: 'abstract' }; const fetchResult = await client.makeRequest('efetch.fcgi', fetchParams); // 这里可以解析XML获取完整摘要,暂时使用summary中的摘要 fullAbstract = article.abstract || 'No abstract available'; } catch (fetchError) { fullAbstract = article.abstract || 'No abstract available'; } const articleDetails = { pmid: article.uid, title: article.title || 'No title available', abstract: fullAbstract, authors: (article.authors || []).map((author: any) => ({ name: author.name, affiliation: author.affiliation || null })), journal: { name: article.fulljournalname || article.source || 'Unknown journal', abbreviation: article.source || null, volume: article.volume || null, issue: article.issue || null, pages: article.pages || null }, publicationDate: article.pubdate || 'Unknown date', publicationType: (article.pubtype || []).join(', ') || 'Unknown type', doi: article.elocationid && article.elocationid.includes('doi:') ? article.elocationid.replace('doi: ', '') : null, pmcid: article.pmcid || null, meshTerms: article.keywords || [], url: `https://pubmed.ncbi.nlm.nih.gov/${article.uid}/`, fullTextUrl: article.pmcid ? `https://www.ncbi.nlm.nih.gov/pmc/articles/${article.pmcid}/` : null, citationCount: null, // PubMed API不直接提供引用数 source: 'PubMed' }; return { success: true, data: { source: 'PubMed API', article: articleDetails, timestamp: Date.now(), apiUsed: true } }; } catch (error) { return { success: false, error: `Failed to get PubMed article details: ${error instanceof Error ? error.message : String(error)}` }; } }
  • Input schema defining the required 'pmid' parameter as a string.
    inputSchema: { type: 'object', properties: { pmid: { type: 'string', description: 'PubMed ID (PMID) of the article' } }, required: ['pmid'] },
  • Local registration of the pubmed_article_details tool within the registerPubMedTools function, including name, description, schema, and handler.
    registry.registerTool({ name: 'pubmed_article_details', description: 'Get detailed information about a specific PubMed article', category: 'academic', source: 'PubMed', inputSchema: { type: 'object', properties: { pmid: { type: 'string', description: 'PubMed ID (PMID) of the article' } }, required: ['pmid'] }, execute: async (args: any) => { const { pmid } = args; try { // 获取文章摘要信息 const summaryParams = { db: 'pubmed', id: pmid, retmode: 'json' }; const summaryResult = await client.makeRequest('esummary.fcgi', summaryParams); if (!summaryResult.result || !summaryResult.result[pmid]) { return { success: false, error: `Article with PMID ${pmid} not found` }; } const article = summaryResult.result[pmid]; // 尝试获取全文摘要 let fullAbstract = null; try { const fetchParams = { db: 'pubmed', id: pmid, retmode: 'xml', rettype: 'abstract' }; const fetchResult = await client.makeRequest('efetch.fcgi', fetchParams); // 这里可以解析XML获取完整摘要,暂时使用summary中的摘要 fullAbstract = article.abstract || 'No abstract available'; } catch (fetchError) { fullAbstract = article.abstract || 'No abstract available'; } const articleDetails = { pmid: article.uid, title: article.title || 'No title available', abstract: fullAbstract, authors: (article.authors || []).map((author: any) => ({ name: author.name, affiliation: author.affiliation || null })), journal: { name: article.fulljournalname || article.source || 'Unknown journal', abbreviation: article.source || null, volume: article.volume || null, issue: article.issue || null, pages: article.pages || null }, publicationDate: article.pubdate || 'Unknown date', publicationType: (article.pubtype || []).join(', ') || 'Unknown type', doi: article.elocationid && article.elocationid.includes('doi:') ? article.elocationid.replace('doi: ', '') : null, pmcid: article.pmcid || null, meshTerms: article.keywords || [], url: `https://pubmed.ncbi.nlm.nih.gov/${article.uid}/`, fullTextUrl: article.pmcid ? `https://www.ncbi.nlm.nih.gov/pmc/articles/${article.pmcid}/` : null, citationCount: null, // PubMed API不直接提供引用数 source: 'PubMed' }; return { success: true, data: { source: 'PubMed API', article: articleDetails, timestamp: Date.now(), apiUsed: true } }; } catch (error) { return { success: false, error: `Failed to get PubMed article details: ${error instanceof Error ? error.message : String(error)}` }; } } });
  • src/index.ts:230-230 (registration)
    Top-level registration call in the main server index file, which invokes registerPubMedTools to add the pubmed_article_details tool (among others) to the global ToolRegistry.
    registerPubMedTools(this.toolRegistry); // 1 tool: search_pubmed
  • PubMedAPIClient class providing the makeRequest method used by the handler to query PubMed EUtils APIs.
    class PubMedAPIClient { private baseURL = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils'; private apiKey: string | undefined; constructor(apiKey?: string) { this.apiKey = apiKey; } async makeRequest(endpoint: string, params: Record<string, any> = {}) { try { const requestParams = { ...params, retmode: 'json', retmax: Math.min(params.retmax || 20, 200), tool: 'open-search-mcp', email: 'support@open-search-mcp.com' }; if (this.apiKey) { (requestParams as any).api_key = this.apiKey; } const response = await axios.get(`${this.baseURL}/${endpoint}`, { params: requestParams, timeout: 20000, headers: { 'User-Agent': 'Open-Search-MCP/2.0' } }); return response.data; } catch (error) { throw error; } } async searchPubMed(query: string, options: any = {}) { // 第一步:搜索获取PMID列表 const searchParams = { db: 'pubmed', term: query, retmax: options.maxResults || 20, sort: options.sort === 'date' ? 'pub_date' : 'relevance', datetype: 'pdat' }; // 添加日期过滤 if (options.dateRange && options.dateRange !== 'all') { const now = new Date(); let startDate; switch (options.dateRange) { case '1year': startDate = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate()); break; case '5years': startDate = new Date(now.getFullYear() - 5, now.getMonth(), now.getDate()); break; case '10years': startDate = new Date(now.getFullYear() - 10, now.getMonth(), now.getDate()); break; } if (startDate) { const startDateStr = startDate.toISOString().split('T')[0].replace(/-/g, '/'); const endDateStr = now.toISOString().split('T')[0].replace(/-/g, '/'); searchParams.term += ` AND ("${startDateStr}"[Date - Publication] : "${endDateStr}"[Date - Publication])`; } } // 添加出版物类型过滤 if (options.publicationType && options.publicationType !== 'all') { const typeMap: Record<string, string> = { 'review': 'Review[Publication Type]', 'clinical_trial': 'Clinical Trial[Publication Type]', 'meta_analysis': 'Meta-Analysis[Publication Type]', 'case_report': 'Case Reports[Publication Type]' }; const pubType = options.publicationType as string; if (typeMap[pubType]) { searchParams.term += ` AND ${typeMap[pubType]}`; } } const searchResult = await this.makeRequest('esearch.fcgi', searchParams); if (!searchResult.esearchresult || !searchResult.esearchresult.idlist || searchResult.esearchresult.idlist.length === 0) { return { articles: [], count: 0 }; } const pmids = searchResult.esearchresult.idlist; // 第二步:获取详细信息 const summaryParams = { db: 'pubmed', id: pmids.join(','), retmode: 'json' }; const summaryResult = await this.makeRequest('esummary.fcgi', summaryParams); return { articles: this.parseSummaryResult(summaryResult), count: parseInt(searchResult.esearchresult.count) || 0 }; } private parseSummaryResult(summaryResult: any): any[] { if (!summaryResult.result) return []; const articles = []; const uids = summaryResult.result.uids || []; for (const uid of uids) { const article = summaryResult.result[uid]; if (!article) continue; articles.push({ pmid: article.uid, title: article.title || 'No title available', abstract: article.abstract || 'No abstract available', authors: (article.authors || []).map((author: any) => author.name).join(', '), journal: article.fulljournalname || article.source || 'Unknown journal', publicationDate: article.pubdate || 'Unknown date', publicationType: (article.pubtype || []).join(', ') || 'Unknown type', doi: article.elocationid && article.elocationid.includes('doi:') ? article.elocationid.replace('doi: ', '') : null, pmcid: article.pmcid || null, volume: article.volume || null, issue: article.issue || null, pages: article.pages || null, url: `https://pubmed.ncbi.nlm.nih.gov/${article.uid}/`, fullTextUrl: article.pmcid ? `https://www.ncbi.nlm.nih.gov/pmc/articles/${article.pmcid}/` : null }); } return articles; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/flyanima/open-search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server