protogrid

Search / io.github.cyanheads/crossref-mcp-server

crossref-mcp-server

R0· no sign-in

Resolve DOIs, search ~155M scholarly works, and fetch references via the Crossref REST API.

v0.4.2 · active · repository · descriptor JSON · versions

An agent can connect right now, no human step.Remote endpoint, no authentication, reachable on the last probe.
Quality86good
Trust94of 100
Uptime, 30 days99%
Latency p50174 ms

Connect

8 clients · secrets stay placeholders
{
  "mcpServers": {
    "crossref-mcp-server": {
      "type": "http",
      "url": "https://crossref.caseyjhand.com/mcp"
    }
  }
}
claude mcp add --transport http crossref-mcp-server https://crossref.caseyjhand.com/mcp
[mcp_servers.crossref-mcp-server]
url = "https://crossref.caseyjhand.com/mcp"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "crossref-mcp-server": {
      "type": "remote",
      "url": "https://crossref.caseyjhand.com/mcp",
      "enabled": true
    }
  }
}
{
  "mcpServers": {
    "crossref-mcp-server": {
      "type": "http",
      "url": "https://crossref.caseyjhand.com/mcp"
    }
  },
  "deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=crossref-mcp-server&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vY3Jvc3NyZWYuY2FzZXlqaGFuZC5jb20vbWNwIn0%3D"
}
{
  "servers": {
    "crossref-mcp-server": {
      "type": "http",
      "url": "https://crossref.caseyjhand.com/mcp"
    }
  }
}
{
  "mcpServers": {
    "crossref-mcp-server": {
      "httpUrl": "https://crossref.caseyjhand.com/mcp"
    }
  }
}
extensions:
  "crossref-mcp-server":
    enabled: true
    name: "crossref-mcp-server"
    type: streamable_http
    uri: "https://crossref.caseyjhand.com/mcp"
    timeout: 300

Quality 86 / 100good

protocol88 · weight 25
  • pass
    protocol.modernsupports 2026-07-28 (server/discover)
  • pass
    protocol.statelessanswers without a session
  • pass
    protocol.transportstreamable HTTP
  • warn
    protocol.list_ttltools/list declares ttlMs 0, so clients re-fetch it on every use
authorizationn/a · weight 15
  • n/a
    auth.prm, auth.as_metadata, auth.cimdno remote uses OAuth
  • n/a
    auth.secret_in_urlno templated URL
tool hygiene79 · weight 30
  • pass
    tools.descriptionsevery tool has a description
  • warn
    tools.description_length4 tools have descriptions over 1,024 characters, which crowds the context
  • pass
    tools.schemasevery tool has an object input schema
  • pass
    tools.annotations7 of 7 tools declare readOnlyHint or destructiveHint
  • fail
    tools.directory_hintsno tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: crossref_get_work (destructiveHint, openWorldHint); crossref_get_references (destructiveHint, openWorldHint); crossref_search_works (destructiveHint, idempotentHint); …
  • pass
    tools.token_costabout 4,672 tokens to load every tool
  • pass
    tools.api_dumptools are not a one-to-one API dump
stability100 · weight 15
  • pass
    stability.changes4 tool changes in 30 days
  • pass
    stability.rug_pullno tool changed its meaning under the same name
dependenciesn/a · weight 15

7 tools, about 4,672 tokens to load them all · tool set ff944c5c8158 · tools last changed 2026-09-24 · checked 2026-10-19 10:20 UTC

Tool changes

  • crossref_search_funderschangeddescription, input schema, output schema
    before

    Finds funders registered in the Crossref Funder Registry by name or funder DOI. Provide funder_doi for an exact single-funder lookup — the full DOI ("10.13039/100000001"), the bare registry ID ("100000001"), or either behind a doi: or https://doi.org/ prefix — or query for name-based search. Name-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of works funded by the matched funder; that list pages two ways. works_offset is the simple one and is capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole funded-works list: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the newest work — it cannot resume from an offset. This list also counts works funded by the funder's registry descendants, which a crossref_search_works filter on {"funder": "10.13039/<id>"} does not. Returns funder name, registry ID, country, and alternate names. The Funder Registry supersedes entries, and a deprecated one answers to the same names as its successor while carrying only a fraction of its works: such a record carries replacedBy with the superseding registry ID and the response carries a notice naming it. The replacement is never followed automatically — re-run with funder_doi set to that ID to get the current entry.

    after · 93% of words in common

    Finds funders registered in the Crossref Funder Registry by name or funder DOI. Provide funder_doi for an exact single-funder lookup — the full DOI ("10.13039/100000001"), the bare registry ID ("100000001"), or either behind a doi: or https://doi.org/ prefix — or query for name-based search. Name-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of the most recent works funded by the matched funder; that list pages two ways, in two orders. works_offset is the simple one: newest published first, capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole funded-works list, newest registered first — ordered by the date each DOI was registered with Crossref, since Crossref does not walk a publication-date sort by cursor: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the most recently registered work — it cannot resume from an offset. This list also counts works funded by the funder's registry descendants, which a crossref_search_works filter on {"funder": "10.13039/<id>"} does not. Returns funder name, registry ID, country, and alternate names. The Funder Registry supersedes entries, and a deprecated one answers to the same names as its successor while carrying only a fraction of its works: such a record carries replacedBy with the superseding registry ID and the response carries a notice naming it. The replacement is never followed automatically — re-run with funder_doi set to that ID to get the current entry.

  • crossref_search_journalschangeddescription, input schema, output schema
    before

    Finds Crossref journal records by ISSN or title query. Provide issn for an exact single-journal lookup, or query for title-based search returning up to rows results. Title-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of the matched journal's most recent works by publication date; that list pages two ways. works_offset is the simple one and is capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole works list: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the newest work — it cannot resume from an offset. Returns journal metadata: title, publisher, ISSN-L, subject areas, and total DOI count.

    after · 90% of words in common

    Finds Crossref journal records by ISSN or title query. Provide issn for an exact single-journal lookup, or query for title-based search returning up to rows results. Title-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of the matched journal's most recent works; that list pages two ways, in two orders. works_offset is the simple one: newest published first, capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole works list, newest registered first — ordered by the date each DOI was registered with Crossref, since Crossref does not walk a publication-date sort by cursor: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the most recently registered work — it cannot resume from an offset. Returns journal metadata: title, publisher, ISSN-L, subject areas, and total DOI count.

  • crossref_search_workschangedinput schema, output schema
  • crossref_get_workchangeddescription, output schema
    before

    Resolves a DOI to its full Crossref metadata record: title, authors, affiliations, abstract (when deposited), journal or container, publication date, type, license, full-text links, and funder acknowledgements. The author list is paged: authorCount is the full deposited total, offset and limit select the page (25 authors by default), and when authors remain the response carries a nextOffset to pass back as offset — large-collaboration papers deposit thousands. Outgoing references are reported as a count in referencesCount; the reference entries themselves come from crossref_get_references. The isReferencedByCount field reports the total incoming citation count from Crossref; the citing works themselves are not available through Crossref — use OpenAlex for citation graphs.

    after · 56% of words in common

    Resolves a DOI to its full Crossref metadata record: title, authors, editors, affiliations, abstract (when deposited), journal or container with the volume, issue, pages, and article number that locate the work in it, ISSNs and ISBNs, publication date, type, license, full-text links, and funder acknowledgements. The author list is paged: authorCount is the full deposited total, offset and limit select the page (25 authors by default), and when authors remain the response carries a nextOffset to pass back as offset — large-collaboration papers deposit thousands. Post-publication updates are relayed as Crossref records them: updatedBy names each correction, retraction, expression of concern, or new version issued against this work, with its notice DOI and whether the publisher or Retraction Watch recorded it, and updateTo names the works this record is itself a notice for. An absent updatedBy does not mean the work was never updated — coverage depends on those deposits. relations lists related identifiers, such as a preprint and its published version, grouped by relation type; only the Crossref-registered DOIs among them resolve through crossref_get_work. Outgoing references are reported as a count in referencesCount; the reference entries themselves come from crossref_get_references. The isReferencedByCount field reports the total incoming citation count from Crossref; the citing works themselves are not available through Crossref — use OpenAlex for citation graphs.

Full history: list_changes · trend: quality JSON.

Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.

Trust 94 / 100

provenance80
liveness100
freshness100
hygiene100

+repository +namespace-matches-repo +reachable +uptime-99% +updated-11d-ago

Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.

Dependencies

@cyanheads/[email protected] npmthis version is not known to the dependency resolver

@cyanheads/[email protected] npmthis version is not known to the dependency resolver

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.

Endpoints

remoteauthreachableuptime 30dp50protocollast ok
https://crossref.caseyjhand.com/mcp streamable-httpnoneyes99%174 ms2026-07-282026-10-19
packageregistryversionruntimesecrets
@cyanheads/crossref-mcp-servernpm0.4.2npx
@cyanheads/crossref-mcp-servernpm0.4.2npx

Tools (7)

crossref_get_memberread-onlyResolves a Crossref member ID to its publisher/organization record: primary name, alternate imprint names, owned DOI prefixes, registered DOI counts, a per-work-type breakdown, and per-category metadata deposit coverage. Members are the organizations that register DOIs with Crossref, so this answers "what does this publisher publish, and how completely do they deposit metadata?" Resolve a DOI prefix (e.g. "10.1038") to its member ID with crossref_get_prefix, then pass that ID here.
crossref_get_prefixread-onlyResolves a DOI prefix — the registrant portion of a DOI, e.g. "10.1038" — to its owning Crossref member: the publisher name and numeric member ID. Answers "who publishes DOIs starting with 10.1038?" The Crossref prefix record carries only these three facts (no counts, coverage, or flags); the returned memberId chains directly into crossref_get_member for the full publisher record.
crossref_get_referencesread-onlyReturns the outgoing reference list for a DOI — the works cited by this paper. Each reference includes the deposited citation string and, where Crossref has resolved it, a DOI you can look up with crossref_get_work. Results are paged: referenceCount is the full deposited total, and when more remain the response carries a nextOffset to pass back as offset. Reference list coverage varies by publisher; many older works and non-participating publishers have no indexed references. Incoming citations — the works that cite this paper — are not available through Crossref; use OpenAlex for that.
crossref_get_workread-onlyResolves a DOI to its full Crossref metadata record: title, authors, editors, affiliations, abstract (when deposited), journal or container with the volume, issue, pages, and article number that locate the work in it, ISSNs and ISBNs, publication date, type, license, full-text links, and funder acknowledgements. The author list is paged: authorCount is the full deposited total, offset and limit select the page (25 authors by default), and when authors remain the response carries a nextOffset to pass back as offset — large-collaboration papers deposit thousands. Post-publication updates are relayed as Crossref records them: updatedBy names each correction, retraction, expression of concern, or new version issued against this work, with its notice DOI and whether the publisher or Retraction Watch recorded it, and updateTo names the works this record is itself a notice for. An absent updatedBy does not mean the work was never updated — coverage depends on those deposits. relations lists related identifiers, such as a preprint and its published version, grouped by relation type; only the Crossref-registered DOIs among them resolve through crossref_get_work. Outgoing references are reported as a count in referencesCount; the reference entries themselves come from crossref_get_references. The isReferencedByCount field reports the total incoming citation count from Crossref; the citing works themselves are not available through Crossref — use OpenAlex for citation graphs.
crossref_search_fundersread-onlyFinds funders registered in the Crossref Funder Registry by name or funder DOI. Provide funder_doi for an exact single-funder lookup — the full DOI ("10.13039/100000001"), the bare registry ID ("100000001"), or either behind a doi: or https://doi.org/ prefix — or query for name-based search. Name-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of the most recent works funded by the matched funder; that list pages two ways, in two orders. works_offset is the simple one: newest published first, capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole funded-works list, newest registered first — ordered by the date each DOI was registered with Crossref, since Crossref does not walk a publication-date sort by cursor: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the most recently registered work — it cannot resume from an offset. This list also counts works funded by the funder's registry descendants, which a crossref_search_works filter on {"funder": "10.13039/<id>"} does not. Returns funder name, registry ID, country, and alternate names. The Funder Registry supersedes entries, and a deprecated one answers to the same names as its successor while carrying only a fraction of its works: such a record carries replacedBy with the superseding registry ID and the response carries a notice naming it. The replacement is never followed automatically — re-run with funder_doi set to that ID to get the current entry.
crossref_search_journalsread-onlyFinds Crossref journal records by ISSN or title query. Provide issn for an exact single-journal lookup, or query for title-based search returning up to rows results. Title-query results page with offset — the nextOffset enrichment carries the value for the following page, up to offset + rows = 100000. Set include_works to true to also return a page of the matched journal's most recent works; that list pages two ways, in two orders. works_offset is the simple one: newest published first, capped ten times lower at works_offset + rows = 10000. works_cursor has no ceiling and reaches the whole works list, newest registered first — ordered by the date each DOI was registered with Crossref, since Crossref does not walk a publication-date sort by cursor: pass works_cursor="*" on the first call, then chain the nextWorksCursor token from each response. The two cannot be combined, and a cursor walk always starts at the most recently registered work — it cannot resume from an offset. Returns journal metadata: title, publisher, ISSN-L, subject areas, and total DOI count.
crossref_search_worksread-onlySearches the Crossref works index (~155M records) by free text and/or structured filters. The generic query matches loosely across all fields; scope precisely with the field-specific parameters queryTitle, queryAuthor, and queryContainerTitle, or resolve a known citation to its DOI with queryBibliographic — all combine with each other and with query. Use the filter parameter for structured filtering (object with hyphen-separated Crossref keys). Sort options: relevance, score, is-referenced-by-count, published, deposited, indexed. Each work returns at most authorLimit authors (25 by default) with authorCount reporting the full deposited total, since a single page of large-collaboration papers can carry tens of thousands of author entries; crossref_get_work pages the whole author list for any DOI whose list was cut. Offset-based paging is capped at ~10K results; use cursor="*" to start cursor-based deep paging, then pass the nextCursor value from each response to continue. The walk ends on the page where nextCursor is absent — that page also carries a notice saying the list is exhausted. Cursor and offset cannot be combined.

Schemas: list_tools.

Similar MCP servers

More from io.github.cyanheads

And 136 more from this publisher.

Official server.json
{
  "name": "io.github.cyanheads/crossref-mcp-server",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "remotes": [
    {
      "url": "https://crossref.caseyjhand.com/mcp",
      "type": "streamable-http"
    }
  ],
  "version": "0.4.2",
  "packages": [
    {
      "version": "0.4.2",
      "transport": {
        "type": "stdio"
      },
      "identifier": "@cyanheads/crossref-mcp-server",
      "runtimeHint": "npx",
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "environmentVariables": [
        {
          "name": "CROSSREF_MAILTO",
          "format": "string",
          "description": "Email for polite-pool User-Agent header — optional. Without: anonymous pool with stricter rate limits."
        },
        {
          "name": "CROSSREF_BASE_URL",
          "format": "string",
          "default": "https://api.crossref.org",
          "description": "Override the Crossref API base URL. Defaults to https://api.crossref.org."
        },
        {
          "name": "CROSSREF_TIMEOUT_MS",
          "format": "string",
          "default": "10000",
          "description": "Per-request timeout in milliseconds."
        },
        {
          "name": "MCP_LOG_LEVEL",
          "format": "string",
          "default": "info",
          "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
        }
      ]
    },
    {
      "version": "0.4.2",
      "transport": {
        "url": "http://localhost:3010/mcp",
        "type": "streamable-http"
      },
      "identifier": "@cyanheads/crossref-mcp-server",
      "runtimeHint": "npx",
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "environmentVariables": [
        {
          "name": "MCP_TRANSPORT_TYPE",
          "value": "http",
          "format": "string",
          "description": "Selects the HTTP transport."
        },
        {
          "name": "CROSSREF_MAILTO",
          "format": "string",
          "description": "Email for polite-pool User-Agent header — optional. Without: anonymous pool with stricter rate limits."
        },
        {
          "name": "CROSSREF_BASE_URL",
          "format": "string",
          "default": "https://api.crossref.org",
          "description": "Override the Crossref API base URL. Defaults to https://api.crossref.org."
        },
        {
          "name": "CROSSREF_TIMEOUT_MS",
          "format": "string",
          "default": "10000",
          "description": "Per-request timeout in milliseconds."
        },
        {
          "name": "MCP_HTTP_HOST",
          "format": "string",
          "default": "127.0.0.1",
          "description": "The hostname for the HTTP server."
        },
        {
          "name": "MCP_HTTP_PORT",
          "format": "string",
          "default": "3010",
          "description": "The port to run the HTTP server on."
        },
        {
          "name": "MCP_HTTP_ENDPOINT_PATH",
          "format": "string",
          "default": "/mcp",
          "description": "The endpoint path for the MCP server."
        },
        {
          "name": "MCP_AUTH_MODE",
          "format": "string",
          "default": "none",
          "description": "Authentication mode to use: 'none', 'jwt', or 'oauth'."
        },
        {
          "name": "MCP_LOG_LEVEL",
          "format": "string",
          "default": "info",
          "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
        }
      ]
    }
  ],
  "repository": {
    "url": "https://github.com/cyanheads/crossref-mcp-server",
    "source": "github"
  },
  "description": "Resolve DOIs, search ~155M scholarly works, and fetch references via the Crossref REST API."
}