@cyanheads/orcid-mcp-server
Search and retrieve researcher profiles, works, affiliations, funding, and peer review records from the ORCID registry.
Public Hosted Server: https://orcid.caseyjhand.com/mcp
Overview
Researcher identity data from the ORCID registry. Search and disambiguate authors, build a researcher dossier from profile, works, affiliations, funding, and peer review records, and chain external identifiers to Crossref, PubMed, or arXiv.
Tools
Tool | Description |
| Search the ORCID registry using structured field params (name, affiliation, keyword, ROR ID, DOI, PMID, grant number) |
| Fetch a researcher's public profile — name, other names, biography, keywords, researcher URLs, external identifiers |
| Retrieve works (publications, datasets, software, preprints) for a researcher, filtered by work type and publication year, paginated |
| Accept up to 1,000 put-codes, fetch the first 100 distinct works, and return deferred codes for continuation |
| Fetch affiliation records: employment, education, memberships, and more |
| List grouped funding summaries or select one award's deposited description, amount, and source |
| Fetch peer review activity: convening organizations, reviewer role, review type |
| List research resources — compute allocations, equipment access, lab facilities |
| Disambiguate an ambiguous author name to a ranked list of verified ORCID iD candidates |
Resources
Resource | Description |
| Researcher profile (person section) — name, other names, bio, keywords, external IDs |
| Works list for a researcher — the first 25 plus the total count |
All resource data is also reachable via tools. Use resources when injecting stable researcher context into a prompt; use tools when filtering or processing results is needed.
The server also publishes an agent skill, orcid-guide (skill://orcid-guide/SKILL.md, source in skills/orcid-guide/): identity-confirmation gates, identifier chains between the tools, and raw Solr field syntax.
Related MCP server: OSIRIS MCP
Capability reference
orcid_search_researchers tool
Structured params —
given_name,family_name,affiliation,keyword,ror_id,doi,pmid,grant_number— AND together automatically;queryadds raw Solr syntax — sent as written when it is the only field, otherwise ANDed as one parenthesized group so a top-levelORkeeps its alternatives (an exclusion-only query such as-keyword:xis ANDed ungrouped, since ORCID matches nothing for a group of only exclusions)At least one param must be non-blank — an empty or whitespace-only search is rejected rather than run against the whole registry
given_namephrase-matches, except that a value of only initials (J.,J. A.) matches given names starting with each letterdoiandpmidmap todoi-self/pmid-selffield queries — finds researchers who linked that specific work to their ORCID record. URL and label forms (https://doi.org/…,doi:…,https://pubmed.ncbi.nlm.nih.gov/…/,PMID:…) are accepted and reduced to the bare identifier, preserving its case. Nonblank values must contain a complete DOI (10.followed by digits,/, and a non-whitespace suffix) or numeric PMID; malformed and prefix-only values fail before a request. Omitted or genuinely blank fields remain unsetror_idtakes a ROR ID bare (00f54p054) or as aror.orgURL (https://ror.org/…,ror.org/…, awww.host, a trailing slash), in either letter case, and is reduced to thehttps://ror.org/<lowercase id>form ORCID indexes; a value that is not a ROR ID, or whose check digits do not match, is rejected before any search runsgrant_numberphrase-matches the grant numbers on researchers' funding items, case-insensitively, over the parts between separators such as hyphens and slashes —5F31MH010500also matches5F31MH010500-03, but a number cut mid-part matches nothing — pair withorcid_get_fundingto inspect each matchrows: results per page, default 20; a larger value (up to 10,000) is clamped to 1,000, the most ORCID serves per request, and a notice names both sizes on both surfaces.start: 0–10,000 offset pagination (the ORCID Public API's ceiling for unauthenticated requests)A page returns
rowsresults, fewer only at the end of the matches;nextStartisstartplus the number returned while matches remainReturns expanded-search results with inline name and institution data — no follow-up profile fetch needed for basic discovery
Use for precise field-anchored lookups; use
orcid_resolve_researcherfor ambiguous names needing ranked disambiguation
orcid_get_profile tool
Accepts a bare ORCID iD (
0000-0001-2345-6789) or an orcid.org URI (https://orcid.org/…,orcid.org/…, awww.host, a trailing slash); a lowercasexcheck digit is canonicalized toX. Every tool that takesorcid_idaccepts the same forms; theorcid://researcher/{orcid_id}/…resources take the bare iDA deprecated iD — one ORCID merged into another account — resolves to the primary record on every record tool and both resources, and
orcidId/orcidUrireport the primary iD; on the tools,selfAssertedis judged against it and anoticenames both iDsReturns name, other names (former names, transliterations, initialed forms), biography, keywords, researcher URLs, external identifiers (Scopus Author ID, ResearcherID, Loop, etc.), emails, and country codes — all in one response
Only publicly visible fields are returned; researchers control per-field visibility. A
noticenames every section with no public data (e.g. "no public email addresses or countries"), since an empty section can be private rather than emptyEntry point for building a researcher dossier before fetching works or affiliations
orcid_get_works tool
work_typeskeeps works of the listed types (ORCID's 58-value vocabulary, e.g.journal-article,preprint,data-set; any listed type matches, an empty list filters nothing);year_fromandyear_tokeep works published in that inclusive range, read from the first four digits ofpublicationDate. Under a year bound, undated works drop out and a notice counts them. The filters run over the whole record before paging, at no extra upstream cost:matchedCountcounts the matches,workCountthe whole record, andappliedFiltersechoes what was appliedReturns 25 matching works by default;
limitis clamped to 1,000 (accepted up to 10,000) with a notice naming both sizes. Page withoffsetand the returnednextOffset; a page holdslimitworks, fewer only at the end, andtruncatedsays more remain. An offset past the matches returns a notice saying so; no match returns a notice naming the filters andworkCountSet
include_external_idstofalseto drop DOI/PMID/arXiv/ISBN identifier lists for a lighter payloadOne record per ORCID work group; its identifiers are the group's — the preferred version's own, then any that another source holds, such as a PMID beside a Crossref DOI
External identifiers are pre-formatted for chaining to Crossref, PubMed, or arXiv
Summaries only — pass a work's
putCodetoorcid_get_work_detailfor abstracts and contributor listsEach work lists its
sources— the researcher, or member organizations such as Crossref or a university system — withselfAssertedmarking what the researcher asserted; an empty list does not mean no publications
orcid_get_work_detail tool
put_codes: 1–1,000 raw codes per call (fromorcid_get_works), deduplicated in first-occurrence order before fetching the first 100 distinct codes in one request; every record ORCID returns for them comes back, and a notice names the input cap when appliedReturns abstract, contributors with CRediT roles, the record's external IDs, citation metadata (BibTeX or other deposited formats), journal title, and URL
A record listing more than 100 contributors keeps the first 100 plus the researcher's own entries, matched by ORCID iD, with
contributorCountandcontributorsTruncatedmarking the cut; a citation over 8,192 bytes is left out and flaggedcitationOmitted, so a large-collaboration paper costs about what its other fields do. Even so, 100 large-collaboration records run past 1 MB: size batches to what the step needsEach put-code is one source's version of the work, so its identifiers can be fewer than
orcid_get_workslists for the work group;sourcesnames that sourcePer-put-code failures (not found or inaccessible) arrive as
errorsentries — the rest of the batch still resolvesdeferredPutCodeslists, in request order, the distinct codes beyond the input cap and any ORCID's answer left out; pass it asput_codesin another call. Notices distinguish the two causesAn upstream rate limit surfaces as a
RateLimitederror carrying ORCID'sretryAfterwhen it sent one
orcid_get_affiliations tool
typesfilters which sections to return:employment,education,invited-positions,distinctions,memberships,qualifications,services, orall— default is employment + education; an explicit empty list is rejectedOne upstream call regardless of how many types are requested
Returns organization name, disambiguated ID (ROR/GRID/Ringgold), department, role, and date range per record
Each record's
sourcesnames who added it — the researcher, or a member organization such as a university research information system; an empty result does not mean no affiliation
orcid_get_funding tool
Without
put_code, returns the complete grouped funding list in one request withview: summary; each preferred summary exposes its optionalputCodeReturns funding type (grant, contract, award, salary-award), funder name and disambiguated ID (Crossref Funder ID/ROR), grant numbers, and funding period
One record per ORCID funding group, from its preferred version — a grant deposited twice counts once in
fundingCount; when the group's versions record distinct award periods, such as renewals under one grant number,periodslists eachSupply a summary
putCodeasput_codeforview: detail: fetches only that deposit, with its own source and optional description, URL, andamount: { value?, currency? }. Decimal text is preserved exactly; missing amounts and currencies stay absentThe deposited description arrives whole (ORCID caps it at 5,000 characters); the text surface represents it as a JSON string so original CRLF line endings survive
An unavailable selected deposit returns
funding_not_foundand denied public access returnsfunding_inaccessible; each error explains how to recoverFunding comes from the researcher or from member organizations (funders, institutions, search-and-link tools), and each record's
sourcesnames which; most researchers with real grants have no entries here, and absence does not imply no funding
orcid_get_peer_reviews tool
Pages the history in upstream order with
offset(default 0) andlimit(default 25; a larger value, up to 10,000, is clamped to 1,000 with a notice naming both sizes on both surfaces)reviewCountcounts returned reviews,limitof them, fewer only at the end;totalCountreports the full history. Continue withnextOffsetwhentruncatedis true. Empty and past-end pages retain the total with no continuation, and an offset past a non-empty history returns a notice saying soReturns reviewer role (
reviewer,editor,chair, etc.), review type, completion date, an ISSN-keyed group identifier, and the convening organization ORCID records per recordThe convening organization is often the service that imported the review (Publons, Clarivate) rather than the journal; ORCID returns no journal name, so the ISSN is the journal key and heads each review that has one
Reviews come from the researcher or from member organizations that import them, and each record's
sourcesnames which; coverage varies widely by researcher
orcid_get_research_resources tool
Covers compute allocations, equipment access, lab facilities, data resources, and clinical study registrations
A newer, sparsely populated ORCID section — most researchers have zero entries, and absence does not imply none exist
Entries are typically deposited by resource-allocation systems (e.g. ACCESS, XSEDE) rather than added by the researcher
Returns resource title, hosting organization (with disambiguated ID), external identifiers (often a portal URI), access period, and the
sourcesthat deposited itDefault
view: summarylists proposals;proposalHostsincludes every proposal host, whilehostOrganizationkeeps the first host for compatibilitySupply a proposal's
putCodeasput_codeforview: detail: each item carries its name, type, all operators inhosts, external identifiers, and URL; proposal provenance stays on the resource recordDetail pages return
item_limititems fromitem_offset:item_offsetdefaults to 0,item_limitto 25, and a largeritem_limitreturns at most 100 (accepted maximum 10,000); both requireput_code.itemCount,returnedItemCount,itemOffset,itemsTruncated, andnextItemOffsetdescribe the page; top-leveltruncatedmirrorsitemsTruncated, anditemLimitNoticediscloses a reduced limit on both surfacesEach page repeats the proposal metadata; resume at
nextItemOffsetwith the sameput_code. Empty and past-end pages have no continuation
orcid_resolve_researcher tool
Returns ranked candidates (
rowsdefault 5; a larger value, up to 10,000, returns at most 20 at every search stage) with transparent disambiguation signals: name match type (exact/partial/other-name/none), institution overlap flag, and anchor type (doi/pmid/none). A notice reports requested and effective sizes when capped, alongside empty-result guidanceName and institution comparisons are case- and accent-insensitive —
José BaselgaandJose Baselgaclassify the same candidate identicallyWhen
doiorpmidis provided (bare or as a URL), usesdoi-selforpmid-selfas an anchor — researchers who have linked that work to their ORCID record are near-deterministic matchesAccepts a full name (
Jennifer Doudna), a byline with initials (J. Doudna,Jennifer A. Doudna), orFamily, Given(Doudna, Jennifer, read asJennifer Doudna); an initial counts toward apartialmatch when the candidate's first given name starts with itSearches the exact name phrase first, so a name that matches as written sends one query. Each later stage runs only when every earlier one found nothing: the byline form of any initials with the affiliation, then the phrase and the byline without it, then the other names listed on ORCID records, then each supplied anchor alone
No synthetic scores — raw signal fields only, so callers can apply their own ranking logic
orcid://researcher/{orcid_id}/profile resource
Returns name, other names, biography, keywords, researcher URLs, and external identifiers as
application/json{orcid_id}is the bare iD, with anXorxcheck digit — a URI segment cannot carry thehttps://orcid.org/formFails with a typed
data.reasonand a recovery hint, like the tools:invalid_orcid_idfor a checksum-invalid iD (rejected locally, before any upstream call),profile_not_foundfor an iD ORCID does not know or a record with no public namePrefer the
orcid_get_profiletool when the response needs to flow into conditional logic
orcid://researcher/{orcid_id}/works resource
Returns the first 25 works plus
workCount(the total available) asapplication/json{orcid_id}is the bare iD, with anXorxcheck digitFails with
invalid_orcid_id(checksum, before any upstream call) orprofile_not_found(unknown iD,data.orcidIdincluded), each with a recovery hintNo cursor pagination on this resource — use the
orcid_get_workstool to page the full list or filter resultsDOIs and PMIDs in the response are ready for Crossref or PubMed chaining
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.
ORCID-specific:
ORCID Public API v3.0 (
https://pub.orcid.org/v3.0) — no API key required for public read endpointsexpanded-searchas the primary search backend — returns ORCID iD, name, and institution data inline, eliminating N+1 profile fetchesSingle
/activitiescall for affiliation queries, filtered client-side — eliminates up to 7 parallel upstream calls vs. per-section fetchingExternal identifiers (DOIs, PMIDs, arXiv IDs) surfaced in works responses in formats ready for cross-server chaining to Crossref, PubMed, or arXiv
Inline markup that depositing systems leave in work titles, abstracts, and funding and research-resource titles (
<i>,<sup>,<h4>) is stripped to plain text; the deposited citation is relayed verbatim
Agent-friendly output:
Provenance —
orcid_resolve_researcherreturns raw disambiguation signals (name match type, institution overlap, anchor type) instead of a synthetic confidence scoreWho asserted each item — every record from the six activity tools carries
sources: the person or member organization that added it (a university system, funder, Crossref, Web of Science) and whether the researcher asserted it (selfAsserted); grouped works and funding list every source in the groupTruncation awareness — pages are sized by count alone and a request over a tool's cap returns the cap with a notice;
orcid_search_researchersreportsnumFoundand atruncatedflag against the ORCID Public API's 10,000-offset ceiling, withnextStartto continue;orcid_get_worksreportsworkCount,matchedCount, andtruncatedagainst the requested page, andorcid_get_peer_reviewstotalCountandtruncated, each withnextOffsetto continue;orcid_get_research_resourcesdetail reportstruncatedwithnextItemOffsetMerged accounts — a deprecated ORCID iD is served from the primary record it was merged into, reported under the primary iD with a notice naming both, including on the three endpoints ORCID does not redirect (bulk work detail, research resources, allocation detail)
Partial failure isolation —
orcid_get_work_detailreturns per-put-code errors alongside successfully resolved works instead of failing the whole batch, and names any put-codes past the 100-code fetch cap or missing from ORCID's answerEmpty-result guidance —
orcid_get_works,orcid_get_affiliations,orcid_get_funding,orcid_get_peer_reviews, andorcid_get_research_resourcesreturn a notice when a result is empty, explaining that this may mean neither the researcher nor a member organization added entries, or that visibility settings hide them, rather than confirmed absence;orcid_get_profilenames each section with no public dataRecord text marked as data — in the text output, biographies and abstracts render as blockquotes, names, titles, and organization names are kept to one line, and a deposited citation sits in a code fence it cannot close, so text a researcher or depositing system wrote never reads as the server's own headings or labels;
structuredContentcarries every value verbatim
Getting started
Connect to the hosted instance, no install:
claude mcp add --transport http orcid-mcp-server https://orcid.caseyjhand.com/mcpOr run it locally:
claude mcp add orcid-mcp-server -- npx -y @cyanheads/orcid-mcp-serverFor other clients, add this to the MCP config file:
{
"mcpServers": {
"orcid-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/orcid-mcp-server"]
}
}
}No API key is required: the ORCID Public API is open for public read access, for non-commercial use under ORCID Public API ToS §2. For Docker or a source build, see Running the server.
Configuration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
Variable | Description | Default |
| Override the ORCID API base URL. Useful for pointing at the sandbox ( |
|
| Transport: |
|
| HTTP server port |
|
| HTTP endpoint path |
|
| HTTP session mode: |
|
| Public origin for TLS-terminating reverse-proxy deployments | none |
| Authentication: |
|
| Log level ( |
|
| Opt-in Bun-only forced-GC pressure loop (ms). Try |
|
| Directory for log files (Node.js only) |
|
| Storage backend: |
|
| Enable OpenTelemetry |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
Clone and install:
git clone https://github.com/cyanheads/orcid-mcp-server.git cd orcid-mcp-server && bun install cp .env.example .env # no required variablesBuild and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker run --rm -p 3010:3010 ghcr.io/cyanheads/orcid-mcp-server:latestThe image defaults to HTTP transport, stateless session mode, and logs to /var/log/orcid-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/orcid-mcp-server:latest"]. To build locally, docker build -t orcid-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| ORCID Public API v3.0 service layer — search, record section fetchers, retry/backoff. |
| Agent skill published over MCP and in the npm package, Docker image, and |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources in the
createApp()arraysWrap ORCID API calls: validate raw response → 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 testLicense
Apache-2.0 — see LICENSE for details.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Search people and companies, enrich profiles, and find email and phone over MCP.
Search NPPES providers and resolve NUCC specialty codes via MCP over STDIO or Streamable HTTP.
Search and compare attributed recipe records through a public read-only remote MCP endpoint.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables searching Figshare research articles, datasets, papers, and posters through the MCP protocol.160 npmMIT

OSIRIS MCPofficial
AlicenseAqualityBmaintenanceEnables controlled, read-only access to research information in OSIRIS through typed, auditable MCP tools for searching activities, people, experts, and organizational metadata.12AGPL 3.0- AlicenseNot gradedqualityBmaintenanceEnables searching DataCite datasets and software, fetching DOI metadata, tracing relations, and formatting citations via MCP, supporting stdio or Streamable HTTP.341 npm1Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables searching ClinicalTrials.gov studies, retrieving detailed study records and posted results, and matching patient profiles to candidate recruiting trials through MCP over STDIO or Streamable HTTP.2,484 npmApache 2.0