Skip to main content
Glama

Openalex Get Citation Graph

openalex_get_citation_graph
Read-onlyIdempotent

Walk the citation graph one hop from a seed work. Direction picks the edge: incoming citations (cites), the seed's own references (cited_by), or OpenAlex's algorithmically-related works (related_to). Note: direction follows OpenAlex's filter convention, which inverts the common English reading — cites returns works that cite the seed; cited_by returns works the seed cites. Results use the works schema; combine with filters/sort to narrow further. Responses cap at 64,000 bytes per surface unless the least a call can return is larger (over_budget); omitted and windows give the openalex_search_entities calls that continue a cut.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sortNoSort field. Prefix with "-" for descending. Comma-separate for a multi-key sort, applied left to right, with the "-" prefix set per key ("-publication_year,cited_by_count" sorts by year descending, then citations ascending). Common: "cited_by_count", "-publication_date". Default is OpenAlex relevance.
cursorNoPagination cursor from a previous response. Pass to get the next page. Omit it on the first call — an empty string is rejected, since a supplied-but-blank cursor is a caller mistake rather than a request for the first page.
selectNoOpenAlex work field names to return. Always returned: id, display_name. Defaults to the curated works select if omitted. Large projections may be cut to fit the response budget (`omitted`, `windows`).
filtersNoAdditional filters to narrow the graph, same syntax as openalex_search_entities. Example: publication_year=">2020", is_oa="true". Do not include cites/cited_by/related_to, nor an alias of one such as cited_works — those keys are set by the `direction` parameter.
seed_idYesSeed work identifier. Accepts OpenAlex ID ("W2741809807"), DOI ("10.1038/nature12373" or full URL), or PMID ("12345678" or "https://pubmed.ncbi.nlm.nih.gov/12345678"). A PMCID is recognized too, bare or as a PubMed Central URL, but OpenAlex indexes no PMCIDs, so it resolves nothing — pass the work's PMID or DOI instead. Use openalex_resolve_name first if you only have a title.
per_pageNoResults per page (1-100). Default 25. A budget-cut page returns fewer (`omitted`).
directionYes"cites": works that cite seed_id (incoming citations). "cited_by": works that seed_id cites (its reference list). "related_to": OpenAlex algorithmically-related works (~8-30 typical, may be empty for less-cited seeds).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
echoNoCompact echo of seed_id, direction, filters, sort — surfaces what was actually queried when no edges are returned.
metaNoResult metadata including pagination.
errorNoPresent when the call failed. Absent on success.
budgetNoWhat this call cost against the OpenAlex daily budget and what is left of it. Price a full walk before committing to it: `totalCount` ÷ `per_page` × `costUsd` against `remainingUsd`. Absent when OpenAlex omitted the accounting headers.
noticeNoGuidance notice. Set when no edges are returned — a first call suggests verifying the seed_id, broadening filters, or trying a different direction; a `cursor` continuation says the walk is already past its last edge instead — when the response budget cut works, windowed an array, or ran over, and when a work carries exactly 100 authorships (possibly capped). Absent otherwise.
omittedNoPresent when the response budget cut whole records from the page end; pagination continues after the full upstream page.
resultsNoWorks on the citation graph in this direction. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed — except identifier and URL fields such as `id`, `doi`, `ids`, and `*_url`, returned exactly as OpenAlex stores them. Works cut by the response budget are in `omitted`; partial or possibly capped arrays are in `windows`.
windowsNoArrays returned in part — windowed to fit the budget, paged by `slice`, or 100 possibly capped authorships — each with its continuation. A `slice` call always carries its window, even for a whole array; otherwise absent when every array is whole.
totalCountNoTotal edges from seed_id in this direction across all pages.
over_budgetNoTrue when even the least this call can return — the first record's non-array fields (its arrays windowed to empty), or one `slice` element — exceeds the budget.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changed
    • changedInput schema / properties / per_page / description
      Previous value: -"Results per page (1-100). Default 25."New value: +"Results per page (1-100). Default 25. A budget-cut page returns fewer (`omitted`)."
    • changedInput schema / properties / select / description
      Previous value: -"OpenAlex work field names to return. Always returned: id, display_name. Defaults to the curated works select if omitted."New value: +"OpenAlex work field names to return. Always returned: id, display_name. Defaults to the curated works select if omitted. Large projections may be cut to fit the response budget (`omitted`, `windows`)."
    • changedOutput schema / properties / meta / properties / next_cursor / description
      Previous value: -"Cursor for next page. null if no more results."New value: +"Cursor for next page. null if no more results. Continues after the full upstream page, `omitted` works included."
    • changedOutput schema / properties / meta / properties / per_page / description
      Previous value: -"Page size OpenAlex echoed for this request — the requested per_page, not the number of records returned. A short or exhausted page carries fewer records than this."New value: +"Page size OpenAlex echoed for this request — the requested per_page, not the number of records returned. A short or exhausted page carries fewer records than this, as does a page the response budget cut (`omitted`)."
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when no edges are returned. A first call suggests verifying the seed_id, broadening filters, or trying a different direction; a `cursor` continuation says the walk is already past its last edge instead. Absent when results are present."New value: +"Guidance notice. Set when no edges are returned — a first call suggests verifying the seed_id, broadening filters, or trying a different direction; a `cursor` continuation says the walk is already past its last edge instead — when the response budget cut works, windowed an array, or ran over, and when a work carries exactly 100 authorships (possibly capped). Absent otherwise."
    • addedOutput schema / properties / omitted
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Present when the response budget cut whole records from the page end; pagination continues after the full upstream page.",
      +  "properties": {
      +    "ids": {
      +      "description": "Bare IDs of the records left out, in page order (a keyword keeps its URL).",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "next": {
      +      "additionalProperties": false,
      +      "description": "One call returning those records as a set, in OpenAlex's order, not page order. Budgeted too, so it may carry its own `omitted`.",
      +      "properties": {
      +        "arguments": {
      +          "additionalProperties": {},
      +          "description": "Arguments to pass as-is.",
      +          "properties": {},
      +          "type": "object"
      +        },
      +        "tool": {
      +          "const": "openalex_search_entities",
      +          "description": "Tool to call.",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "tool",
      +        "arguments"
      +      ],
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "ids",
      +    "next"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / over_budget
      Added value: +{
      +  "description": "True when even the least this call can return — the first record's non-array fields (its arrays windowed to empty), or one `slice` element — exceeds the budget.",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / results / description
      Previous value: -"Works on the citation graph in this direction. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed."New value: +"Works on the citation graph in this direction. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed — except identifier and URL fields such as `id`, `doi`, `ids`, and `*_url`, returned exactly as OpenAlex stores them. Works cut by the response budget are in `omitted`; partial or possibly capped arrays are in `windows`."
    • addedOutput schema / properties / windows
      Added value: +{
      +  "description": "Arrays returned in part — windowed to fit the budget, paged by `slice`, or 100 possibly capped authorships — each with its continuation. A `slice` call always carries its window, even for a whole array; otherwise absent when every array is whole.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "An array returned in part.",
      +    "properties": {
      +      "field": {
      +        "description": "Array field.",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "Bare ID of the record.",
      +        "type": "string"
      +      },
      +      "next": {
      +        "anyOf": [
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "arguments": {
      +                "additionalProperties": {},
      +                "description": "Arguments to pass as-is.",
      +                "properties": {},
      +                "type": "object"
      +              },
      +              "tool": {
      +                "const": "openalex_search_entities",
      +                "description": "Tool to call.",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "tool",
      +              "arguments"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "`id` + `slice` call for the next elements; null at the array end."
      +      },
      +      "offset": {
      +        "description": "Index of the first element shown.",
      +        "type": "number"
      +      },
      +      "possibly_capped": {
      +        "description": "True for exactly 100 authorships on a list record (OpenAlex's cap): the list may be longer.",
      +        "type": "boolean"
      +      },
      +      "shown": {
      +        "description": "Elements shown.",
      +        "type": "number"
      +      },
      +      "total": {
      +        "description": "Array length as returned to this call.",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "id",
      +      "field",
      +      "offset",
      +      "shown",
      +      "total",
      +      "possibly_capped",
      +      "next"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  2. Changed1 schema field changed
    • changedOutput schema / properties / results / description
      Previous value: -"Works on the citation graph in this direction."New value: +"Works on the citation graph in this direction. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed."
  3. Changed6 schema fields changed
    • changedInput schema / properties / cursor / description
      Previous value: -"Pagination cursor from a previous response. Pass to get the next page."New value: +"Pagination cursor from a previous response. Pass to get the next page. Omit it on the first call — an empty string is rejected, since a supplied-but-blank cursor is a caller mistake rather than a request for the first page."
    • addedInput schema / properties / cursor / minLength
      Added value: +1
    • changedInput schema / properties / filters / description
      Previous value: -"Additional filters to narrow the graph, same syntax as openalex_search_entities. Example: publication_year=\">2020\", is_oa=\"true\". Do not include cites/cited_by/related_to — those are set by the `direction` parameter."New value: +"Additional filters to narrow the graph, same syntax as openalex_search_entities. Example: publication_year=\">2020\", is_oa=\"true\". Do not include cites/cited_by/related_to, nor an alias of one such as cited_works — those keys are set by the `direction` parameter."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `rate_limited`: OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429). `upstream_budget_exhausted`: The OpenAlex daily usage budget is spent (HTTP 429). `upstream_timeout`: OpenAlex did not respond within the request deadline. `upstream_unavailable`: OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON. `upstream_unauthorized`: OpenAlex rejected the API key (HTTP 401). `upstream_forbidden`: OpenAlex denied access to the requested resource (HTTP 403). `comma_in_filter_value`: A filter value contains a comma, which collides with the OpenAlex filter separator. `upstream_invalid_params`: OpenAlex rejected an invalid filter or sort field name (HTTP 400). `upstream_invalid_id_value`: An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400). `upstream_sort_requires_search`: sort=-relevance_score was used but the citation-graph query has no active search (HTTP 400). `upstream_invalid_params_other`: OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name. `reserved_filter_key`: filters contains cites/cited_by/related_to — the direction parameter reserves those keys. `entity_not_found`: OpenAlex has no work matching the seed_id. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `rate_limited`: OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429). `upstream_budget_exhausted`: The OpenAlex daily usage budget is spent (HTTP 429). `upstream_timeout`: OpenAlex did not respond within the request deadline. `upstream_unavailable`: OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON. `upstream_unauthorized`: OpenAlex rejected the API key (HTTP 401). `upstream_forbidden`: OpenAlex denied access to the requested resource (HTTP 403). `comma_in_filter_value`: A filter value contains a comma, which collides with the OpenAlex filter separator. `upstream_invalid_params`: OpenAlex rejected an invalid filter or sort field name (HTTP 400). `upstream_invalid_id_value`: An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400). `upstream_sort_requires_search`: sort=-relevance_score was used but the citation-graph query has no active search (HTTP 400). `upstream_invalid_params_other`: OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name. `reserved_filter_key`: filters contains cites/cited_by/related_to, or an alias of one such as cited_works — the direction parameter reserves those keys. `entity_not_found`: OpenAlex has no work matching the seed_id. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / meta / properties / per_page / description
      Previous value: -"Records on this page."New value: +"Page size OpenAlex echoed for this request — the requested per_page, not the number of records returned. A short or exhausted page carries fewer records than this."
    • changedOutput schema / properties / notice / description
      Previous value: -"Recovery guidance when no edges are returned — suggests verifying the seed_id, broadening filters, or trying a different direction. Absent when results are present."New value: +"Guidance when no edges are returned. A first call suggests verifying the seed_id, broadening filters, or trying a different direction; a `cursor` continuation says the walk is already past its last edge instead. Absent when results are present."
  4. Changed1 schema field changed
    • changedInput schema / properties / seed_id / description
      Previous value: -"Seed work identifier. Accepts OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\" or full URL), PMID (\"12345678\" or \"https://pubmed.ncbi.nlm.nih.gov/12345678\"), or PMCID. Use openalex_resolve_name first if you only have a title."New value: +"Seed work identifier. Accepts OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\" or full URL), or PMID (\"12345678\" or \"https://pubmed.ncbi.nlm.nih.gov/12345678\"). A PMCID is recognized too, bare or as a PubMed Central URL, but OpenAlex indexes no PMCIDs, so it resolves nothing — pass the work's PMID or DOI instead. Use openalex_resolve_name first if you only have a title."
  5. Changed1 schema field changed
    • changedInput schema / properties / seed_id / description
      Previous value: -"Seed work identifier. Accepts OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\" or full URL), PMID, or PMCID. Use openalex_resolve_name first if you only have a title."New value: +"Seed work identifier. Accepts OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\" or full URL), PMID (\"12345678\" or \"https://pubmed.ncbi.nlm.nih.gov/12345678\"), or PMCID. Use openalex_resolve_name first if you only have a title."
  6. Changed4 schema fields changed
    • removedOutput schema / properties / meta / properties / next_cursor / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / meta / properties / next_cursor / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / results / items / properties / display_name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / results / items / properties / display_name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  7. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "meta",
      +      "results",
      +      "echo",
      +      "totalCount"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `rate_limited`: OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429). `upstream_budget_exhausted`: The OpenAlex daily usage budget is spent (HTTP 429). `upstream_timeout`: OpenAlex did not respond within the request deadline. `upstream_unavailable`: OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON. `upstream_unauthorized`: OpenAlex rejected the API key (HTTP 401). `upstream_forbidden`: OpenAlex denied access to the requested resource (HTTP 403). `comma_in_filter_value`: A filter value contains a comma, which collides with the OpenAlex filter separator. `upstream_invalid_params`: OpenAlex rejected an invalid filter or sort field name (HTTP 400). `upstream_invalid_id_value`: An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400). `upstream_sort_requires_search`: sort=-relevance_score was used but the citation-graph query has no active search (HTTP 400). `upstream_invalid_params_other`: OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name. `reserved_filter_key`: filters contains cites/cited_by/related_to — the direction parameter reserves those keys. `entity_not_found`: OpenAlex has no work matching the seed_id. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "rate_limited",
      +            "upstream_budget_exhausted",
      +            "upstream_timeout",
      +            "upstream_unavailable",
      +            "upstream_unauthorized",
      +            "upstream_forbidden",
      +            "comma_in_filter_value",
      +            "upstream_invalid_params",
      +            "upstream_invalid_id_value",
      +            "upstream_sort_requires_search",
      +            "upstream_invalid_params_other",
      +            "reserved_filter_key",
      +            "entity_not_found"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "meta",
      -  "results",
      -  "echo",
      -  "totalCount"
      -]
  8. Changed1 schema field changed
    • addedOutput schema / properties / budget / properties / prepaidRemainingUsd
      Added value: +{
      +  "description": "USD left in the prepaid balance — a separate pool OpenAlex draws on only after the daily allowance runs out, and which the daily reset does not refill. Add it to `remainingUsd` for the full spendable amount. Absent when the account holds no prepaid balance.",
      +  "type": "number"
      +}
  9. Changed1 schema field changed
    • addedOutput schema / properties / budget
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "What this call cost against the OpenAlex daily budget and what is left of it. Price a full walk before committing to it: `totalCount` ÷ `per_page` × `costUsd` against `remainingUsd`. Absent when OpenAlex omitted the accounting headers.",
      +  "properties": {
      +    "costUsd": {
      +      "description": "USD this call spent, covering both upstream requests — the seed validation lookup (unbilled) and the graph page itself.",
      +      "type": "number"
      +    },
      +    "remainingUsd": {
      +      "description": "USD left in today's OpenAlex budget after this call.",
      +      "type": "number"
      +    },
      +    "resetsInSeconds": {
      +      "description": "Seconds until the daily budget refills (midnight UTC).",
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "costUsd",
      +    "remainingUsd",
      +    "resetsInSeconds"
      +  ],
      +  "type": "object"
      +}
  10. Changed4 schema fields changed
    • changedInput schema / properties / sort / description
      Previous value: -"Sort field. Prefix with \"-\" for descending. Common: \"cited_by_count\", \"-publication_date\". Default is OpenAlex relevance."New value: +"Sort field. Prefix with \"-\" for descending. Comma-separate for a multi-key sort, applied left to right, with the \"-\" prefix set per key (\"-publication_year,cited_by_count\" sorts by year descending, then citations ascending). Common: \"cited_by_count\", \"-publication_date\". Default is OpenAlex relevance."
    • addedOutput schema / properties / results / items / properties / display_name / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / results / items / properties / display_name / description
      Previous value: -"Work title."New value: +"Work title. null when OpenAlex holds no title for the record (paratext works and other untitled entries) — use `id` to identify it."
    • removedOutput schema / properties / results / items / properties / display_name / type
      Removed value: -"string"
  11. Changed3 schema fields changed
    • addedOutput schema / properties / totalCount
      Added value: +{
      +  "description": "Total edges from seed_id in this direction across all pages.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / totalEdges
      Removed value: -{
      -  "description": "Total edges from seed_id in this direction across all pages.",
      -  "type": "number"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "meta",
      -  "results",
      -  "echo",
      -  "totalEdges"
      -]New value: +[
      +  "meta",
      +  "results",
      +  "echo",
      +  "totalCount"
      +]
  12. Changed1 schema field changed
    • changedOutput schema / properties / echo / description
      Previous value: -"Compact echo of seed_id, direction, filters, sort — useful when no edges are returned so callers see what was actually queried."New value: +"Compact echo of seed_id, direction, filters, sort — surfaces what was actually queried when no edges are returned."
  13. Changed6 schema fields changed
    • addedOutput schema / properties / echo
      Added value: +{
      +  "description": "Compact echo of seed_id, direction, filters, sort — useful when no edges are returned so callers see what was actually queried.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / meta / properties / echo
      Removed value: -{
      -  "description": "Compact echo of seed_id, direction, filters, sort — useful when empty.",
      -  "type": "string"
      -}
    • changedOutput schema / properties / meta / required
      Previous value: -[
      -  "count",
      -  "per_page",
      -  "next_cursor",
      -  "echo"
      -]New value: +[
      +  "count",
      +  "per_page",
      +  "next_cursor"
      +]
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Recovery guidance when no edges are returned — suggests verifying the seed_id, broadening filters, or trying a different direction. Absent when results are present.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / totalEdges
      Added value: +{
      +  "description": "Total edges from seed_id in this direction across all pages.",
      +  "type": "number"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "meta",
      -  "results"
      -]New value: +[
      +  "meta",
      +  "results",
      +  "echo",
      +  "totalEdges"
      +]
  14. Changed1 schema field changed
    • changedInput schema / properties / filters / description
      Previous value: -"Additional filters to narrow the graph, same syntax as openalex_search_entities. Example: publication_year=\">2020\", is_oa=\"true\". The direction filter is added automatically — do not pass cites/cited_by/related_to here."New value: +"Additional filters to narrow the graph, same syntax as openalex_search_entities. Example: publication_year=\">2020\", is_oa=\"true\". Do not include cites/cited_by/related_to — those are set by the `direction` parameter."
  15. Added

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the readOnly/idempotent/openWorld annotations, the description discloses the non-obvious direction-convention inversion, the 64,000-byte response cap with its exception, and the over_budget/omitted/windows truncation signals. These are behavioral traits an agent could not infer from structured fields.

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?

Dense but front-loaded: purpose, edge semantics, the critical inversion caveat, then the budget/continuation mechanics. Every sentence carries information, though the budget/windows clause is compressed enough to require careful reading.

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?

With an output schema present the description needn't explain return fields, and it still covers the truncation behavior, continuation path, seed-ID formats, and filter constraints. For a 7-parameter graph tool this is complete enough to call correctly.

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 value by flagging that 'direction' inverts the common English reading of cites/cited_by and by steering away from PMCIDs. It does not restate every parameter, which is appropriate since the schema already documents them.

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 opening sentence gives a specific verb and resource ('walk the citation graph one hop from a seed work') and immediately distinguishes the three edge types. An agent can tell this apart from openalex_search_entities or openalex_analyze_trends without opening a schema.

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?

It names alternatives and conditions explicitly: use openalex_resolve_name first if you only have a title, and combine with filters/sort to narrow. It also directs the agent to openalex_search_entities for continuation calls, so the when-to-use routing is complete.

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.