Skip to main content
Glama

crossref-mcp-server

Search Works

crossref_search_works
Read-only

Searches the Crossref works index (~188M 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, created. 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. Post-publication updates ride each work as Crossref records them: updatedBy names each correction, retraction, expression of concern, or new version issued against it, and updateTo the works it is itself a notice for — an absent updatedBy does not mean the work was never updated. 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. A walk with a query term and no sort runs by relevance, one with filters only in Crossref registration order. 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

NameRequiredDescriptionDefault
rowsNoNumber of results to return per page (1–100 per call, default 20). A larger value, up to 1000, returns 100 and says so in notice — on an offset page the notice also names the offset that continues after the records returned.
sortNoSort field. Omitted, an offset page with a query term is ranked by relevance, and so is a cursor walk with one (sent as score). 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). Applies only alongside sort; without one it has no effect.
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. A walk with a query term runs by relevance unless sort is set; a walk with filters only runs in Crossref registration order. Relevance scores shift slightly between identical requests, so a relevance walk can repeat or skip a record at a page boundary — sort:"created" walks every match without repeats. 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, updated-by → updatedBy, update-to → updateTo. 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 per call, default 25; a larger value, up to 100000, applies 500 and says so in notice). 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

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. On any page, present when rows or authorLimit was above its per-call cap, naming the value requested and the cap applied — on an offset page with records remaining, also the offset that continues after the records returned, with the smaller rows that still fit when a full page there would pass the ~10K offset ceiling. 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 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"New value: +"Abstract when present in the indexed record — the text of the publisher’s JATS deposit, with markup removed and character references decoded; numeric JATS superscripts retain caret notation (10^{16}, GeV^2), 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. Changed12 schema fields changed
    • changedInput schema / properties / authorLimit / description
      Previous value: -"Maximum 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."New value: +"Maximum number of authors to return per work (1–500 per call, default 25; a larger value, up to 100000, applies 500 and says so in notice). 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."
    • changedInput schema / properties / authorLimit / maximum
      Previous value: -500New value: +100000
    • 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, or with a publication-date sort (published, published-print, published-online), which Crossref does not walk by cursor."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. A walk with a query term runs by relevance unless sort is set; a walk with filters only runs in Crossref registration order. Relevance scores shift slightly between identical requests, so a relevance walk can repeat or skip a record at a page boundary — sort:\"created\" walks every match without repeats. 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, 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)."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, updated-by → updatedBy, update-to → updateTo. 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)."
    • changedInput schema / properties / fields / items / enum
      Previous 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"
      -]New 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",
      +  "updated-by",
      +  "update-to"
      +]
    • changedInput schema / properties / order / description
      Previous value: -"Sort direction (asc or desc)"New value: +"Sort direction (asc or desc). Applies only alongside sort; without one it has no effect."
    • changedInput schema / properties / rows / description
      Previous value: -"Number of results to return per page (1–100, default 20)"New value: +"Number of results to return per page (1–100 per call, default 20). A larger value, up to 1000, returns 100 and says so in notice — on an offset page the notice also names the offset that continues after the records returned."
    • changedInput schema / properties / rows / maximum
      Previous value: -100New value: +1000
    • changedInput schema / properties / sort / description
      Previous 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."New value: +"Sort field. Omitted, an offset page with a query term is ranked by relevance, and so is a cursor walk with one (sent as score). 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."
    • 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 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."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. On any page, present when rows or authorLimit was above its per-call cap, naming the value requested and the cap applied — on an offset page with records remaining, also the offset that continues after the records returned, with the smaller rows that still fit when a full page there would pass the ~10K offset ceiling. A page needing more than one caveat carries them all in this one string."
    • addedOutput schema / properties / works / items / properties / updateTo
      Added value: +{
      +  "description": "Works this record is an update notice for, in the entry shape updatedBy uses and in deposited order. Omitted when the record is not registered as a notice.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "Update link",
      +    "properties": {
      +      "doi": {
      +        "description": "DOI on the other side of the link: the notice, in updatedBy; the updated work, in updateTo. It is this work's own DOI when the update was made to this record in place.",
      +        "type": "string"
      +      },
      +      "recordId": {
      +        "description": "Retraction Watch record ID. Present only on retraction-watch entries.",
      +        "type": "string"
      +      },
      +      "source": {
      +        "description": "Who recorded the link: publisher, or retraction-watch for an entry Crossref carries from the Retraction Watch database",
      +        "type": "string"
      +      },
      +      "type": {
      +        "description": "Crossref update type as deposited: correction, erratum, corrigendum, addendum, retraction, withdrawal, expression_of_concern, new_version, new_edition, or another code",
      +        "type": "string"
      +      },
      +      "updated": {
      +        "additionalProperties": false,
      +        "description": "Date the update was issued",
      +        "properties": {
      +          "day": {
      +            "description": "Day of month",
      +            "type": "number"
      +          },
      +          "month": {
      +            "description": "Month (1–12)",
      +            "type": "number"
      +          },
      +          "year": {
      +            "description": "Year",
      +            "type": "number"
      +          }
      +        },
      +        "type": "object"
      +      }
      +    },
      +    "required": [
      +      "doi",
      +      "type",
      +      "source"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / works / items / properties / updatedBy
      Added value: +{
      +  "description": "Update notices Crossref records against this work — corrections, errata, retractions, expressions of concern, withdrawals, new versions — in deposited order. Entries are never merged: the same notice DOI can appear once per source, typed differently by each. Omitted when none is recorded, which does not mean the work was never updated: coverage depends on publisher and Retraction Watch deposits.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "Update link",
      +    "properties": {
      +      "doi": {
      +        "description": "DOI on the other side of the link: the notice, in updatedBy; the updated work, in updateTo. It is this work's own DOI when the update was made to this record in place.",
      +        "type": "string"
      +      },
      +      "recordId": {
      +        "description": "Retraction Watch record ID. Present only on retraction-watch entries.",
      +        "type": "string"
      +      },
      +      "source": {
      +        "description": "Who recorded the link: publisher, or retraction-watch for an entry Crossref carries from the Retraction Watch database",
      +        "type": "string"
      +      },
      +      "type": {
      +        "description": "Crossref update type as deposited: correction, erratum, corrigendum, addendum, retraction, withdrawal, expression_of_concern, new_version, new_edition, or another code",
      +        "type": "string"
      +      },
      +      "updated": {
      +        "additionalProperties": false,
      +        "description": "Date the update was issued",
      +        "properties": {
      +          "day": {
      +            "description": "Day of month",
      +            "type": "number"
      +          },
      +          "month": {
      +            "description": "Month (1–12)",
      +            "type": "number"
      +          },
      +          "year": {
      +            "description": "Year",
      +            "type": "number"
      +          }
      +        },
      +        "type": "object"
      +      }
      +    },
      +    "required": [
      +      "doi",
      +      "type",
      +      "source"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  3. 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"
  4. 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"
      +}
  5. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only cover readOnly/openWorld, but the description goes far beyond: the ~10K offset cap and cursor walk protocol, the end condition (page with no nextCursor), the incompatibility of cursor with offset and publication-date sorts, the relevance-walk repeat/skip hazard with the sort:"created" workaround, and the truncation of author lists with authorCount as the true total. It also explains that an absent updatedBy does not mean a work was never updated – a genuine non-obvious caveat.

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

Conciseness4/5

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

Purpose and mode selection are front-loaded, and the dense back half is mostly load-bearing detail about paging. Some of it restates cursor and sort behavior already spelled out in the schema parameter descriptions, which is avoidable repetition in an already long description.

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, nested-object, deep-paging search tool this covers everything an agent needs to call it correctly: query modes, filter shape, sort/paging compatibility, payload limiting, and the escape hatch to crossref_get_work. The output schema exists and the description does not waste space explaining return shapes beyond the paging and author-cap semantics.

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%, so the baseline is 3, but the description adds real meaning: the combination semantics ('all combine with each other and with query'), the authorLimit default of 25 versus the deposited total, and the fact that filter keys are hyphen-separated Crossref names. Much of the cursor and sort text duplicates the schema's own parameter descriptions, keeping it out of 5 territory.

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?

States a specific verb and resource plus scale ('Searches the Crossref works index (~188M records) by free text and/or structured filters'). It then distinguishes the generic query from the field-specific variants queryTitle/queryAuthor/queryContainerTitle and queryBibliographic, so an agent can pick the right mode without opening the schema.

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

Usage Guidelines4/5

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

Strong in-mode routing: use queryBibliographic to resolve a known citation to a DOI, field-specific params to scope precisely, filter for structured filtering, and crossref_get_work to page a truncated author list. It does not, however, differentiate itself from adjacent siblings such as crossref_search_journals or crossref_search_funders, so tool-level selection guidance is incomplete.

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.