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.