About datacite-mcp-server
An MCP server for searching DataCite research outputs and retrieving DOI metadata, relationship graphs, repository records, and citations. It covers datasets, software, and other deposited works, with no API key required.
Key features
- 01Search works with text and structured filters
- 02Retrieve full DOI metadata
- 03Trace DOI relations and citation links
- 04Search repository accounts and fields
- 05Render citations in styles and machine formats
- 06Look up supported vocabularies and coverage
Use cases
- 01Find datasets or software by creator, field, or repository
- 02Inspect related versions, supplements, and citations for a DOI
- 03Format a DOI citation for a paper or reference manager
- 04Check repository details before searching its works
MCP support
Exposes six DataCite search, metadata, relation, repository, citation, and reference tools to MCP clients. Supports STDIO and Streamable HTTP transports.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://datacite.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-datacite https://datacite.caseyjhand.com/mcp{"mcpServers":{"cyanheads-datacite":{"type":"http","url":"https://datacite.caseyjhand.com/mcp"}}}Open in Cursor{"servers":{"cyanheads-datacite":{"type":"http","url":"https://datacite.caseyjhand.com/mcp"}}}Open in VS Code{"mcpServers":{"cyanheads-datacite":{"type":"http","url":"https://datacite.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-datacite":{"serverUrl":"https://datacite.caseyjhand.com/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
6| Parameter | Type | Required | Description |
|---|---|---|---|
| page | integer | No | Ranked page number, 1 when omitted. page × limit may not exceed 10,000; not with cursor. |
| sort | enum | No | relevance, newest, oldest, recently_updated, most_cited, most_viewed, or most_downloaded. Omitted: relevance when text or query is set, else newest. Not with cursor.relevance | newest | oldest | recently_updated | most_cited | most_viewed | most_downloaded |
| text | string | No | Plain words and phrases, searched literally: every query-syntax character is escaped, so "Climate change: impacts" works and text can never cause a syntax error. Terms are ANDed. |
| limit | integer | No | Rows per page, 1–100. |
| place | string | No | A geographic place phrase, matched against deposited place names. |
| query | string | No | OpenSearch query-string syntax — field paths (titles.title:"…", creators.name:…, relatedIdentifiers.relationType:…), AND/OR/NOT, ranges, wildcards. Field paths: datacite_list_reference topic query_syntax. ANDed with text and the filters. |
| cursor | string | No | Cursor walk over the full result set in registration order: "*" to start, then the nextCursor of the previous page, unchanged, with the same query and filters. Not with page or sort. |
| funder | string | No | A funder ROR ID, a Crossref Funder ID (10.13039/100000001, its doi.org URL, or the bare digits), or a funder name. |
| creator | string | No | A creator ORCID iD (0000-0002-1825-0097, 16 digits, or an orcid.org URL; checksum verified) or a name — every name token must appear in one creator field. |
| subject | string | No | A subject phrase, matched case-insensitively against subject terms. |
| language | string | No | ISO 639-1 language code of the work, any case (en, de). |
| licenses | array | No | The work's own license ids (any match), SPDX-style: cc-by-4.0, cc0-1.0, mit. Lowercased, then matched exactly; common ids: datacite_list_reference topic licenses. |
| affiliation | string | No | A ROR ID (021nxhr62 or a ror.org URL) — matches creator and contributor affiliations — or an affiliation name phrase. |
| provider_ids | array | No | Provider ids (any match), e.g. dryad — the providerId datacite_search_repositories returns. Any case. |
| published_to | integer | No | Latest publication year (inclusive). Alone, the range is open-ended. |
| min_citations | integer | No | Only works DataCite records at least this many citations for. |
| include_facets | boolean | No | Add top facet counts (resource types, years, repositories, providers, affiliations, fields of science, licenses). Adds 2–8 s. |
| published_from | integer | No | Earliest publication year (inclusive). Alone, the range is open-ended. |
| repository_ids | array | No | Repository ids (any match), shaped provider.repository — e.g. dryad.dryad or cern.zenodo — as datacite_search_repositories returns them in repositoryId. Any case. |
| resource_types | array | No | resourceTypeGeneral values (any match): dataset, software, computational-notebook, workflow, model, physical-object, … PascalCase accepted. Full list: datacite_list_reference topic resource_types. |
| fields_of_science | array | No | OECD Fields of Science ids or labels (any match), e.g. computer_and_information_sciences or "Earth and related environmental sciences". List: datacite_list_reference topic fields_of_science. |
| affiliation_country | string | No | ISO 3166-1 alpha-2 country of a creator or contributor affiliation, any case (DE, us). Alpha-3 codes and names are rejected. |
| include_child_funders | boolean | No | Also match the ROR funder's child organizations. Only with a ROR funder. |
Details
From the project README@cyanheads/datacite-mcp-server
Search DataCite datasets and software, fetch DOI metadata, trace relations, format citations via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://datacite.caseyjhand.com/mcp
Overview
DOI metadata from DataCite for datasets, software, samples, workflows, and other research outputs that repositories deposit worldwide. Search it, open a record in full, trace a DOI's relations (versions, parts, supplements, citations), find the repositories that publish in a field, and format citations. No API key required.
Tools
| Tool | Description |
|---|---|
datacite_search_works | Search works by plain text or query syntax plus structured filters, in ranked pages or a full cursor walk, with optional facet counts |
datacite_get_work | Fetch the full deposited metadata for one DOI, or learn which registration agency holds a DOI DataCite doesn't |
datacite_trace_relations | Map the relation graph around any DOI — versions, parts, supplements, derivations, citations — with each edge's source |
datacite_search_repositories | Find repository accounts by text, field of science, type, certificate, software, or provider, and get the repositoryId work search filters on |
datacite_get_citation | Render a DOI as a formatted citation in a CSL style and locale, or as BibTeX, RIS, CSL JSON, and other machine formats |
datacite_list_reference | Look up the vocabularies, identifier forms, and coverage rules the other tools accept, offline |
Capability reference
datacite_search_works tool
text(literal words, with angle brackets removed; nonblank text that leaves no searchable clause fails asinvalid_text) orquery(OpenSearch query syntax), ANDed with filters:resource_types,creator(ORCID iD or name),affiliation(ROR ID or name),affiliation_country,funder(ROR ID, Crossref Funder ID, or name;include_child_funderswith a ROR funder),subject,fields_of_science,repository_ids,provider_ids,licenses,language,place,published_from/published_to, andmin_citations; list filters take up to 10 values, any of which matchlimit1–10,000 (default 20), applied at most 100 with a notice; rankedpages reach the first 10,000 matches undersort(relevance,newest,oldest,recently_updated,most_cited,most_viewed,most_downloaded; defaultrelevancewithtextorquery, elsenewest), whilecursor: "*"walks the whole result set in registration order throughnextCursorand takes neitherpagenorsort. A ranked ceiling stop is distinguished from the last page- Crossref Funder IDs resolve through one exact ROR FundRef mapping before searching
funded-by; an unavailable, incomplete, or ambiguous mapping keeps literal identifier matching and discloses reduced coverage. The cached, paced lookup takes at most five seconds without retry. A cursor walk keeps its initial resolved or literal filter on every continuation without another ROR lookup, including across server restarts.include_child_fundersstill requires an explicitly supplied ROR - License ids are trimmed and lowercased, preserving internal spaces (
cc0 1.0differs fromcc0-1.0); reuse the licenses facet ids exactly.queryalso supports deposition timestamps, e.g.created:[2026-10-16 TO *],updated, andregistered include_facetsadds top counts for resource types, years, repositories, providers, affiliations, fields of science, and licenses (2–8 s slower); every response reportstotalCount,effectiveQuery,sortApplied, andappliedFilters
datacite_get_work tool
- One
doi, in any case: bare, with adoi:orinfo:doi/prefix, as a doi.org URL, or%2F-encoded - Titles, creators and contributors with ORCID iDs and ROR affiliations, dates, subjects, descriptions, funding, geolocations, rights, related identifiers and items, repository and provider, and
counts(citations, references, versions, parts, views, downloads); long lists are capped and their full sizes reported intruncatedListsandrelatedIdentifierCounts - Page one capped
listwith a zero-basedoffset(default 0):creators,contributors,relatedIdentifiers,subjects, andfundingReferencesreturn up to 100 entries,relatedItems25, andgeoLocations50. Offsets index valid mapped entries in deposit order.listPagereportslist,offset,total, andnextOffsetwhile entries remain; other metadata keeps its normal caps. Default truncation notices give exact continuation inputs. An offset requires a list; past-end pages are empty - Titles and search snippets are plain text, with recognized formatting tags removed and entities decoded once before snippet truncation. Structured descriptions keep their deposited text; rendered descriptions preserve paragraph and line boundaries
- Geolocations preserve points, boxes, ordered polygon vertices, and optional polygon interior points. Incomplete polygons are omitted with a notice; valid sibling geometry remains
- A DOI DataCite holds no public record for returns
found: falsewithmissReason(other_agency,does_not_exist,not_public,unclassified), theregistrationAgencywhen known, andguidance
datacite_trace_relations tool
- Any agency's
doi: a DataCite dataset or software DOI, or a journal article's DOI to find the DataCite data and software it cites or that cite, supplement, or derive from it depth1 (default) or 2 — the second hop expands at most 10 DataCite neighbours and runs only when the first hop leavesmax_nodesroom;max_nodes1–10,000 (default 50, root included), applied at most 100 with a notice, fills with own-metadata targets, then records pointing at the root, then Event Data endpoints, then the second hop;relation_typeskeeps only the listed relation types, read from the traced DOI's side (omitted: all);include_event_data(defaulttrue) adds Event Data citation links- Edges keep
relationTypeexactly as asserted and list theirsources(metadata,reverse_metadata,event_data);coveragestates how much of each source was read (up to 100 reverse records per hop, only the first 10 when those are large, and up to 100 events per call), androotCountscarries DataCite's own counts for comparison. An absent edge is not evidence that no relationship exists - Reverse lookups inspect both
relatedIdentifiersand identifiedrelatedItems, verify each assertion's target and type, and merge identical edges event_offset(0–9,999, absolute and zero-based) selects Event-Data-only tracing, including when set to 0: metadata edges and depth-2 expansion are skipped. Continue withcoverage.eventData.nextEventOffsetand the same DOI and filters. Each call reads one upstream page and stops before an eligible endpoint that cannot fitmax_nodes; root-only calls explain how to raise the cap. Coverage distinguishes exhaustion, a blocked classification lookup, unavailable/skipped reads, and the upstream 10,000-result ceiling. Upstream ordering can change between calls; continuations are not snapshots
datacite_search_repositories tool
querytext over names and descriptions, plusfield_of_science,repository_types,certificates,software,client_type, andprovider_id; orrepository_idsalone (up to 1,000 inputs) to look up the first 25 distinct normalized ids in input order. A notice names unqueried ids; missing-id notices cover queried ids onlylimit1–10,000 (default 20), applied at most 100 with a notice, withpage; name-ordered rows carry therepositoryIdthatdatacite_search_workstakes inrepository_ids, plusproviderId, types, certificates, software, subjects, homepage, and re3data link- Search responses echo the composed
effectiveQuery(*without query clauses), including empty pages; ID lookups reportappliedFilters.repository_idswithout a query echo
datacite_get_citation tool
format:text(default),csl_json,bibtex,ris,datacite_json,datacite_xml,schema_org,codemeta, orjats- For
textonly:styletakes a CSL style id (defaultapa; verified ids underdatacite_list_referencetopiccitation_styles), and one DataCite would silently render as APA fails asunsupported_style;localetakes one of the 61 CSL locales DataCite renders (en-GB,de-DE,fr-FR, …) or a bare language code that expands to its primary dialect (de→de-DE), defaulten-US(list: topiccitation_locales) textreturns the citation as plain text incitationand the upstream markup incitationHtml; text payloads over 100,000 UTF-16 code units are cut without splitting a surrogate pair. Machine formats return complete payloads inline up to that cap; larger documents omitcitationand returndownloadUrlfor the full document andtotalCharacters, withtruncated: true,shown: 0, andcap: 100000. A DOI DataCite doesn't hold returnsfound: falseas indatacite_get_work; a format DataCite can't render for that DOI fails asformat_unavailable
datacite_list_reference tool
topic:resource_types,relation_types,identifier_types,date_types,contributor_types,fields_of_science,licenses,repository_types,certificates,software_platforms,client_types,sort_orders,query_syntax,citation_formats,citation_styles,citation_locales,identifier_formats, orcoverage- Returns
entries(value,label,group,inverse) and usagenotes; makes no upstream request
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
The published datacite-guide skill covers attribution, identifier resolution, relation evidence, and complete inventories. It ships with the package and plugins and is available through the MCP Skills extension.
DataCite-specific:
- Keyless and read-only: the DataCite REST API (
/dois,/repositories, Event Data at/events, and DOI content negotiation for citations), plus the doi.org registration-agency lookup for DOIs DataCite doesn't hold - Shared request budget: one paced request queue, an in-process response cache, and a 45 s deadline per tool call; a spent budget fails as
rate_limitedwith the wait in seconds.DATACITE_CONTACT_EMAILmoves requests to DataCite's identified tier, 1,000 requests per 5 minutes per IP instead of 500 - Forgiving identifiers: DOIs in any case, bare or prefixed or as doi.org URLs; ORCID iDs with their checksum verified; ROR IDs and Crossref Funder IDs bare or as URLs; vocabulary values in any case, with hyphens, underscores, or spaces
- DataCite DOI metadata is waived under CC0 1.0; the waiver covers the deposited metadata only, not the datasets, software, or papers it describes.
datacite_get_workreportsmetadataLicenseseparately from the work's ownrights
Agent-friendly output:
- Provenance on every search:
effectiveQuery,appliedFiltersas sent upstream, the sort or order applied, andtotalCount; trace edges name theirsources, andcoveragesays how much of each source was read - Typed misses instead of errors: a DOI DataCite doesn't hold comes back
found: falsewith amissReason, the agency that holds it when known, and the next step - Disclosed limits: capped lists report their full counts, and notices explain zero hits, the 10,000-match paging ceiling, an unexpanded second hop, and citations the returned edges don't account for
- In the text output, depositor-supplied text (titles, descriptions, names) is blockquoted or flattened and machine payloads are fenced, so deposited content can't pose as structure. Titles and snippets are normalized on both surfaces; structured descriptions and other deposited fields retain their original text
Getting started
Connect to the hosted instance, no install:
claude mcp add --transport http datacite-mcp-server https://datacite.caseyjhand.com/mcp
Every caller of the hosted instance shares one DataCite request budget of 800 requests per 5 minutes. For sustained use, run your own instance.
Or run it locally:
claude mcp add datacite-mcp-server -- npx -y @cyanheads/datacite-mcp-server
For other clients, add this to the MCP config file:
{
"mcpServers": {
"datacite-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/datacite-mcp-server"]
}
}
}
No API key is needed. Set the optional DATACITE_CONTACT_EMAIL to double DataCite's per-IP request allowance. For Docker or a source build, see Running the server.
Configuration
| Variable | Description | Default |
|---|---|---|
DATACITE_CONTACT_EMAIL | Contact email sent in the User-Agent as mailto:, never in a URL. Moves requests to DataCite's identified tier: 1,000 requests per 5 minutes per IP instead of 500. Validated as an email at startup. | none |
DATACITE_MAX_REQUESTS_PER_5MIN | Request budget per 5-minute window, an integer from 50 to 1000. Divide it across replicas that share one egress IP. | 800 with a contact email, 400 without |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of optional overrides.
Running the server
Requires Bun v1.4.0 or higher, or Node.js v24+. To build from source:
git clone https://github.com/cyanheads/datacite-mcp-server.git
cd datacite-mcp-server
bun install
cp .env.example .env
Set DATACITE_CONTACT_EMAIL in .env to use DataCite's identified tier.
Local development
-
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Docker
Run over stdio:
docker run -i --rm -e MCP_TRANSPORT_TYPE=stdio ghcr.io/cyanheads/datacite-mcp-server:latest
Or expose Streamable HTTP at http://localhost:3010/mcp:
docker run --rm -p 127.0.0.1:3010:3010 ghcr.io/cyanheads/datacite-mcp-server:latest
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers the six tools and sets the server instructions. |
skills/ | Published guidance for agents using the DataCite tools. |
src/mcp-server/tools | Tool definitions (*.tool.ts) and the input-schema, miss-guidance, and text-rendering helpers they share. |
src/services/datacite | DataCite REST client (/dois, /repositories, /events, content negotiation), query builder, identifier normalizers, record mappers, relation-graph builder, and citation style check. |
src/services/doi-ra | doi.org registration-agency lookup for DOIs DataCite holds no public record for. |
src/services/ror | Exact Crossref Funder ID to ROR lookup with literal-search fallback. |
src/services/http | Shared upstream pipeline — response cache, request pacer, retry, per-call deadline, rate-limit handling. |
src/services/reference | Static vocabularies behind datacite_list_reference and the input validators. |
src/config | Server-specific environment variable parsing and validation with Zod. |
tests/ | Vitest tests mirroring src/, with recorded DataCite and doi.org fixtures. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.