Skip to main content
Glama

crossref-mcp-server

Search Works

crossref_search_works
Read-only

Searches 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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rowsNoNumber of results to return per page (1–100, default 20)
sortNoSort field. The publication-date sorts (published, published-print, published-online) work with offset paging only — Crossref refuses them alongside cursor; every other sort works with either.
orderNoSort direction (asc or desc)
queryNoFree-text search query, e.g. "CRISPR gene editing" or "climate change adaptation"
cursorNoCursor token for deep paging. Pass "*" to start cursor-based paging (required past ~10K results), then pass the nextCursor value from each response until a response omits it, which means the list is exhausted. Cannot be combined with offset, or with a publication-date sort (published, published-print, published-online), which Crossref does not walk by cursor.
fieldsNoFields to return (reduces payload). Names are case-sensitive, and each fills one output field: DOI → doi, title → title, type → type, author → authors and authorCount, published / published-print / published-online → published, container-title → containerTitle, publisher → publisher, is-referenced-by-count → isReferencedByCount, score → score, abstract → abstract, volume → volume, issue → issue, page → page, article-number → articleNumber, ISSN → issn. A selected field absent from a work means the record does not deposit it. DOI is always returned whether or not it is listed here, so every result stays resolvable by crossref_get_work, which also returns the fields this list does not cover (license, funder, references, and the rest of the record).
filterNoStructured filter object using Crossref hyphen-separated keys. All values must be strings. Boolean flag keys (has-abstract, has-references, has-full-text) require string values "true" or "false". Example: {"type":"journal-article","has-abstract":"true","from-pub-date":"2023-01-01"}
offsetNoZero-based result offset for offset-based paging. Cannot be used with cursor. Capped at ~10K; use cursor for deeper paging.
queryTitleNoMatch against work titles only, e.g. "Array programming with NumPy".
authorLimitNoMaximum number of authors to return per work (1–500, default 25). Ordinary records fit under the default; large-collaboration papers deposit thousands, and a page of them is large enough to exhaust a client context. Each work reports its full deposited total as authorCount — call crossref_get_work with that work doi to page the authors this cap left out.
queryAuthorNoMatch against author names only, e.g. "Charles R. Harris".
queryBibliographicNoWhole-citation match to resolve a known reference to its DOI. Combine title, author, year, and container into one string, e.g. "Watson Crick molecular structure of nucleic acids Nature 1953".
queryContainerTitleNoMatch against the container title (journal or book name) only, e.g. "Nature".

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
capNoThe per-work author cap applied to this page. Absent when no list was cut.
errorNoPresent when the call failed. Absent on success.
worksNoMatching works. Empty when nothing matched the query, when an offset runs past the end of the results, or on the page that ends a cursor walk — the notice enrichment says which.
noticeNoGuidance on an empty page, naming which of its three causes applies: a query nothing matched, an offset past the end of a list that did match, or a cursor walk that has reached the end of the list. On a page carrying records, present when authorLimit cut at least one work list, naming how many and the route to the rest, or when every query term and filter value was supplied blank, so the page lists the whole index unfiltered. A page needing more than one caveat carries them all in this one string.
returnedNoNumber of records returned in this response
truncatedNoTrue when at least one work on this page had its author list cut by authorLimit. Absent when every work on the page carries its full deposited author list.
nextCursorNoCursor token to pass as cursor on the next call to continue a cursor walk. Present only on a page requested with cursor, and absent once the walk reaches the end of the list.
totalResultsNoTotal matching records in Crossref

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / works / items / properties / abstract / description
      Previous value: -"Abstract when present in the indexed record — the text of the publisher’s JATS deposit, with markup removed and character references decoded; a link keeps its tag only where its href holds an address the text it wraps does not already carry, and a formula the deposit encodes more than once appears once, in the first notation deposited"New value: +"Abstract when present in the indexed record — the text of the publisher’s JATS deposit, with markup removed and character references decoded; a link keeps its tag only where its href holds an address the text it wraps does not already carry, and each formula appears once — MathML as the TeX annotation it carries, otherwise written out linearly (x_i, A^{−1}, √(m), (a+b)/c), and TeX deposited beside MathML in whichever notation comes first"
  2. Changed23 schema fields changed
    • changedInput schema / properties / cursor / description
      Previous value: -"Cursor token for deep paging. Pass \"*\" to start cursor-based paging (required past ~10K results), then pass the nextCursor value from each response until a response omits it, which means the list is exhausted. Cannot be combined with offset."New value: +"Cursor token for deep paging. Pass \"*\" to start cursor-based paging (required past ~10K results), then pass the nextCursor value from each response until a response omits it, which means the list is exhausted. Cannot be combined with offset, or with a publication-date sort (published, published-print, published-online), which Crossref does not walk by cursor."
    • changedInput schema / properties / fields / description
      Previous value: -"Fields to return (reduces payload). Names are case-sensitive. Useful set: DOI, title, author, published, type, is-referenced-by-count, abstract, container-title, publisher, score. DOI is always returned whether or not it is listed here, so every result stays resolvable by crossref_get_work."New value: +"Fields to return (reduces payload). Names are case-sensitive, and each fills one output field: DOI → doi, title → title, type → type, author → authors and authorCount, published / published-print / published-online → published, container-title → containerTitle, publisher → publisher, is-referenced-by-count → isReferencedByCount, score → score, abstract → abstract, volume → volume, issue → issue, page → page, article-number → articleNumber, ISSN → issn. A selected field absent from a work means the record does not deposit it. DOI is always returned whether or not it is listed here, so every result stays resolvable by crossref_get_work, which also returns the fields this list does not cover (license, funder, references, and the rest of the record)."
    • addedInput schema / properties / fields / items / description
      Added value: +"Crossref select name"
    • addedInput schema / properties / fields / items / enum
      Added value: +[
      +  "DOI",
      +  "title",
      +  "type",
      +  "author",
      +  "published",
      +  "published-print",
      +  "published-online",
      +  "container-title",
      +  "publisher",
      +  "is-referenced-by-count",
      +  "score",
      +  "abstract",
      +  "volume",
      +  "issue",
      +  "page",
      +  "article-number",
      +  "ISSN"
      +]
    • changedInput schema / properties / filter / description
      Previous value: -"Structured filter object using Crossref hyphen-separated keys. All values must be strings. Boolean flag keys (has-abstract, has-references, has-full-text) require string values \"true\" or \"false\". Example: {\"type\":\"journal-article\",\"has-abstract\":\"true\",\"from-pub-date\":\"2023-01-01\",\"directory\":\"DOAJ\"}"New value: +"Structured filter object using Crossref hyphen-separated keys. All values must be strings. Boolean flag keys (has-abstract, has-references, has-full-text) require string values \"true\" or \"false\". Example: {\"type\":\"journal-article\",\"has-abstract\":\"true\",\"from-pub-date\":\"2023-01-01\"}"
    • addedInput schema / properties / offset / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / offset / type
      Previous value: -"number"New value: +"integer"
    • addedInput schema / properties / order / anyOf
      Added value: +[
      +  {
      +    "const": "",
      +    "type": "string"
      +  },
      +  {
      +    "description": "Sort direction",
      +    "enum": [
      +      "asc",
      +      "desc"
      +    ],
      +    "type": "string"
      +  }
      +]
    • removedInput schema / properties / order / enum
      Removed value: -[
      -  "asc",
      -  "desc"
      -]
    • removedInput schema / properties / order / type
      Removed value: -"string"
    • changedInput schema / properties / rows / type
      Previous value: -"number"New value: +"integer"
    • addedInput schema / properties / sort / anyOf
      Added value: +[
      +  {
      +    "const": "",
      +    "type": "string"
      +  },
      +  {
      +    "description": "Crossref sort field",
      +    "enum": [
      +      "relevance",
      +      "score",
      +      "is-referenced-by-count",
      +      "published",
      +      "published-print",
      +      "published-online",
      +      "deposited",
      +      "indexed",
      +      "created",
      +      "updated",
      +      "references-count"
      +    ],
      +    "type": "string"
      +  }
      +]
    • changedInput schema / properties / sort / description
      Previous value: -"Sort field"New value: +"Sort field. The publication-date sorts (published, published-print, published-online) work with offset paging only — Crossref refuses them alongside cursor; every other sort works with either."
    • removedInput schema / properties / sort / enum
      Removed value: -[
      -  "relevance",
      -  "score",
      -  "is-referenced-by-count",
      -  "published",
      -  "published-print",
      -  "published-online",
      -  "deposited",
      -  "indexed",
      -  "created",
      -  "updated",
      -  "references-count"
      -]
    • removedInput schema / properties / sort / type
      Removed value: -"string"
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `rate_limited`: Crossref answered HTTP 429 and the limit did not clear inside the retry budget. `upstream_unavailable`: Crossref was unreachable, returned a 5xx status, or served an HTML error page instead of JSON. `malformed_response`: Crossref returned HTTP 200 with a body that is not valid JSON. `request_timeout`: Crossref did not respond within CROSSREF_TIMEOUT_MS, or answered HTTP 408/504. `cursor_offset_conflict`: Both cursor and offset were supplied in the same request. `offset_too_large`: The requested offset exceeds the ~10K Crossref limit for offset-based paging. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `rate_limited`: Crossref answered HTTP 429 and the limit did not clear inside the retry budget. `upstream_unavailable`: Crossref was unreachable, returned a 5xx status, or served an HTML error page instead of JSON. `malformed_response`: Crossref returned HTTP 200 with a body that is not valid JSON. `request_timeout`: Crossref did not respond within CROSSREF_TIMEOUT_MS, or answered HTTP 408/504. `unknown_filter`: Crossref rejected a filter key it does not recognize (filter-not-available). `sort_cursor_conflict`: A publication-date sort (published, published-print, published-online) was combined with cursor paging, which Crossref refuses. `invalid_cursor`: Crossref did not recognize the cursor token (HTTP 404 cursor-invalid). `invalid_parameter`: Crossref rejected a parameter value (a filter value of the wrong type or form), or answered HTTP 400 with a body that did not parse. `cursor_offset_conflict`: Both cursor and offset were supplied in the same request. `offset_too_large`: The requested offset exceeds the ~10K Crossref limit for offset-based paging. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "rate_limited",
      -  "upstream_unavailable",
      -  "malformed_response",
      -  "request_timeout",
      -  "cursor_offset_conflict",
      -  "offset_too_large"
      -]New value: +[
      +  "rate_limited",
      +  "upstream_unavailable",
      +  "malformed_response",
      +  "request_timeout",
      +  "unknown_filter",
      +  "sort_cursor_conflict",
      +  "invalid_cursor",
      +  "invalid_parameter",
      +  "cursor_offset_conflict",
      +  "offset_too_large"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance on an empty page, naming which of its three causes applies: a query nothing matched, an offset past the end of a list that did match, or a cursor walk that has reached the end of the list. On a page carrying records, present only when authorLimit cut at least one work list, naming how many and the route to the rest."New value: +"Guidance on an empty page, naming which of its three causes applies: a query nothing matched, an offset past the end of a list that did match, or a cursor walk that has reached the end of the list. On a page carrying records, present when authorLimit cut at least one work list, naming how many and the route to the rest, or when every query term and filter value was supplied blank, so the page lists the whole index unfiltered. A page needing more than one caveat carries them all in this one string."
    • addedOutput schema / properties / works / items / properties / articleNumber
      Added value: +{
      +  "description": "Article number, deposited by journals that number articles instead of paging them",
      +  "type": "string"
      +}
    • addedOutput schema / properties / works / items / properties / issn
      Added value: +{
      +  "description": "ISSN(s) of the containing journal",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / works / items / properties / issue
      Added value: +{
      +  "description": "Issue of the container the work appears in",
      +  "type": "string"
      +}
    • addedOutput schema / properties / works / items / properties / page
      Added value: +{
      +  "description": "Page range as deposited, e.g. \"357-362\"",
      +  "type": "string"
      +}
    • addedOutput schema / properties / works / items / properties / volume
      Added value: +{
      +  "description": "Volume of the container the work appears in",
      +  "type": "string"
      +}
  3. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint/openWorldHint annotations, it discloses the ~10K offset cap, cursor-based paging with nextCursor and the exhaustion signal, the authorLimit/authorCount behavior with huge-collaboration papers, and sort restrictions (publication-date sorts incompatible with cursor). This materially affects how an agent pages and interprets results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but structured, leading with the core action, then search strategy, then paging/cursor constraints, then author cap and relationship to crossref_get_work. The fields parameter mapping is deferred to the schema, so the description avoids duplicating the full parameter list while still earning every sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 13-parameter search tool with no required parameters, this description covers intent, filtering, sorting, paging, cursor behavior, payload reduction, and how to go deeper with crossref_get_work. The output schema exists, so not describing return-value structure is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema itself is rich, so the baseline is 3. The description adds strategic meaning beyond the schema: which query parameter to prefer depending on need, how cursor walking terminates, and what authorLimit truncation means for the output. It does not radically extend the schema's already detailed parameter descriptions, so 4 rather than 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Searches the Crossref works index (~155M records) by free text and/or structured filters.' It clearly separates this from the sibling get_* tools by explaining that search results are resolvable through crossref_get_work, and from search_journals/funders through the 'works index' scoping.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage strategy: loose generic query vs. field-specific queryTitle/queryAuthor/queryContainerTitle/queryBibliographic, and notes they combine. It also names crossref_get_work as the alternative for full records and for paging truncated author lists, and states cursor/offset cannot be combined.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.