DOI Citation Verifier
This server verifies academic citations and finds real DOI-backed papers across multiple scholarly databases.
Verify a single citation with
verifyCitationusing title, authors, year, DOI, and/or journal; it returns verified status, confidence/source/DOI link, possible matches, and database errors.Batch-verify many citations in one call with
batchVerifyCitations, optionally tracking each citation byid.Search for papers by topic, keywords, or author with
findVerifiedPapers, optionally limiting to one source, max results (1โ20), and publication-year range; results are deduplicated and DOI-only.Query multiple databases in parallel: CrossRef, OpenAlex, PubMed, zbMATH, ERIC, HAL, INSPIRE-HEP, and Semantic Scholar; the schema also lists DBLP, though the README says DBLP was removed in 7.0.0.
Use DOI links, caching, source selection, and an optional Semantic Scholar API key; the tools are read-only/idempotent and report database failures instead of hiding them.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DOI Citation Verifier verify the paper 'Attention Is All You Need' by Vaswani et al. from 2017"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
๐ Quick Install
npx -y github:tfscharff/doi-mcpOr 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.
Related MCP server: CiteStamp MCP server
The Problem This Solves
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:
8-database verification: Checks citations across CrossRef, OpenAlex, PubMed, zbMATH, ERIC, HAL, INSPIRE-HEP, and Semantic Scholar
Parallel search: Queries all databases simultaneously
Comprehensive coverage: 600+ million publications across all disciplines including STEM, humanities, social sciences, and education
DOI-only results: A paper counts only if a database returns a DOI for it. Every verified citation, possible match, and search result includes a DOI.
Features
8 Database Search: CrossRef, OpenAlex, PubMed, zbMATH, ERIC, HAL, INSPIRE-HEP, Semantic Scholar
Verify Citations: Check if a paper with specific details actually exists, one at a time or in batches
Find Verified Papers: Search for real papers on a topic and get only DOI-backed results
Strict matching: A candidate must match the citation's title or an author; a matching year alone never verifies anything
Parallel Processing: All database queries run simultaneously
Caching: Repeated successful queries return instantly (5-minute TTL, 100 entries)
Source Selection: Search all databases or target specific sources
Zero Configuration: No API keys required (an optional Semantic Scholar key avoids its shared rate limit)
Failures are reported, not hidden: When a database errors or rate-limits, responses name it and say why, so a failed lookup is never mistaken for "no such paper"
Fully Tested: 100% line coverage across scoring, caching, HTTP, all 8 database adapters, the tools, and the MCP server itself
How It Works
When an AI assistant is asked about research or for citations:
Without this MCP: The assistant might cite "According to Smith et al. (2023) in Nature..." referencing a paper that doesn't exist
With this MCP: The assistant uses
verifyCitationfirst, which searches across 8 databases in parallel and returns:Verified match with a DOI โ Can be cited
No DOI-backed match found โ Cannot cite; must search for real papers instead
If a DOI is supplied, it is resolved directly at doi.org first; the database search is the fallback.
Scoring
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.
Limitations
Papers without a DOI can't be verified. Some real papers, such as conference proceedings that never received a DOI, will come back
verified: false. This is deliberate: the server only vouches for citations it can link to.Speed depends on the slowest database. Most lookups take one to a few seconds; title/author searches wait for all 8 databases.
Semantic Scholar rate-limits requests without an API key: they share one global anonymous quota that is often exhausted. Set
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, itsRATE_LIMITEDerror is reported and the other databases are still used.DBLP was removed in 7.0.0. dblp.org serves a bot-check page to API clients instead of JSON. Computer-science papers with DOIs are still found through CrossRef and OpenAlex.
Each database is asked for 3ร
limitresults and trimmed back tolimitafter dropping records without a DOI, so a few DOI-less top hits don't empty a source.
Tools
All tools are read-only (readOnlyHint: true, destructiveHint: false, idempotentHint: true).
verifyCitation
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 name
Returns JSON with:
verified: true/falseIf verified:
confidence(high/medium),source,doi,doiUrl,title,authors,year,journal,abstractFromArticle,messageIf not verified: a warning
message, pluspossibleMatches(each with a DOI) when there were near misses, anderrors(database,code,message) for any database that failed, since it may have held the match
Example 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"
}batchVerifyCitations
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? }objects
Returns: 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.
findVerifiedPapers
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 year
Returns: 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" })Resources and prompt
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 DOI
Installation
Add 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" }
}Alternative: Global Install
npm install -g github:tfscharff/doi-mcpThen use this config:
{
"mcpServers": {
"doi-mcp": {
"command": "doi-mcp"
}
}
}Alternative: Clone Locally
git clone https://github.com/tfscharff/doi-mcp.git
cd doi-mcp
npm install
npm run buildConfig for local install:
{
"mcpServers": {
"doi-mcp": {
"command": "node",
"args": ["/absolute/path/to/doi-mcp/dist/index.js"]
}
}
}Troubleshooting
Server not connecting
Check Node.js is installed:
node --version(requires v18+)Check Claude Desktop logs:
Windows:
%APPDATA%\Claude\logs\macOS:
~/Library/Logs/Claude/Linux:
~/.config/Claude/logs/
npx command fails
npm cache clean --forceTesting locally
npx @modelcontextprotocol/inspector node dist/index.jsReleases
Every change is published as a GitHub release following Semantic Versioning:
Major (5.0.0 โ 6.0.0): a change in what gets verified or returned, or in the tools' inputs and outputs
Minor (5.0.0 โ 5.1.0): new features, such as a new database or tool
Patch (5.0.0 โ 5.0.1): fixes, docs, and maintenance
See CHANGELOG.md for what changed in each version.
Development
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 reportTests mock all network calls; nothing hits the live APIs.
Releasing
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.mdThe 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.
Architecture
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:
Create
src/databases/newdb.tswithconfig,search(), andnormalize()Import and add to
src/databases/index.tsAdd it to the database lists in the tool descriptions in
src/server.tsAdd tests in
tests/databases/newdb.test.ts
Example Usage
Before 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 existAfter 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 DOIVerification 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."Database Coverage
All databases are queried in parallel:
General Databases
CrossRef: 150+ million scholarly publications across all disciplines
OpenAlex: 250+ million scholarly works across all disciplines
Semantic Scholar: 200+ million papers with AI-powered search
Specialized Databases
PubMed: 35+ million biomedical and life sciences publications
zbMATH: 4+ million mathematics publications
ERIC: 1.7+ million education research publications
HAL: 4.4+ million French/European scholarly documents (2.5M English)
INSPIRE-HEP: 1.7+ million high-energy physics publications
Total Coverage
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.
License
MIT
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
Related
API Documentation
Resources
Available Tools
3 toolsbatchVerifyCitationsARead-onlyIdempotent
Verify multiple citations in a single call. More efficient than calling verifyCitation multiple times. Returns verification status for each citation.
Inputs: citations (required).
findVerifiedPapersARead-onlyIdempotent
Search multiple academic databases (CrossRef, OpenAlex, PubMed, zbMATH, ERIC, HAL, INSPIRE-HEP, Semantic Scholar) for papers and return only verified, real citations with DOIs.
Inputs: query (required), limit, source, yearTo, +1 more.
verifyCitationARead-onlyIdempotent
CRITICAL: Use this to verify ANY academic citation before mentioning it. Checks multiple databases (CrossRef, OpenAlex, PubMed, zbMATH, ERIC, HAL, INSPIRE-HEP, Semantic Scholar) if a paper exists. Only papers with a DOI count as verified; every verified result includes a doiUrl.
Inputs: doi, year, title, authors, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogโฆ
TDQS
Scored across 3 tools
verifyCitation (single) vs batchVerifyCitations (multiple) are clearly distinguished by cardinality, and findVerifiedPapers is discovery rather than verification. Minor overlap in that findVerifiedPapers also returns verified results, but the input intent (search query vs supplied citation) keeps them separable.
All camelCase with a verb-leading noun phrase (verifyCitation, batchVerifyCitations, findVerifiedPapers), which is readable and predictable. The 'batchVerify' compound verb is a slight deviation from the plain verb_noun pattern but is intuitive.
Three tools is lean but justified: each maps to a distinct workflow (single verify, bulk verify, discover-and-verify). Nothing redundant, though the surface is small enough that it sits near the lower bound.
The set covers the core lifecycle: verify one, verify many, and search for verified papers with DOI URLs. It is missing explicit DOI-based lookup or citation formatting/normalization, but for a verification-focused server the main workflows are covered.
Maintenance
Related MCP Connectors
AI research grounded in 300M scientific works โ every citation a verifiable DOI.
Checks AI-written references against Crossref, PubMed and OpenAlex. Formats citations, PRISMA.
Catch AI-fabricated citations (real DOI + fake title). Retraction, open-access, 10,000+ CSL styles.
Real-time fact-check, citation verification, and source-freshness for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceVerifies citations in reference lists by checking DOIs against public registries to catch AI-hallucinated or mismatched citations.MIT

CiteStamp MCP serverofficial
AlicenseNot gradedqualityBmaintenanceGround citations before your agent emits them by checking references against public scholarly registries and flagging hallucinated or retracted ones.MIT- FlicenseNot gradedqualityDmaintenanceFabrication-free, DOI-backed citations for AI content and agents, using openAlex public-domain data with resolvable DOIs. Includes an API and planned MCP server for agent-native citation retrieval.-

SciWeave MCP Serverofficial
FlicenseNot gradedqualityDmaintenanceGround Claude, ChatGPT, Cursor, and Windsurf in 300M scientific works โ every citation a verifiable DOI.-