@cyanheads/openalex-mcp-server 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +25 -7
- package/CLAUDE.md +25 -7
- package/Dockerfile +17 -8
- package/README.md +28 -19
- package/changelog/0.10.x/0.10.0.md +30 -0
- package/changelog/0.9.x/0.9.0.md +48 -0
- package/dist/config/server-config.d.ts +2 -0
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +10 -0
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/prompts/definitions/literature-review.prompt.js +1 -1
- package/dist/mcp-server/prompts/definitions/research-landscape.prompt.js +1 -1
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts +35 -4
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.js +86 -41
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts +48 -5
- package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/citation-graph.tool.js +77 -24
- package/dist/mcp-server/tools/definitions/citation-graph.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/describe-fields.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/describe-fields.tool.js +34 -4
- package/dist/mcp-server/tools/definitions/describe-fields.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts +43 -1
- package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/resolve-name.tool.js +182 -40
- package/dist/mcp-server/tools/definitions/resolve-name.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +64 -6
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-entities.tool.js +138 -35
- package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -1
- package/dist/mcp-server/tools/page-size.d.ts +18 -0
- package/dist/mcp-server/tools/page-size.d.ts.map +1 -0
- package/dist/mcp-server/tools/page-size.js +28 -0
- package/dist/mcp-server/tools/page-size.js.map +1 -0
- package/dist/mcp-server/tools/render-budget.d.ts +4 -2
- package/dist/mcp-server/tools/render-budget.d.ts.map +1 -1
- package/dist/mcp-server/tools/render-budget.js +4 -2
- package/dist/mcp-server/tools/render-budget.js.map +1 -1
- package/dist/mcp-server/tools/response-budget.d.ts +3 -3
- package/dist/mcp-server/tools/response-budget.d.ts.map +1 -1
- package/dist/mcp-server/tools/response-budget.js +64 -35
- package/dist/mcp-server/tools/response-budget.js.map +1 -1
- package/dist/services/openalex/budget.d.ts +3 -1
- package/dist/services/openalex/budget.d.ts.map +1 -1
- package/dist/services/openalex/budget.js +3 -1
- package/dist/services/openalex/budget.js.map +1 -1
- package/dist/services/openalex/field-catalog.json +50 -1
- package/dist/services/openalex/filter-values.d.ts +48 -0
- package/dist/services/openalex/filter-values.d.ts.map +1 -0
- package/dist/services/openalex/filter-values.js +350 -0
- package/dist/services/openalex/filter-values.js.map +1 -0
- package/dist/services/openalex/iso-codes.json +1565 -0
- package/dist/services/openalex/openalex-service.d.ts +176 -20
- package/dist/services/openalex/openalex-service.d.ts.map +1 -1
- package/dist/services/openalex/openalex-service.js +573 -127
- package/dist/services/openalex/openalex-service.js.map +1 -1
- package/dist/services/openalex/provider-text.d.ts +7 -6
- package/dist/services/openalex/provider-text.d.ts.map +1 -1
- package/dist/services/openalex/provider-text.js +485 -61
- package/dist/services/openalex/provider-text.js.map +1 -1
- package/dist/services/openalex/types.d.ts +5 -2
- package/dist/services/openalex/types.d.ts.map +1 -1
- package/package.json +14 -12
- package/server.json +35 -21
|
@@ -18,7 +18,7 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
18
18
|
group_by: z.ZodString;
|
|
19
19
|
filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
20
20
|
include_unknown: z.ZodDefault<z.ZodBoolean>;
|
|
21
|
-
per_page: z.ZodDefault<z.ZodNumber
|
|
21
|
+
per_page: z.ZodDefault<z.ZodLazy<z.ZodNumber>>;
|
|
22
22
|
order: z.ZodOptional<z.ZodEnum<{
|
|
23
23
|
count: "count";
|
|
24
24
|
key: "key";
|
|
@@ -32,11 +32,17 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
32
32
|
}, z.core.$strip>;
|
|
33
33
|
groups: z.ZodArray<z.ZodObject<{
|
|
34
34
|
key: z.ZodString;
|
|
35
|
-
key_display_name: z.ZodString
|
|
35
|
+
key_display_name: z.ZodNullable<z.ZodString>;
|
|
36
36
|
count: z.ZodNumber;
|
|
37
37
|
is_unknown: z.ZodOptional<z.ZodLiteral<true>>;
|
|
38
38
|
}, z.core.$strip>>;
|
|
39
39
|
}, z.core.$strip>, readonly [{
|
|
40
|
+
readonly reason: "unmatched_quote_in_filter_value";
|
|
41
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
42
|
+
readonly when: "A filter value sent unquoted has an unmatched double quote.";
|
|
43
|
+
readonly recovery: "Pair double quotes used for a search phrase, or remove the stray quote.";
|
|
44
|
+
readonly thrownBy: "service";
|
|
45
|
+
}, {
|
|
40
46
|
readonly reason: "rate_limited";
|
|
41
47
|
readonly code: JsonRpcErrorCode.RateLimited;
|
|
42
48
|
readonly when: "OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429).";
|
|
@@ -50,6 +56,13 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
50
56
|
readonly retryable: false;
|
|
51
57
|
readonly recovery: "This server's daily OpenAlex budget is spent and refills at midnight UTC — retrying before then will not succeed.";
|
|
52
58
|
readonly thrownBy: "service";
|
|
59
|
+
}, {
|
|
60
|
+
readonly reason: "upstream_plan_required";
|
|
61
|
+
readonly code: JsonRpcErrorCode.Forbidden;
|
|
62
|
+
readonly when: "A filter is one OpenAlex serves only on a paid plan — created_date, updated_date, or a from_/to_ form of either (HTTP 429 \"Plan upgrade required\").";
|
|
63
|
+
readonly retryable: false;
|
|
64
|
+
readonly recovery: "Drop the plan-gated filter and rerun; retrying it unchanged will not succeed. To bound works by date, filter on publication_date, from_publication_date, or to_publication_date, which need no paid plan.";
|
|
65
|
+
readonly thrownBy: "service";
|
|
53
66
|
}, {
|
|
54
67
|
readonly reason: "upstream_timeout";
|
|
55
68
|
readonly code: JsonRpcErrorCode.Timeout;
|
|
@@ -79,8 +92,26 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
79
92
|
}, {
|
|
80
93
|
readonly reason: "comma_in_filter_value";
|
|
81
94
|
readonly code: JsonRpcErrorCode.InvalidParams;
|
|
82
|
-
readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator.";
|
|
83
|
-
readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or
|
|
95
|
+
readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator, on a field that takes no phrase. Free-text search filters (any `.search` key, such as title.search or abstract.search.exact) and fields matched as whole text (display_name, awards.funder_display_name, awards.funder_award_id, geo.city, geo.region, raw_affiliation_strings, block_key, parsed_longest_name, biblio fields) are exempt: a comma there is sent quoted, as part of the phrase.";
|
|
96
|
+
readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or move a phrase that contains commas into a free-text search filter such as title.search or raw_affiliation_strings.search.";
|
|
97
|
+
readonly thrownBy: "service";
|
|
98
|
+
}, {
|
|
99
|
+
readonly reason: "invalid_country_code";
|
|
100
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
101
|
+
readonly when: "A country filter (a key ending in country_code, country_codes, or countries) holds a segment that cannot be a country code, such as a misspelled name, an unassigned number, \"unknown\", or two codes joined by a space (\"DE US\").";
|
|
102
|
+
readonly recovery: "Pass the country as an ISO 3166-1 alpha-2 code such as DE, US, or GB (an alpha-3 code, numeric code, or English name is converted), or null for records with no country.";
|
|
103
|
+
readonly thrownBy: "service";
|
|
104
|
+
}, {
|
|
105
|
+
readonly reason: "mixed_and_or_in_filter_value";
|
|
106
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
107
|
+
readonly when: "A filter value puts \"|\" (OR) beside an AND operator — a \"+\", or a space on a field where words mean AND (on a country field a space is always part of a country name, and inside a language name it is part of the name). OpenAlex splits the value on \"|\" first and drops every alternative that ANDs more than one value, so no single value can carry both.";
|
|
108
|
+
readonly recovery: "Keep \"|\" and the AND operator in separate filter keys: OR the alternatives in this key and put the AND in a second key that reaches the same values — on works, {\"authorships.institutions.country_code\": \"DE|FR\", \"institutions.country_code\": \"US\"} matches (DE or FR) and US. The filters object holds each key once, so where no second key fits, run one call per alternative instead.";
|
|
109
|
+
readonly thrownBy: "service";
|
|
110
|
+
}, {
|
|
111
|
+
readonly reason: "quote_in_filter_value";
|
|
112
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
113
|
+
readonly when: "A filter value sent to OpenAlex double-quoted holds a double quote inside its outer pair — a value the server quotes (a multi-word value on a field matched as whole text, or a value holding a comma on such a field or on a free-text search filter), or one the caller wrapped in double quotes on any filter but a free-text search.";
|
|
114
|
+
readonly recovery: "Remove the double quote from the value; a phrase is matched without quoting its own text.";
|
|
84
115
|
readonly thrownBy: "service";
|
|
85
116
|
}, {
|
|
86
117
|
readonly reason: "upstream_invalid_params";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-trends.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"analyze-trends.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAgBjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkZ5B,CAAC"}
|
|
@@ -5,17 +5,27 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { escapeMarkdown } from '../escape-markdown.js';
|
|
8
|
+
import { clampPageSize, pageSizeSchema } from '../page-size.js';
|
|
8
9
|
import { renderBudgetTrailer } from '../render-budget.js';
|
|
9
10
|
import { joinNotices } from '../response-budget.js';
|
|
10
|
-
import { getOpenAlexService } from '../../../services/openalex/openalex-service.js';
|
|
11
|
+
import { getOpenAlexService, isBooleanGroupBy } from '../../../services/openalex/openalex-service.js';
|
|
11
12
|
import { ENTITY_TYPES } from '../../../services/openalex/types.js';
|
|
12
13
|
/** Disclosure for a works group_by over `authorships.countries` (see the handler). */
|
|
13
14
|
const COUNTRIES_CAP_NOTICE = 'OpenAlex builds authorships.countries groups from only the first 100 authorships of each work, so a country that appears only past position 100 on a large collaboration is not counted. Group by authorships.institutions.country_code to count every authorship.';
|
|
15
|
+
/** Upstream cursors can wrap even after a short page; callers own the stopping decision. */
|
|
16
|
+
const KEY_ORDER_GUIDANCE = "OpenAlex can wrap a key-ordered walk to earlier groups. Stop when a page's first key repeats an earlier key, or when a page is short or empty.";
|
|
14
17
|
export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
15
|
-
description:
|
|
18
|
+
description: `Aggregate OpenAlex entities into groups and count them. Use for trend analysis (group works by publication_year), distribution analysis (group by oa_status, type, country), and comparative analysis (group by institution or topic). Combine with filters to scope the analysis. Returns up to 200 groups per page — use order "key" and cursor pagination for fields with many distinct values. ${KEY_ORDER_GUIDANCE}`,
|
|
16
19
|
sourceUrl: 'https://github.com/cyanheads/openalex-mcp-server/blob/main/src/mcp-server/tools/definitions/analyze-trends.tool.ts',
|
|
17
20
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
18
21
|
errors: [
|
|
22
|
+
{
|
|
23
|
+
reason: 'unmatched_quote_in_filter_value',
|
|
24
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
25
|
+
when: 'A filter value sent unquoted has an unmatched double quote.',
|
|
26
|
+
recovery: 'Pair double quotes used for a search phrase, or remove the stray quote.',
|
|
27
|
+
thrownBy: 'service',
|
|
28
|
+
},
|
|
19
29
|
{
|
|
20
30
|
reason: 'rate_limited',
|
|
21
31
|
code: JsonRpcErrorCode.RateLimited,
|
|
@@ -32,6 +42,14 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
32
42
|
recovery: "This server's daily OpenAlex budget is spent and refills at midnight UTC — retrying before then will not succeed.",
|
|
33
43
|
thrownBy: 'service',
|
|
34
44
|
},
|
|
45
|
+
{
|
|
46
|
+
reason: 'upstream_plan_required',
|
|
47
|
+
code: JsonRpcErrorCode.Forbidden,
|
|
48
|
+
when: 'A filter is one OpenAlex serves only on a paid plan — created_date, updated_date, or a from_/to_ form of either (HTTP 429 "Plan upgrade required").',
|
|
49
|
+
retryable: false,
|
|
50
|
+
recovery: 'Drop the plan-gated filter and rerun; retrying it unchanged will not succeed. To bound works by date, filter on publication_date, from_publication_date, or to_publication_date, which need no paid plan.',
|
|
51
|
+
thrownBy: 'service',
|
|
52
|
+
},
|
|
35
53
|
{
|
|
36
54
|
reason: 'upstream_timeout',
|
|
37
55
|
code: JsonRpcErrorCode.Timeout,
|
|
@@ -65,8 +83,29 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
65
83
|
{
|
|
66
84
|
reason: 'comma_in_filter_value',
|
|
67
85
|
code: JsonRpcErrorCode.InvalidParams,
|
|
68
|
-
when: 'A filter value contains a comma, which collides with the OpenAlex filter separator.',
|
|
69
|
-
recovery: 'Use `|` for OR within a filter value (e.g. "2020|2021"), or
|
|
86
|
+
when: 'A filter value contains a comma, which collides with the OpenAlex filter separator, on a field that takes no phrase. Free-text search filters (any `.search` key, such as title.search or abstract.search.exact) and fields matched as whole text (display_name, awards.funder_display_name, awards.funder_award_id, geo.city, geo.region, raw_affiliation_strings, block_key, parsed_longest_name, biblio fields) are exempt: a comma there is sent quoted, as part of the phrase.',
|
|
87
|
+
recovery: 'Use `|` for OR within a filter value (e.g. "2020|2021"), or move a phrase that contains commas into a free-text search filter such as title.search or raw_affiliation_strings.search.',
|
|
88
|
+
thrownBy: 'service',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
reason: 'invalid_country_code',
|
|
92
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
93
|
+
when: 'A country filter (a key ending in country_code, country_codes, or countries) holds a segment that cannot be a country code, such as a misspelled name, an unassigned number, "unknown", or two codes joined by a space ("DE US").',
|
|
94
|
+
recovery: 'Pass the country as an ISO 3166-1 alpha-2 code such as DE, US, or GB (an alpha-3 code, numeric code, or English name is converted), or null for records with no country.',
|
|
95
|
+
thrownBy: 'service',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
reason: 'mixed_and_or_in_filter_value',
|
|
99
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
100
|
+
when: 'A filter value puts "|" (OR) beside an AND operator — a "+", or a space on a field where words mean AND (on a country field a space is always part of a country name, and inside a language name it is part of the name). OpenAlex splits the value on "|" first and drops every alternative that ANDs more than one value, so no single value can carry both.',
|
|
101
|
+
recovery: 'Keep "|" and the AND operator in separate filter keys: OR the alternatives in this key and put the AND in a second key that reaches the same values — on works, {"authorships.institutions.country_code": "DE|FR", "institutions.country_code": "US"} matches (DE or FR) and US. The filters object holds each key once, so where no second key fits, run one call per alternative instead.',
|
|
102
|
+
thrownBy: 'service',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
reason: 'quote_in_filter_value',
|
|
106
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
107
|
+
when: 'A filter value sent to OpenAlex double-quoted holds a double quote inside its outer pair — a value the server quotes (a multi-word value on a field matched as whole text, or a value holding a comma on such a field or on a free-text search filter), or one the caller wrapped in double quotes on any filter but a free-text search.',
|
|
108
|
+
recovery: 'Remove the double quote from the value; a phrase is matched without quoting its own text.',
|
|
70
109
|
thrownBy: 'service',
|
|
71
110
|
},
|
|
72
111
|
{
|
|
@@ -119,31 +158,27 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
119
158
|
group_by: z
|
|
120
159
|
.string()
|
|
121
160
|
.min(1)
|
|
122
|
-
.describe('Field to group by. Works examples: "publication_year", "type", "oa_status", "primary_topic.field.id", "authorships.institutions.country_code", "is_retracted". OpenAlex builds authorships.countries groups from only the first 100 authorships of each work; authorships.institutions.country_code counts every authorship. Authors: "last_known_institutions.country_code", "has_orcid". Sources: "type", "is_oa", "country_code". Not all fields support group_by — call openalex_describe_fields(entity_type, "group_by") for the groupable set.'),
|
|
161
|
+
.describe('Field to group by. Works examples: "publication_year", "type", "oa_status", "primary_topic.field.id", "authorships.institutions.country_code", "is_retracted". The native ":include_unknown" suffix also enables include_unknown, even when the boolean is false; passing both adds the suffix once. OpenAlex builds authorships.countries groups from only the first 100 authorships of each work; authorships.institutions.country_code counts every authorship. Authors: "last_known_institutions.country_code", "has_orcid". Sources: "type", "is_oa", "country_code". Not all fields support group_by — call openalex_describe_fields(entity_type, "group_by") for the groupable set.'),
|
|
123
162
|
filters: z
|
|
124
163
|
.record(z.string(), z.string())
|
|
125
164
|
.optional()
|
|
126
|
-
.describe(
|
|
165
|
+
.describe('Filter record object, using the same value syntax as openalex_search_entities; native string input is unavailable here. Narrows the population before aggregation. Country fields take ISO 3166-1 alpha-2 codes ("DE") and `language` takes ISO 639-1 codes ("en"); alpha-3, numeric, ISO 639-2, and English-name forms are converted — a multi-word name is one value, so "South Korea|Japan" ORs two countries — and a value that cannot be a country code is rejected. A multi-word value on a field matched as whole text (display_name, awards.funder_display_name, geo.city, raw_affiliation_strings) matches as one phrase ("National Science Foundation"; a comma, as in "University of California, Berkeley", is part of it, and it cannot contain a double quote of its own), "!" and "|" included, but cannot be ANDed with "+" in the same field. A value sent unquoted must have paired double quotes; balanced search phrases remain valid. A value mixing "|" with an AND operator — a "+", or a space on a field where words mean AND — is rejected, since OpenAlex drops every "|" alternative that ANDs more than one value; put the AND in a second key instead. For full-text within filters, use abstract.search, title.search, or default.search — there is no bare \'search\' filter key. Example: group works by year filtered to a specific topic.'),
|
|
127
166
|
include_unknown: z
|
|
128
167
|
.boolean()
|
|
129
168
|
.default(false)
|
|
130
|
-
.describe('Add a group for entities with no value for the grouped field. Hidden by default. That group carries `is_unknown: true`; OpenAlex keys it -111 or -111.0 on numeric fields, "unknown" on text fields and under order "key", and an ID ending in /unknown on ID fields — a sentinel, not a measured value. The key is not a filter value: passing -111 as a filter matches a numeric range, not the entities with no value. Boolean fields have no separate group — a missing value counts as false.'),
|
|
131
|
-
per_page:
|
|
132
|
-
.number()
|
|
133
|
-
.int()
|
|
134
|
-
.min(1)
|
|
135
|
-
.max(200)
|
|
169
|
+
.describe('Add a group for entities with no value for the grouped field. Hidden by default unless group_by has the native ":include_unknown" suffix, which enables this setting even when the boolean is false; passing both adds the suffix once. That group carries `is_unknown: true`; OpenAlex keys it -111 or -111.0 on numeric fields, "unknown" on text fields and under order "key", and an ID ending in /unknown on ID fields — a sentinel, not a measured value. The key is not a filter value: passing -111 as a filter matches a numeric range, not the entities with no value. Boolean fields have no separate group — a missing value counts as false.'),
|
|
170
|
+
per_page: pageSizeSchema(200)
|
|
136
171
|
.default(200)
|
|
137
|
-
.describe('Maximum groups per page
|
|
172
|
+
.describe('Maximum groups per page. Default 200 (the upstream cap); positive integers above 200 clamp to 200 with a notice unless OPENALEX_CLAMP_PER_PAGE=false restores rejection. A real top-N knob in count order without a cursor (the default) — reduce to return only the highest-count groups.'),
|
|
138
173
|
order: z
|
|
139
174
|
.enum(['count', 'key'])
|
|
140
175
|
.optional()
|
|
141
|
-
.describe(
|
|
176
|
+
.describe(`Sort order for groups. Without a cursor, omit or pass "count" (default) to return the top-N groups by count descending — no further pages. Pass "key" to enumerate distinct values in key-ascending order with cursor pagination. Boolean fields keep count order even with "key" and do not support cursor pagination. A supplied cursor selects key order even if order is omitted or "count". ${KEY_ORDER_GUIDANCE}`),
|
|
142
177
|
cursor: z
|
|
143
178
|
.string()
|
|
144
179
|
.min(1)
|
|
145
180
|
.optional()
|
|
146
|
-
.describe(
|
|
181
|
+
.describe(`Pagination cursor from a previous response. A supplied cursor selects key order even if order is omitted or "count". Pass the next_cursor from the previous response to advance, subject to the stop conditions below. 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. ${KEY_ORDER_GUIDANCE}`),
|
|
147
182
|
}),
|
|
148
183
|
output: z.object({
|
|
149
184
|
meta: z
|
|
@@ -153,7 +188,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
153
188
|
next_cursor: z
|
|
154
189
|
.string()
|
|
155
190
|
.nullable()
|
|
156
|
-
.describe(
|
|
191
|
+
.describe(`Upstream continuation cursor; null when OpenAlex supplies none. A non-null cursor does not guarantee unseen groups. ${KEY_ORDER_GUIDANCE}`),
|
|
157
192
|
})
|
|
158
193
|
.describe('Aggregation metadata.'),
|
|
159
194
|
groups: z
|
|
@@ -164,7 +199,8 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
164
199
|
.describe('Group key (OpenAlex ID or raw value), exactly as OpenAlex returns it.'),
|
|
165
200
|
key_display_name: z
|
|
166
201
|
.string()
|
|
167
|
-
.
|
|
202
|
+
.nullable()
|
|
203
|
+
.describe('Human-readable group label as plain text, with HTML entities decoded and markup removed; null when OpenAlex supplies no label. Text output uses the group key when the label is null.'),
|
|
168
204
|
count: z.number().describe('Number of entities in this group.'),
|
|
169
205
|
is_unknown: z
|
|
170
206
|
.literal(true)
|
|
@@ -180,14 +216,14 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
180
216
|
enrichment: {
|
|
181
217
|
echo: z
|
|
182
218
|
.string()
|
|
183
|
-
.describe('Compact echo of the
|
|
219
|
+
.describe('Compact echo of the criteria (entity_type, group_by, filters) and effective include_unknown and order settings — surfaces what was actually requested when no groups are returned.'),
|
|
184
220
|
totalCount: z
|
|
185
221
|
.number()
|
|
186
222
|
.describe('Total entities matching the filters before grouping (across all pages).'),
|
|
187
223
|
notice: z
|
|
188
224
|
.string()
|
|
189
225
|
.optional()
|
|
190
|
-
.describe('Guidance notice. Set when a first call returns no groups (recovery suggestions), when a
|
|
226
|
+
.describe('Guidance notice. Set when per_page was clamped (requested and applied sizes), on every effective key-order call (upstream wrap warning and stopping conditions), when a first call returns no groups (recovery suggestions), when a cursor continuation returns none because the traversal is already finished, when a count-order page is full and more groups likely exist (truncation signal with narrowing advice), or when works are grouped by authorships.countries, which OpenAlex counts from only the first 100 authorships of each work. Absent otherwise.'),
|
|
191
227
|
budget: z
|
|
192
228
|
.object({
|
|
193
229
|
costUsd: z
|
|
@@ -211,13 +247,14 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
211
247
|
budget: { render: renderBudgetTrailer },
|
|
212
248
|
},
|
|
213
249
|
async handler(input, ctx) {
|
|
250
|
+
const pageSize = clampPageSize(input.per_page, 200, 'openalex_analyze_trends', ctx);
|
|
214
251
|
const service = getOpenAlexService();
|
|
215
252
|
const result = await service.analyze({
|
|
216
253
|
entityType: input.entity_type,
|
|
217
254
|
groupBy: input.group_by,
|
|
218
255
|
filters: input.filters,
|
|
219
256
|
includeUnknown: input.include_unknown,
|
|
220
|
-
perPage:
|
|
257
|
+
perPage: pageSize.applied,
|
|
221
258
|
order: input.order,
|
|
222
259
|
cursor: input.cursor,
|
|
223
260
|
}, ctx);
|
|
@@ -227,10 +264,13 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
227
264
|
totalCount: result.meta.count,
|
|
228
265
|
groupCount: result.groups.length,
|
|
229
266
|
});
|
|
230
|
-
const
|
|
267
|
+
const keyOrder = input.cursor !== undefined || (input.order === 'key' && !isBooleanGroupBy(input.group_by));
|
|
268
|
+
const echo = buildAnalyzeEcho(input, keyOrder);
|
|
231
269
|
ctx.enrich({ echo, totalCount: result.meta.count });
|
|
232
270
|
// `notice` is last-wins, so every sentence is collected and set once.
|
|
233
271
|
const notices = [];
|
|
272
|
+
if (pageSize.notice)
|
|
273
|
+
notices.push(pageSize.notice);
|
|
234
274
|
// An empty page on a `cursor` continuation means the key-ascending traversal already
|
|
235
275
|
// enumerated every group, so there is nothing left to remove or regroup. On a first call
|
|
236
276
|
// the same shape can still be an honest zero — including the all-values-unknown case,
|
|
@@ -240,16 +280,13 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
240
280
|
? `No groups returned for ${echo}. Try removing filters or grouping by a different field.`
|
|
241
281
|
: `Pagination exhausted for ${echo} — the previous page held the last group, so this one came back empty. Stop paging rather than removing filters or regrouping.`);
|
|
242
282
|
}
|
|
243
|
-
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (result.meta.next_cursor) {
|
|
249
|
-
notices.push(`Showing ${result.groups.length} groups in key-ascending order. Pass the returned \`next_cursor\` to continue the traversal.`);
|
|
250
|
-
}
|
|
283
|
+
if (keyOrder) {
|
|
284
|
+
// A cursor selects key order regardless of `order`; upstream can wrap without suppressing it.
|
|
285
|
+
notices.push(result.groups.length === 0
|
|
286
|
+
? KEY_ORDER_GUIDANCE
|
|
287
|
+
: `Showing ${result.groups.length} groups in key-ascending order. ${KEY_ORDER_GUIDANCE}${result.meta.next_cursor ? ' Otherwise, pass the returned `next_cursor` to continue the traversal.' : ''}`);
|
|
251
288
|
}
|
|
252
|
-
else if (result.groups.length ===
|
|
289
|
+
else if (result.groups.length > 0 && result.groups.length === pageSize.applied) {
|
|
253
290
|
// Count-desc (the default): the page is filled to the limit, so more distinct groups likely
|
|
254
291
|
// exist. The omitted groups all have counts ≤ the smallest group shown, so we can bound the
|
|
255
292
|
// gap even though OpenAlex exposes no total group count.
|
|
@@ -279,11 +316,14 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
279
316
|
},
|
|
280
317
|
format: (result) => {
|
|
281
318
|
const heading = `${result.meta.count} total entities across ${result.meta.groups_count ?? result.groups.length} groups on this page`;
|
|
319
|
+
const footer = result.meta.next_cursor
|
|
320
|
+
? `\n\nUpstream next_cursor: \`${result.meta.next_cursor}\`. ${KEY_ORDER_GUIDANCE}`
|
|
321
|
+
: '';
|
|
282
322
|
if (result.groups.length === 0) {
|
|
283
323
|
return [
|
|
284
324
|
{
|
|
285
325
|
type: 'text',
|
|
286
|
-
text: `No groups found. (count=${result.meta.count}, groups_count=${result.meta.groups_count ?? 0})`,
|
|
326
|
+
text: `No groups found. (count=${result.meta.count}, groups_count=${result.meta.groups_count ?? 0})${footer}`,
|
|
287
327
|
},
|
|
288
328
|
];
|
|
289
329
|
}
|
|
@@ -298,9 +338,6 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
298
338
|
]
|
|
299
339
|
: result.groups;
|
|
300
340
|
const lines = renderOrder.map((g) => `${renderGroupLabel(g)}: ${g.count}`);
|
|
301
|
-
const footer = result.meta.next_cursor
|
|
302
|
-
? `\n\n*More groups available — next_cursor: \`${result.meta.next_cursor}\`*`
|
|
303
|
-
: '';
|
|
304
341
|
return [
|
|
305
342
|
{
|
|
306
343
|
type: 'text',
|
|
@@ -322,22 +359,30 @@ function isTimeSeriesGrouping(groups) {
|
|
|
322
359
|
function renderGroupLabel(g) {
|
|
323
360
|
const key = escapeMarkdown(g.key);
|
|
324
361
|
if (g.is_unknown) {
|
|
325
|
-
const
|
|
326
|
-
|
|
362
|
+
const label = g.key_display_name === null ||
|
|
363
|
+
g.key_display_name === g.key ||
|
|
364
|
+
g.key_display_name.toLowerCase() === 'unknown'
|
|
365
|
+
? ''
|
|
366
|
+
: `, label ${escapeMarkdown(g.key_display_name)}`;
|
|
327
367
|
return `unknown (no value; key ${key}${label})`;
|
|
328
368
|
}
|
|
369
|
+
if (g.key_display_name === null)
|
|
370
|
+
return escapeMarkdown(g.key, 'line-start');
|
|
329
371
|
const display = escapeMarkdown(g.key_display_name, 'line-start');
|
|
330
372
|
return g.key === g.key_display_name ? display : `${display} (${key})`;
|
|
331
373
|
}
|
|
332
|
-
|
|
333
|
-
|
|
374
|
+
/** The request as one line: caller text is JSON-encoded, so a line break in it stays escaped. */
|
|
375
|
+
function buildAnalyzeEcho(input, keyOrder) {
|
|
376
|
+
const parts = [`entity_type=${input.entity_type}`, `group_by=${JSON.stringify(input.group_by)}`];
|
|
334
377
|
if (input.filters && Object.keys(input.filters).length > 0) {
|
|
335
378
|
parts.push(`filters=${JSON.stringify(input.filters)}`);
|
|
336
379
|
}
|
|
337
|
-
if (input.include_unknown)
|
|
380
|
+
if (input.include_unknown || input.group_by.endsWith(':include_unknown'))
|
|
338
381
|
parts.push('include_unknown=true');
|
|
339
|
-
if (
|
|
340
|
-
parts.push(
|
|
382
|
+
if (keyOrder)
|
|
383
|
+
parts.push('order=key');
|
|
384
|
+
else if (input.order)
|
|
385
|
+
parts.push('order=count');
|
|
341
386
|
return parts.join(' | ');
|
|
342
387
|
}
|
|
343
388
|
//# sourceMappingURL=analyze-trends.tool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-trends.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"analyze-trends.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
14
14
|
filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
15
15
|
sort: z.ZodOptional<z.ZodString>;
|
|
16
16
|
select: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
17
|
-
per_page: z.ZodDefault<z.ZodNumber
|
|
17
|
+
per_page: z.ZodDefault<z.ZodLazy<z.ZodNumber>>;
|
|
18
18
|
cursor: z.ZodOptional<z.ZodString>;
|
|
19
19
|
}, z.core.$strip>, z.ZodObject<{
|
|
20
20
|
meta: z.ZodObject<{
|
|
@@ -47,6 +47,12 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
47
47
|
}, z.core.$strip>>>;
|
|
48
48
|
over_budget: z.ZodOptional<z.ZodBoolean>;
|
|
49
49
|
}, z.core.$strip>, readonly [{
|
|
50
|
+
readonly reason: "unmatched_quote_in_filter_value";
|
|
51
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
52
|
+
readonly when: "A filter value sent unquoted has an unmatched double quote.";
|
|
53
|
+
readonly recovery: "Pair double quotes used for a search phrase, or remove the stray quote.";
|
|
54
|
+
readonly thrownBy: "service";
|
|
55
|
+
}, {
|
|
50
56
|
readonly reason: "rate_limited";
|
|
51
57
|
readonly code: JsonRpcErrorCode.RateLimited;
|
|
52
58
|
readonly when: "OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429).";
|
|
@@ -60,6 +66,13 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
60
66
|
readonly retryable: false;
|
|
61
67
|
readonly recovery: "This server's daily OpenAlex budget is spent and refills at midnight UTC — retrying before then will not succeed.";
|
|
62
68
|
readonly thrownBy: "service";
|
|
69
|
+
}, {
|
|
70
|
+
readonly reason: "upstream_plan_required";
|
|
71
|
+
readonly code: JsonRpcErrorCode.Forbidden;
|
|
72
|
+
readonly when: "A filter is one OpenAlex serves only on a paid plan — created_date, updated_date, or a from_/to_ form of either (HTTP 429 \"Plan upgrade required\").";
|
|
73
|
+
readonly retryable: false;
|
|
74
|
+
readonly recovery: "Drop the plan-gated filter and rerun; retrying it unchanged will not succeed. To bound works by date, filter on publication_date, from_publication_date, or to_publication_date, which need no paid plan.";
|
|
75
|
+
readonly thrownBy: "service";
|
|
63
76
|
}, {
|
|
64
77
|
readonly reason: "upstream_timeout";
|
|
65
78
|
readonly code: JsonRpcErrorCode.Timeout;
|
|
@@ -89,14 +102,32 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
89
102
|
}, {
|
|
90
103
|
readonly reason: "comma_in_filter_value";
|
|
91
104
|
readonly code: JsonRpcErrorCode.InvalidParams;
|
|
92
|
-
readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator.";
|
|
93
|
-
readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or
|
|
105
|
+
readonly when: "A filter value contains a comma, which collides with the OpenAlex filter separator, on a field that takes no phrase. Free-text search filters (any `.search` key, such as title.search or abstract.search.exact) and fields matched as whole text (display_name, awards.funder_display_name, awards.funder_award_id, authorships.institutions.geo.city, authorships.institutions.geo.region, raw_affiliation_strings, biblio fields) are exempt: a comma there is sent quoted, as part of the phrase.";
|
|
106
|
+
readonly recovery: "Use `|` for OR within a filter value (e.g. \"2020|2021\"), or move a phrase that contains commas into a free-text search filter such as title.search or raw_affiliation_strings.search.";
|
|
107
|
+
readonly thrownBy: "service";
|
|
108
|
+
}, {
|
|
109
|
+
readonly reason: "invalid_country_code";
|
|
110
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
111
|
+
readonly when: "A country filter (a key ending in country_code, country_codes, or countries) holds a segment that cannot be a country code, such as a misspelled name, an unassigned number, \"unknown\", or two codes joined by a space (\"DE US\").";
|
|
112
|
+
readonly recovery: "Pass the country as an ISO 3166-1 alpha-2 code such as DE, US, or GB (an alpha-3 code, numeric code, or English name is converted), or null for works with no country.";
|
|
113
|
+
readonly thrownBy: "service";
|
|
114
|
+
}, {
|
|
115
|
+
readonly reason: "mixed_and_or_in_filter_value";
|
|
116
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
117
|
+
readonly when: "A filter value puts \"|\" (OR) beside an AND operator — a \"+\", or a space on a field where words mean AND (on a country field a space is always part of a country name, and inside a language name it is part of the name). OpenAlex splits the value on \"|\" first and drops every alternative that ANDs more than one value, so no single value can carry both.";
|
|
118
|
+
readonly recovery: "Keep \"|\" and the AND operator in separate filter keys: OR the alternatives in this key and put the AND in a second key that reaches the same values — {\"authorships.institutions.country_code\": \"DE|FR\", \"institutions.country_code\": \"US\"} matches works with (DE or FR) and US. The filters object holds each key once, so where no second key fits, run one call per alternative instead.";
|
|
119
|
+
readonly thrownBy: "service";
|
|
120
|
+
}, {
|
|
121
|
+
readonly reason: "quote_in_filter_value";
|
|
122
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
123
|
+
readonly when: "A filter value sent to OpenAlex double-quoted holds a double quote inside its outer pair — a value the server quotes (a multi-word value on a field matched as whole text, or a value holding a comma on such a field or on a free-text search filter), or one the caller wrapped in double quotes on any filter but a free-text search.";
|
|
124
|
+
readonly recovery: "Remove the double quote from the value; a phrase is matched without quoting its own text.";
|
|
94
125
|
readonly thrownBy: "service";
|
|
95
126
|
}, {
|
|
96
127
|
readonly reason: "upstream_invalid_params";
|
|
97
128
|
readonly code: JsonRpcErrorCode.InvalidParams;
|
|
98
|
-
readonly when: "OpenAlex rejected an invalid filter or sort field name (HTTP 400).";
|
|
99
|
-
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,
|
|
129
|
+
readonly when: "OpenAlex rejected an invalid filter, select, or sort field name (HTTP 400).";
|
|
130
|
+
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, and browse the valid work fields with openalex_describe_fields(\"works\", \"filter\") for filters or openalex_describe_fields(\"works\", \"select\") for select.";
|
|
100
131
|
readonly thrownBy: "service";
|
|
101
132
|
}, {
|
|
102
133
|
readonly reason: "upstream_invalid_id_value";
|
|
@@ -121,6 +152,18 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
121
152
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
122
153
|
readonly when: "filters contains cites/cited_by/related_to, or an alias of one such as cited_works — the direction parameter reserves those keys.";
|
|
123
154
|
readonly recovery: "Remove the reserved key from filters, or restate the relationship through direction.";
|
|
155
|
+
}, {
|
|
156
|
+
readonly reason: "id_type_mismatch";
|
|
157
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
158
|
+
readonly when: "seed_id is a native OpenAlex ID of another entity type — an author, source, institution, topic, publisher, funder, or concept ID rather than a work ID.";
|
|
159
|
+
readonly recovery: "seed_id must identify a work — pass the work's OpenAlex ID (W…), DOI, or PMID. To walk the works of an author or other entity, list them first with openalex_search_entities filters.";
|
|
160
|
+
readonly thrownBy: "service";
|
|
161
|
+
}, {
|
|
162
|
+
readonly reason: "id_dot_segment";
|
|
163
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
164
|
+
readonly when: "seed_id holds a `.` or `..` path segment, written plainly or percent-encoded.";
|
|
165
|
+
readonly recovery: "Pass the work's identifier itself — its OpenAlex ID (W…), DOI, or PMID — with no relative path segments.";
|
|
166
|
+
readonly thrownBy: "service";
|
|
124
167
|
}, {
|
|
125
168
|
readonly reason: "entity_not_found";
|
|
126
169
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citation-graph.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"citation-graph.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA2CjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6Z/B,CAAC"}
|