/** * @fileoverview One-hop citation graph traversal: cites / cited_by / related_to from a seed work. * @module mcp-server/tools/definitions/citation-graph.tool */ import { z } from '@cyanheads/mcp-ts-core'; import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors'; export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").ToolDefinition; filters: z.ZodOptional>; sort: z.ZodOptional; select: z.ZodOptional>; per_page: z.ZodDefault; cursor: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ meta: z.ZodObject<{ count: z.ZodNumber; per_page: z.ZodNumber; next_cursor: z.ZodNullable; }, z.core.$strip>; results: z.ZodArray; }, z.core.$loose>>; }, z.core.$strip>, readonly [{ readonly reason: "rate_limited"; readonly code: JsonRpcErrorCode.RateLimited; readonly when: "OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429)."; readonly retryable: true; readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller."; }, { readonly reason: "upstream_budget_exhausted"; readonly code: JsonRpcErrorCode.RateLimited; readonly when: "The OpenAlex daily usage budget is spent (HTTP 429)."; readonly retryable: false; readonly recovery: "The daily budget refills at midnight UTC — retrying sooner will not succeed. Set OPENALEX_API_KEY to a free key (https://openalex.org/settings/api) for a larger daily budget than anonymous access, or wait for the reset."; }, { readonly reason: "upstream_timeout"; readonly code: JsonRpcErrorCode.Timeout; readonly when: "OpenAlex did not respond within the request deadline."; readonly retryable: true; readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load."; }, { readonly reason: "upstream_unavailable"; readonly code: JsonRpcErrorCode.ServiceUnavailable; readonly when: "OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON."; readonly retryable: true; readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists."; }, { readonly reason: "upstream_unauthorized"; readonly code: JsonRpcErrorCode.Unauthorized; readonly when: "OpenAlex rejected the API key (HTTP 401)."; readonly recovery: "Check that OPENALEX_API_KEY is set to a valid OpenAlex account API key (free from https://openalex.org/settings/api)."; }, { readonly reason: "upstream_forbidden"; readonly code: JsonRpcErrorCode.Forbidden; readonly when: "OpenAlex denied access to the requested resource (HTTP 403)."; readonly recovery: "Confirm the API key has access to this entity type or endpoint, then retry the request."; }, { readonly reason: "comma_in_filter_value"; readonly code: JsonRpcErrorCode.InvalidParams; readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator."; readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or use a `.search` filter or the `query` parameter for free-text phrases that contain commas."; }, { readonly reason: "upstream_invalid_params"; readonly code: JsonRpcErrorCode.InvalidParams; readonly when: "OpenAlex rejected an invalid filter or sort field name (HTTP 400)."; readonly recovery: "The upstream message names the rejected token and suggests close matches. Pass a valid OpenAlex work ID (W…), DOI, or PMID for seed_id, or use openalex_describe_fields(entity_type, \"filter\") to browse valid filter fields."; }, { readonly reason: "upstream_invalid_id_value"; readonly code: JsonRpcErrorCode.InvalidParams; readonly when: "An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400)."; readonly recovery: "Call openalex_resolve_name to turn the name into an OpenAlex ID, then filter by that ID. Entity filters such as authorships.author.id and primary_topic.id accept IDs only."; }, { readonly reason: "upstream_sort_requires_search"; readonly code: JsonRpcErrorCode.InvalidParams; readonly when: "sort=-relevance_score was used but the citation-graph query has no active search (HTTP 400)."; readonly recovery: "Sorting by relevance_score requires an active search, which a citation-graph walk lacks — choose a concrete sort field such as -cited_by_count or -publication_date, or add a `*.search` filter."; }, { readonly reason: "upstream_invalid_params_other"; readonly code: JsonRpcErrorCode.InvalidParams; readonly when: "OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name."; readonly recovery: "Read the upstream message in the error above and adjust the request — check filter operators, value formats, and cursor/per_page bounds."; }, { readonly reason: "reserved_filter_key"; readonly code: JsonRpcErrorCode.ValidationError; readonly when: "filters contains cites/cited_by/related_to — the direction parameter reserves those keys."; readonly recovery: "Remove the reserved key from filters, or restate the relationship through direction."; }, { readonly reason: "entity_not_found"; readonly code: JsonRpcErrorCode.NotFound; readonly when: "OpenAlex has no work matching the seed_id."; readonly recovery: "Verify seed_id with openalex_resolve_name, or pass a known OpenAlex work ID (W…), DOI, or PMID. OpenAlex indexes no PMCIDs, so convert a PMCID to a PMID or DOI before passing it."; }], { readonly echo: z.ZodString; readonly totalCount: z.ZodNumber; readonly notice: z.ZodOptional; readonly budget: z.ZodOptional; }, z.core.$strip>>; }>; //# sourceMappingURL=citation-graph.tool.d.ts.map