ワンクリックで
pm-export
// Export PubMed paper(s) to Zotero or save as RIS file. Supports single paper by PMID or batch export from search results. Use when user wants to save papers to their reference manager.
// Export PubMed paper(s) to Zotero or save as RIS file. Supports single paper by PMID or batch export from search results. Use when user wants to save papers to their reference manager.
Perform advanced PubMed search with field qualifiers - author, title, journal, MeSH, date range, article type. Constructs proper PubMed query syntax from natural language. Use for precise filtered searches.
Find full-text download links for a PubMed paper by PMID - DOI, PMC open access, Sci-Hub, and publisher links. Use when user wants to read or download a paper's full text.
Navigate PubMed search result pages or change sort order. Use when user wants to see more results or change ordering.
Get full paper details for a PubMed article by PMID - title, authors with affiliations, abstract, MeSH terms, keywords, publication types, DOI, and citation info. Use when user needs detailed information about a specific paper.
Search PubMed for biomedical literature by keywords. Returns structured results with PMID, title, authors, journal, date, DOI. Use when the user wants to find papers on a topic.
| name | pm-export |
| description | Export PubMed paper(s) to Zotero or save as RIS file. Supports single paper by PMID or batch export from search results. Use when user wants to save papers to their reference manager. |
| argument-hint | [PMID or space-separated PMIDs] |
Export PubMed paper citation data and push to Zotero desktop via local Connector API, or generate MEDLINE/RIS format.
$ARGUMENTS contains one or more PMIDs (space-separated), e.g.:
35641793 — single paper35641793 27741350 35362092 — batch exportUse mcp__chrome-devtools__evaluate_script on any PubMed page. Replace PMID_LIST with the actual PMIDs:
async () => {
const pmids = "PMID_LIST".split(/[\s,]+/).filter(Boolean);
// Batch esummary for basic metadata
const sumResp = await fetch(
`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${pmids.join(',')}&retmode=json`
);
const sumData = await sumResp.json();
// efetch XML for full records (abstracts, keywords)
const fetchResp = await fetch(
`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=${pmids.join(',')}&retmode=xml`
);
const xml = await fetchResp.text();
const xmlDoc = new DOMParser().parseFromString(xml, 'text/xml');
const papers = pmids.map(pmid => {
const r = sumData.result?.[pmid] || {};
const doi = (r.articleids || []).find(a => a.idtype === 'doi')?.value || '';
// Find this paper's article in the XML
const articles = xmlDoc.querySelectorAll('PubmedArticle');
let abstract = '', keywords = [], meshTerms = [], pubTypes = [];
let issn = '', pmcid = '';
for (const art of articles) {
if (art.querySelector('PMID')?.textContent === pmid) {
abstract = Array.from(art.querySelectorAll('AbstractText'))
.map(el => el.textContent).join(' ');
keywords = Array.from(art.querySelectorAll('Keyword'))
.map(k => k.textContent);
meshTerms = Array.from(art.querySelectorAll('MeshHeading DescriptorName'))
.map(d => d.textContent);
pubTypes = Array.from(art.querySelectorAll('PublicationType'))
.map(p => p.textContent);
issn = art.querySelector('ISSN')?.textContent || '';
pmcid = art.querySelector('ArticleId[IdType="pmc"]')?.textContent || '';
break;
}
}
return {
pmid,
title: r.title || '',
authors: (r.authors || []).map(a => ({
lastName: a.name?.split(' ')[0] || '',
firstName: a.name?.split(' ').slice(1).join(' ') || '',
})),
journal: r.fulljournalname || '',
journalAbbr: r.source || '',
pubdate: r.pubdate || '',
volume: r.volume || '',
issue: r.issue || '',
pages: r.pages || '',
doi,
issn,
pmcid,
abstract,
keywords,
pubtype: pubTypes,
language: (r.lang || ['eng'])[0] === 'eng' ? 'en' : (r.lang || ['eng'])[0]
};
});
return papers;
}
Save the returned JSON array to a temp file, then run the Python script:
python "e:/pm-skills/.claude/skills/pm-export/scripts/push_to_zotero.py" /tmp/pm_papers.json
The Python script runs a 3-step flow:
POST /connector/saveItems). Note: Zotero 7.x ignores the attachments field in saveItems.pdfUrl or pmcid is available)POST /connector/saveAttachment), linked to the parent item via parentItemID in the X-Metadata headerOther details:
itemType: journalArticle, libraryCatalog: PubMed){firstName, lastName} structureSingle paper:
Exported to Zotero:
Title: {title}
Authors: {authors}
Journal: {journal} ({pubdate})
DOI: {doi}
PMID: {pmid}
Batch:
Exported {count} papers to Zotero:
1. {title1} ({journal1}, {pubdate1})
2. {title2} ({journal2}, {pubdate2})
...
If the user wants a file instead of Zotero, use efetch to get MEDLINE format directly:
async () => {
const pmids = "PMID_LIST";
const resp = await fetch(
`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=${pmids}&rettype=medline&retmode=text`
);
return await resp.text();
}
Save the returned text as a .nbib file. This can be imported into Zotero, EndNote, or any reference manager.
evaluate_script + bash pythone:/pm-skills/.claude/skills/pm-export/scripts/push_to_zotero.py