Connects to the public ORCID API to search researchers by name, affiliation, ROR ID, DOI, or PMID, then pull their profile metadata, publication lists, institutional affiliations, funding records, and peer review activity. The nine tools map directly to ORCID's REST endpoints: search returns expanded results with inline institution data, get_works returns summaries with put-codes and external IDs, and get_work_detail fetches abstracts and contributor lists when you need them. The resolve_researcher tool ranks disambiguation candidates by name match type and institutional overlap. Useful when you're building researcher dossiers, chaining identifiers across bibliographic servers, or need verified ORCID IDs before hitting Crossref or PubMed.
Search and retrieve researcher profiles, works, affiliations, funding, and peer review records from the ORCID registry via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://orcid.caseyjhand.com/mcp
Nine tools organized around three workflows — author disambiguation, researcher profiling, and cross-server identifier chaining:
| Tool | Description |
|---|---|
orcid_search_researchers | Search the ORCID registry using structured field params (name, affiliation, keyword, ROR ID, DOI, PMID). All params are ANDed into a Solr query against the expanded-search endpoint, returning ORCID iDs with inline name and institution data. |
orcid_get_profile | Fetch a researcher's public profile: name, biography, keywords, researcher URLs, and external identifiers (Scopus Author ID, ResearcherID, Loop, etc.). |
orcid_get_works | Retrieve works (publications, datasets, software, preprints) for a researcher. Returns summaries with put-codes, titles, types, dates, journal names, and external identifiers. Pass put-codes to orcid_get_work_detail for abstracts and full contributor lists. |
orcid_get_work_detail | Fetch full detail records for 1–100 works by their put-codes in a single bulk request (from orcid_get_works). Returns abstracts, all contributors with CRediT roles, complete external IDs, citation metadata, journal title, and URL. Per-record errors are surfaced without failing the whole call. |
orcid_get_affiliations | Fetch affiliation records for a researcher. Accepts a types list to filter which sections to return: employment, education, invited-positions, distinctions, memberships, qualifications, services, or all. |
orcid_get_funding | Fetch funding records: grants, contracts, awards, and salary awards, with funder names, grant numbers, and funding periods. |
orcid_get_peer_reviews | Fetch peer review activity: convening organizations, reviewer role, review type, completion dates, and ISSN-keyed group identifiers. |
orcid_get_research_resources | List research resources associated with a researcher — compute allocations, equipment access, lab facilities, and data resources. Sparsely populated; most researchers have no entries. |
orcid_resolve_researcher | Disambiguate an ambiguous author name to a verified ORCID iD. Returns a ranked list of up to 5 candidates with transparent signals: name match type, institution overlap, and whether a DOI or PMID anchor was used. |
orcid_search_researchersSearch the ORCID registry with structured field parameters mapped to Solr field queries.
given_name, family_name, affiliation, keyword, ror_id, doi, pmid — are ANDed into a Solr query automaticallydoi and pmid translate to doi-self and pmid-self field queries: "who has linked this work to their ORCID record?"query appends raw Solr to the generated clause for advanced useror_id values (full URLs like https://ror.org/00f54p054) are quoted internally to handle Solr's colon parsingorcid_resolve_researcher for ambiguous names needing ranked disambiguationorcid_get_profileFetch a researcher's public person section by ORCID iD.
0000-0001-2345-6789) or full URI formorcid_get_worksRetrieve the works list for a researcher.
orcid_get_work_detailFetch full detail records for 1–100 works in a single bulk request using the ORCID bulk works endpoint.
put_codes is an array of 1–100 put-codes from orcid_get_workserrors entries — the remaining works still resolveorcid_get_affiliationsFetch affiliation records by type, using a single /activities call filtered client-side.
types controls which sections to include: employment, education, invited-positions, distinctions, memberships, qualifications, services, or all['employment', 'education'] (the 90% case)/activities endpoint returns all sections at onceorcid_get_fundingFetch funding records for a researcher.
orcid_get_peer_reviewsFetch peer review activity for a researcher.
reviewer, editor, chair, etc.), review type, completion dates, and ISSN-keyed group identifiersorcid_get_research_resourcesList research resources associated with a researcher.
orcid_resolve_researcherDisambiguate an author name to a verified ORCID iD.
exact/partial/other-name), institution overlap flag, and anchor type (doi/pmid/none)doi or pmid is provided, uses doi-self or pmid-self as an anchor — researchers who have linked that work to their ORCID record are near-deterministic matches| Type | Name | Description |
|---|---|---|
| Resource | orcid://researcher/{orcid_id}/profile | Researcher profile (person section: name, bio, keywords, external IDs). Prefer the tool when the response needs to flow into conditional logic. |
| Resource | orcid://researcher/{orcid_id}/works | Works list for a researcher. DOIs and PMIDs in the response are ready for Crossref/PubMed chaining. |
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.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1ORCID-specific:
https://pub.orcid.org/v3.0/) — no API key required for public read endpointsexpanded-search as the primary search backend — returns ORCID iD, name, and institution data inline, eliminating N+1 profile fetches/activities call for affiliation queries, filtered client-side — eliminates up to 7 parallel upstream calls vs. per-section fetchingAgent-friendly output:
orcid_resolve_researcher — name match type, institution overlap, and anchor type are returned as raw fields, not a synthetic score, so agents can reason about match confidencenum_found so agents know when the 10,000-result public API cap was hit; funding and profile tools note when sections are empty due to researcher-controlled visibilityA public instance is available at https://orcid.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"orcid-mcp-server": {
"type": "streamable-http",
"url": "https://orcid.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file. No API key is required — the ORCID Public API is open for public read access.
{
"mcpServers": {
"orcid-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/orcid-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"orcid-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/orcid-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"orcid-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/orcid-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/orcid-mcp-server.git
cd orcid-mcp-server
bun install
cp .env.example .env
# edit .env if needed — no required vars
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
| Variable | Description | Default |
|---|---|---|
ORCID_API_BASE_URL | Override the ORCID API base URL. Useful for pointing at the sandbox (https://pub.sandbox.orcid.org/v3.0/). | https://pub.orcid.org/v3.0/ |
MCP_TRANSPORT_TYPE | Transport: stdio or http | stdio |
MCP_HTTP_PORT | HTTP server port | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path | /mcp |
MCP_PUBLIC_URL | Public origin for TLS-terminating reverse-proxy deployments | none |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.) | info |
MCP_GC_PRESSURE_INTERVAL_MS | Opt-in Bun-only forced-GC pressure loop (ms). Try 60000 if heap growth is observed under sustained HTTP load. | 0 (disabled) |
LOGS_DIR | Directory for log files (Node.js only) | <project-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.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run 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 build -t orcid-mcp-server .
docker run --rm -p 3010:3010 orcid-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/orcid-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and resources, inits services. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts). Seven tools across search, profile, works, affiliations, funding, peer reviews, and disambiguation. |
src/mcp-server/resources | Resource definitions (*.resource.ts). Profile and works resources. |
src/services/orcid | ORCID Public API v3.0 service layer — search, record section fetchers, retry/backoff. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagecreateApp() arraysIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.