A Model Context Protocol (MCP) server that prevents citation hallucination by verifying academic citations against 9 authoritative databases. This server enables AI assistants to verify every citation
翻译准备中
开发工具TypeScript · JavaScriptGitHub @tfscharff自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
安装型项目无需部署域名也可验证。个人仓库可通过 GitHub 登录验证,组织仓库可使用上方的仓库验证文件。
A Model Context Protocol (MCP) server that prevents citation hallucination by verifying academic citations against 9 authoritative databases. This server enables AI assistants to verify every citation against real publications before citing them.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗npx -y github:tfscharff/doi-mcp
Or add to your Claude Desktop config:
{
"mcpServers": {
"doi-mcp": {
"command": "npx",
"args": ["-y", "github:tfscharff/doi-mcp"]
}
}
}
To pin a release, append its tag: github:tfscharff/doi-mcp#v7.0.0. See Releases.
Large language models sometimes "hallucinate" academic citations - citing papers that don't exist, misattributing real titles to wrong authors, or mixing up publication details. This MCP server eliminates that problem by:
When an AI assistant is asked about research or for citations:
verifyCitation first, which searches across 8 databases in parallel and returns:
If a DOI is supplied, it is resolved directly at doi.org first; the database search is the fallback.
Each candidate returned by the databases is scored against the citation:
| Match | Points |
|---|---|
| Title contains the first 30 characters of the cited title (case-insensitive) | +3 |
| Exact year | +3 (±1 year: +1) |
| Each cited author whose last name appears in the candidate's authors | +2 |
A candidate is only considered if it has a DOI and matches on title or at least one author. A score of 3+ verifies the citation; 5+ is reported as high confidence.
verified: false. This is deliberate: the server only vouches for citations it can link to.SEMANTIC_SCHOLAR_API_KEY (see Installation) for a dedicated quota. Without one, a 429 is retried once after a second; if that is also limited, its RATE_LIMITED error is reported and the other databases are still used.limit results and trimmed back to limit after dropping records without a DOI, so a few DOI-less top hits don't empty a source.All tools are read-only (readOnlyHint: true, destructiveHint: false, idempotentHint: true).
Primary anti-hallucination tool - Verifies a citation exists before it can be mentioned.
Input:
title (string, optional): Paper title (partial matches accepted)authors (array, optional): Author names (last names sufficient)year (number, optional): Publication yeardoi (string, optional): DOI if knownjournal (string, optional): Journal nameReturns JSON with:
verified: true/falseconfidence (high/medium), source, doi, doiUrl, title, authors, year, journal, abstractFromArticle, messagemessage, plus possibleMatches (each with a DOI) when there were near misses, and errors (database, code, message) for any database that failed, since it may have held the matchExample successful verification:
{
"verified": true,
"confidence": "high",
"source": "CrossRef",
"doi": "10.1038/nature14539",
"doiUrl": "https://doi.org/10.1038/nature14539",
"title": "Deep learning",
"authors": ["Yann LeCun", "Yoshua Bengio", "Geoffrey Hinton"],
"year": 2015,
"journal": "Nature",
"message": "✓ Citation verified with high confidence"
}
Verify several citations in one call. Each citation takes the same fields as verifyCitation, plus an optional id to match results back to inputs.
Input:
citations (array): { id?, title?, authors?, year?, doi?, journal? } objectsReturns: summary (total, verified, failed) and a results array, one entry per citation, each with id, verified, and either paper (including doiUrl) or a message. Unverified entries also carry errors for any database that failed.
Search for real papers on a topic and return only papers with DOIs.
Input:
query (string): Search query (topic, keywords, author names)source (string, optional): Which database to search - "all" (default), "crossref", "openalex", "pubmed", "zbmath", "eric", "hal", "inspirehep", or "semanticscholar"limit (number, optional): Number of results per source (1-20, default: 5)yearFrom (number, optional): Minimum publication yearyearTo (number, optional): Maximum publication yearReturns: Up to limit papers, deduplicated by DOI, each with source, title, authors, year, journal, doi, and doiUrl, plus errors for any database that failed.
With no papers, it returns count: 0, sourcesQueried, errors, and a message that separates "nothing with a DOI matched" from "these databases failed". If every database queried failed, the result is also flagged isError:
{
"count": 0,
"message": "Every database queried failed, so no papers could be checked: Semantic Scholar (HTTP 429: rate limited (...)).",
"sourcesQueried": ["Semantic Scholar"],
"errors": [{ "database": "Semantic Scholar", "code": "RATE_LIMITED", "message": "HTTP 429: rate limited (...)" }]
}
Example:
// Search all 8 databases
findVerifiedPapers({ query: "CRISPR gene editing", limit: 5 })
// Search only PubMed for biomedical papers
findVerifiedPapers({ query: "cancer immunotherapy", source: "pubmed", limit: 10 })
// Search zbMATH for mathematics papers
findVerifiedPapers({ query: "algebraic topology", source: "zbmath" })
// Search ERIC for education research
findVerifiedPapers({ query: "active learning pedagogy", source: "eric" })
// Search HAL for French/European humanities research
findVerifiedPapers({ query: "phenomenology Husserl", source: "hal" })
// Search INSPIRE-HEP for high-energy physics papers
findVerifiedPapers({ query: "Higgs boson", source: "inspirehep" })
citation://databases (JSON): the 8 databases with coverage and API URLscitation://guidelines (Markdown): when and how to use each toolcitation-verification-rules (prompt): rules that tell the assistant to verify before citing and to cite only with a DOIAdd to your Claude Desktop config file:
Windows: %APPDATA%\Claude\claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"doi-mcp": {
"command": "npx",
"args": ["-y", "github:tfscharff/doi-mcp"]
}
}
}
Restart Claude Desktop and the server will be available.
To give Semantic Scholar a dedicated quota, add a free API key to the server's environment:
"doi-mcp": {
"command": "npx",
"args": ["-y", "github:tfscharff/doi-mcp"],
"env": { "SEMANTIC_SCHOLAR_API_KEY": "your-key" }
}
npm install -g github:tfscharff/doi-mcp
Then use this config:
{
"mcpServers": {
"doi-mcp": {
"command": "doi-mcp"
}
}
}
git clone https://github.com/tfscharff/doi-mcp.git
cd doi-mcp
npm install
npm run build
Config for local install:
{
"mcpServers": {
"doi-mcp": {
"command": "node",
"args": ["/absolute/path/to/doi-mcp/dist/index.js"]
}
}
}
node --version (requires v18+)%APPDATA%\Claude\logs\~/Library/Logs/Claude/~/.config/Claude/logs/npm cache clean --force
npx @modelcontextprotocol/inspector node dist/index.js
Every change is published as a GitHub release following Semantic Versioning:
See CHANGELOG.md for what changed in each version.
Development requires Node.js 22.12+ (for Vitest 5). The server itself runs on Node 18+.
npm install # Install dependencies
npm run build # Compile TypeScript to dist/
npm run dev # Watch mode
npm test # Run tests
npm run test:watch # Tests in watch mode
npm run test:coverage # Tests with coverage report
Tests mock all network calls; nothing hits the live APIs.
dist/ is committed so npx can run the server straight from GitHub. Don't commit or tag releases by hand; use:
npm run ship -- "fix(pubmed): handle missing PMIDs" --body-file notes.md
The optional notes file becomes the body of the CHANGELOG.md entry and the GitHub release notes. On Windows, npm cuts inline arguments off at the first newline, so ship refuses --body there; use --body-file.
scripts/ship.mjs checks the header is a Conventional Commit, runs the tests, rebuilds dist/, bumps the version (feat → minor; fix, docs, chore, etc. → patch; ! or BREAKING CHANGE: → major), adds a CHANGELOG.md entry, then commits, tags vX.Y.Z, pushes, and creates the GitHub release. Use --dry-run to preview, or --as X.Y.Z to force a version. It only runs on main with uncommitted changes.
src/
├── index.ts # Entry point (stdio transport)
├── server.ts # MCP server setup, Zod input schemas
├── types.ts # Shared interfaces
├── scoring.ts # Match scoring algorithm
├── cache.ts # Result cache (5-min TTL)
├── http.ts # Fetch utilities with timeouts
├── tools/ # Tool handlers
│ ├── verifyCitation.ts
│ ├── batchVerifyCitations.ts
│ └── findVerifiedPapers.ts
└── databases/ # Database adapters
├── index.ts # Parallel query orchestrator; drops results without a DOI
├── crossref.ts
├── openalex.ts
├── pubmed.ts
└── ... (8 adapters total)
Adding a new database:
src/databases/newdb.ts with config, search(), and normalize()src/databases/index.tssrc/server.tstests/databases/newdb.test.tsBefore this MCP (citation hallucination):
User: "Tell me about recent AlphaFold research"
Assistant: "According to Johnson et al. (2024) in Science, AlphaFold3 achieved..."
❌ This paper doesn't exist
After this MCP (verified citations only):
User: "Tell me about recent AlphaFold research"
Assistant: [Uses findVerifiedPapers tool]
"According to Abramson et al. (2024) in Nature (https://doi.org/10.1038/s41586-024-07487-w),
AlphaFold 3 predicts..."
✓ Real paper with a DOI
Verification catches fake citations:
User: "Can you verify this citation: Smith et al. (2024), 'Quantum AI', Nature"
Assistant: [Uses verifyCitation tool - searches all 8 databases in parallel]
"⚠ I cannot verify this citation - no matching publication with a DOI
was found in any of the 8 databases. This citation may be incorrect."
All databases are queried in parallel:
600+ million publications across all academic disciplines with specialized depth in STEM, computer science, biomedical sciences, mathematics, and education research. Only records that carry a DOI are used.
MIT
Contributions are welcome! Please feel free to submit issues or pull requests.