@cyanheads/openalex-mcp-server 0.10.0 → 0.11.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.
Files changed (64) hide show
  1. package/AGENTS.md +30 -15
  2. package/CLAUDE.md +30 -15
  3. package/Dockerfile +6 -0
  4. package/README.md +55 -116
  5. package/changelog/0.10.x/0.10.1.md +28 -0
  6. package/changelog/0.11.x/0.11.0.md +41 -0
  7. package/dist/config/server-config.d.ts.map +1 -1
  8. package/dist/config/server-config.js +1 -1
  9. package/dist/config/server-config.js.map +1 -1
  10. package/dist/index.js +2 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp-server/prompts/definitions/literature-review.prompt.js +1 -1
  13. package/dist/mcp-server/prompts/definitions/research-landscape.prompt.js +1 -1
  14. package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts +1 -0
  15. package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/analyze-trends.tool.js +10 -5
  17. package/dist/mcp-server/tools/definitions/analyze-trends.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts +6 -9
  19. package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/citation-graph.tool.js +43 -33
  21. package/dist/mcp-server/tools/definitions/citation-graph.tool.js.map +1 -1
  22. package/dist/mcp-server/tools/definitions/describe-fields.tool.d.ts +1 -0
  23. package/dist/mcp-server/tools/definitions/describe-fields.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/definitions/describe-fields.tool.js +25 -1
  25. package/dist/mcp-server/tools/definitions/describe-fields.tool.js.map +1 -1
  26. package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/resolve-name.tool.js +44 -16
  28. package/dist/mcp-server/tools/definitions/resolve-name.tool.js.map +1 -1
  29. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +22 -18
  30. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -1
  31. package/dist/mcp-server/tools/definitions/search-entities.tool.js +194 -85
  32. package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -1
  33. package/dist/mcp-server/tools/escape-markdown.d.ts +26 -11
  34. package/dist/mcp-server/tools/escape-markdown.d.ts.map +1 -1
  35. package/dist/mcp-server/tools/escape-markdown.js +95 -26
  36. package/dist/mcp-server/tools/escape-markdown.js.map +1 -1
  37. package/dist/mcp-server/tools/page-size.d.ts +38 -7
  38. package/dist/mcp-server/tools/page-size.d.ts.map +1 -1
  39. package/dist/mcp-server/tools/page-size.js +37 -11
  40. package/dist/mcp-server/tools/page-size.js.map +1 -1
  41. package/dist/mcp-server/tools/record-page.d.ts +174 -0
  42. package/dist/mcp-server/tools/record-page.d.ts.map +1 -0
  43. package/dist/mcp-server/tools/record-page.js +392 -0
  44. package/dist/mcp-server/tools/record-page.js.map +1 -0
  45. package/dist/mcp-server/tools/render-entity-record.d.ts +3 -1
  46. package/dist/mcp-server/tools/render-entity-record.d.ts.map +1 -1
  47. package/dist/mcp-server/tools/render-entity-record.js +7 -2
  48. package/dist/mcp-server/tools/render-entity-record.js.map +1 -1
  49. package/dist/services/openalex/field-catalog.json +107 -0
  50. package/dist/services/openalex/openalex-service.d.ts +18 -7
  51. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  52. package/dist/services/openalex/openalex-service.js +84 -63
  53. package/dist/services/openalex/openalex-service.js.map +1 -1
  54. package/dist/services/openalex/types.d.ts +13 -2
  55. package/dist/services/openalex/types.d.ts.map +1 -1
  56. package/dist/services/openalex/types.js +28 -1
  57. package/dist/services/openalex/types.js.map +1 -1
  58. package/package.json +7 -6
  59. package/server.json +5 -5
  60. package/skills/openalex-guide/SKILL.md +77 -0
  61. package/dist/mcp-server/tools/response-budget.d.ts +0 -159
  62. package/dist/mcp-server/tools/response-budget.d.ts.map +0 -1
  63. package/dist/mcp-server/tools/response-budget.js +0 -509
  64. package/dist/mcp-server/tools/response-budget.js.map +0 -1
@@ -1,509 +0,0 @@
1
- /**
2
- * @fileoverview Response-size budget for the tools that return OpenAlex entity records
3
- * (`openalex_search_entities`, `openalex_get_citation_graph`). Holds each surface — serialized
4
- * `structuredContent` and the summed `content[]` text, enrichment trailer included — to
5
- * 64,000 bytes: a list page loses whole records from its end, a record too large on its own has
6
- * its biggest arrays windowed, and every cut is disclosed with the call that continues it. The
7
- * same pass discloses OpenAlex's 100-author list cap and 5,000-author singleton storage cap.
8
- * @module mcp-server/tools/response-budget
9
- */
10
- import { z } from '@cyanheads/mcp-ts-core';
11
- import { renderEntityRecord, } from './render-entity-record.js';
12
- /** Per-surface ceiling: serialized `structuredContent`, and summed `content[]` text. */
13
- export const RESPONSE_BUDGET_BYTES = 64_000;
14
- /**
15
- * The most authorships OpenAlex returns on a list record. An `id` lookup can return more,
16
- * up to the separate storage ceiling.
17
- */
18
- const LIST_AUTHORSHIPS_CAP = 100;
19
- const STORED_AUTHORSHIPS_CAP = 5000;
20
- const STORAGE_CAP_NOTICE = 'OpenAlex stores at most 5,000 authorships per work in singleton records and snapshots; this author array may omit part of the byline. `total` counts stored entries, not the complete byline. Further OpenAlex fetches or snapshots cannot recover authors beyond this storage ceiling.';
21
- /** Record arrays the cap applies to: `authorships`, and the `author_list` derived from it. */
22
- const CAPPED_AUTHOR_FIELDS = ['authorships', 'author_list'];
23
- /**
24
- * Bytes reserved on each surface for the `budget` enrichment field. The service writes it from
25
- * OpenAlex's rate-limit headers through `ctx.enrich`, so its value is not in the handler's hands
26
- * when the page is measured. The allowance covers its widest realistic form — every number at
27
- * full double precision, with a prepaid balance — measured at 176 bytes as a JSON member and 108
28
- * as a trailer line with its separator.
29
- */
30
- export const BUDGET_FIELD_ALLOWANCE_BYTES = 256;
31
- const BUDGET_LABEL = `${RESPONSE_BUDGET_BYTES.toLocaleString('en-US')}-byte`;
32
- const CONTINUATION_TOOL = 'openalex_search_entities';
33
- const OPENALEX_ID_PREFIX = 'https://openalex.org/';
34
- const NATIVE_OPENALEX_ID = /^[A-Z]\d+$/;
35
- /**
36
- * The call that continues a cut, shared by `omitted.next` and every `windows[].next`. Its
37
- * arguments are data to pass back unchanged, so the schema leaves them loosely typed rather than
38
- * spelling out the search tool's input a second time.
39
- */
40
- const continuationCallSchema = z.object({
41
- tool: z.literal(CONTINUATION_TOOL).describe('Tool to call.'),
42
- arguments: z.object({}).loose().describe('Arguments to pass as-is.'),
43
- });
44
- const arrayWindowSchema = z
45
- .object({
46
- id: z.string().describe('Bare ID of the record.'),
47
- field: z.string().describe('Array field.'),
48
- offset: z.number().describe('Index of the first element shown.'),
49
- shown: z.number().describe('Elements shown.'),
50
- total: z
51
- .number()
52
- .describe('Stored array length returned to this call, not a complete byline total.'),
53
- possibly_capped: z
54
- .boolean()
55
- .describe('True for exactly 100 authorships or author_list entries on a list record, or 5,000 on a singleton lookup: the byline may be longer than the returned array.'),
56
- next: continuationCallSchema
57
- .nullable()
58
- .describe('`id` + `slice` call for the next elements; null at the array end.'),
59
- })
60
- .describe('An array returned in part.');
61
- /** Output field: whole records the budget cut from a list page, and the call returning them. */
62
- export const omittedOutputSchema = z
63
- .object({
64
- ids: z
65
- .array(z.string())
66
- .describe('Bare IDs of the records left out, in page order (a keyword keeps its URL).'),
67
- next: continuationCallSchema.describe("One call returning those records as a set, in OpenAlex's order, not page order. Budgeted too, so it may carry its own `omitted`."),
68
- })
69
- .optional()
70
- .describe('Present when the response budget cut whole records from the page end; pagination continues after the full upstream page.');
71
- /** Output field: arrays returned in part, or possibly in part, each with its continuation. */
72
- export const windowsOutputSchema = z
73
- .array(arrayWindowSchema)
74
- .optional()
75
- .describe('Arrays windowed to fit the budget, paged by `slice`, or possibly capped at 100 list authors or 5,000 stored singleton authors. A `slice` call always carries its window, even for a whole array. `next` is null at the stored-array end, including a possibly capped singleton.');
76
- /** Output field: the least this call can return does not fit the budget on its own. */
77
- export const overBudgetOutputSchema = z
78
- .boolean()
79
- .optional()
80
- .describe("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.");
81
- const utf8Bytes = (text) => Buffer.byteLength(text, 'utf8');
82
- /** `https://openalex.org/W123` → `W123`. Any other form (a keyword URL) passes through whole. */
83
- export function bareId(id) {
84
- const tail = id.startsWith(OPENALEX_ID_PREFIX) ? id.slice(OPENALEX_ID_PREFIX.length) : id;
85
- return NATIVE_OPENALEX_ID.test(tail) ? tail : id;
86
- }
87
- /** Join notice sentences, dropping empty ones; undefined when none remain. */
88
- export function joinNotices(parts) {
89
- return parts.filter(Boolean).join(' ') || undefined;
90
- }
91
- // ---------------------------------------------------------------------------
92
- // Rendering — shared by both tools' format() and by the budget's own measurement
93
- // ---------------------------------------------------------------------------
94
- const renderCall = (call) => `\`${call.tool}\` \`${JSON.stringify(call.arguments)}\``;
95
- function renderWindow(window) {
96
- const capped = window.possibly_capped
97
- ? window.total >= STORED_AUTHORSHIPS_CAP
98
- ? ' — possibly capped: OpenAlex stores at most 5,000 authorships per work; total counts stored entries, not the complete byline'
99
- : ` — possibly capped: OpenAlex returns at most ${LIST_AUTHORSHIPS_CAP} authorships on a list record`
100
- : '';
101
- const next = window.next ? `next: ${renderCall(window.next)}` : 'end of array';
102
- return `**Window:** ${window.id} \`${window.field}\` — offset ${window.offset}, ${window.shown} shown of ${window.total}${capped} — ${next}`;
103
- }
104
- /** Markdown lines disclosing what the budget cut; empty when the page carries no disclosure. */
105
- function renderBudgetDisclosure(disclosure) {
106
- const lines = [];
107
- if (disclosure.over_budget) {
108
- lines.push('', `**Over budget:** the least this call can return — the first record's non-array fields, or one \`slice\` element — exceeds the ${BUDGET_LABEL} response budget on its own.`);
109
- }
110
- if (disclosure.windows?.length)
111
- lines.push('', ...disclosure.windows.map(renderWindow));
112
- if (disclosure.omitted) {
113
- const { ids, next } = disclosure.omitted;
114
- lines.push('', `**Omitted by the ${BUDGET_LABEL} response budget (${ids.length}):** ${ids.join(', ')}`, `**Omitted records call:** ${renderCall(next)}`);
115
- }
116
- return lines;
117
- }
118
- /**
119
- * Each windowed array's place in its full array, per record ID, so a window numbers its items
120
- * at their real index and its line says how much of the array it shows.
121
- */
122
- function windowViewsByRecord(windows) {
123
- const views = new Map();
124
- for (const window of windows ?? []) {
125
- const fields = views.get(window.id) ?? new Map();
126
- fields.set(window.field, { offset: window.offset, total: window.total });
127
- views.set(window.id, fields);
128
- }
129
- return views;
130
- }
131
- /**
132
- * `format()` for a record page: a count header, each record, then the budget disclosure.
133
- * `noun` names what `meta.count` counts ("result(s)", "edge(s)").
134
- */
135
- export function formatRecordPage(page, noun) {
136
- const countLabel = `${page.meta.count} ${noun} — ${page.meta.per_page} per page`;
137
- const lines = [
138
- page.meta.next_cursor
139
- ? `**${countLabel}** — next cursor: \`${page.meta.next_cursor}\``
140
- : `**${countLabel}**`,
141
- ];
142
- const views = windowViewsByRecord(page.windows);
143
- for (const record of page.results) {
144
- lines.push(...renderEntityRecord(record, views.get(bareId(record.id))));
145
- }
146
- lines.push(...renderBudgetDisclosure(page));
147
- return [{ type: 'text', text: lines.join('\n') }];
148
- }
149
- // ---------------------------------------------------------------------------
150
- // Measurement
151
- // ---------------------------------------------------------------------------
152
- /**
153
- * Byte-exact copy of the framework's trailer join (`joinTrailerFields` in mcp-ts-core's tool
154
- * handler factory, which the package does not export — cyanheads/mcp-ts-core#538). A line opening
155
- * a block quote or list item is followed by a blank line instead of a single newline. The
156
- * response-budget test compares the modelled trailer with the one `runToolContract` renders.
157
- */
158
- const OPENS_LAZY_CONTAINER = /^ {0,3}(?:>|(?:[-+*]|\d{1,9}[.)])(?: |$))/;
159
- function joinTrailerFields(fields) {
160
- let text = '';
161
- for (const field of fields) {
162
- if (text.length > 0) {
163
- text += OPENS_LAZY_CONTAINER.test(text.slice(text.lastIndexOf('\n') + 1)) ? '\n\n' : '\n';
164
- }
165
- text += field;
166
- }
167
- return text;
168
- }
169
- /**
170
- * The enrichment trailer's bytes, minus the service-written `budget` line. Fields render as the
171
- * framework renders them for these tools: `echo` under its `Query` label, `totalCount` under
172
- * `totalLabel`, and `notice` as a block quote, joined after a leading blank line.
173
- */
174
- export function trailerTextBytes(enrichment) {
175
- const fields = [
176
- `**Query:** ${enrichment.echo}`,
177
- `**${enrichment.totalLabel}:** ${enrichment.totalCount}`,
178
- ...(enrichment.notice === undefined ? [] : [`> ${enrichment.notice}`]),
179
- ];
180
- return utf8Bytes(`\n\n${joinTrailerFields(fields)}`);
181
- }
182
- /**
183
- * Both surfaces' bytes for a page frame — the page with no records — plus the enrichment the
184
- * handler writes and the allowance for the service's `budget` field.
185
- */
186
- export function measurePageFrame(frame, noun, enrichment) {
187
- const { echo, notice, totalCount } = enrichment;
188
- const structured = utf8Bytes(JSON.stringify({ ...frame, echo, totalCount, ...(notice !== undefined && { notice }) }));
189
- const text = formatRecordPage(frame, noun).reduce((sum, block) => sum + utf8Bytes(block.text), 0);
190
- return {
191
- structured: structured + BUDGET_FIELD_ALLOWANCE_BYTES,
192
- text: text + trailerTextBytes(enrichment) + BUDGET_FIELD_ALLOWANCE_BYTES,
193
- };
194
- }
195
- /**
196
- * What one record adds to the busier surface: its JSON array member or its rendered lines,
197
- * each plus the one separator byte (comma, newline) joining it to its neighbour. Rendered with
198
- * the renderer `format()` uses, with the window views `format()` will pass.
199
- */
200
- function recordCharge(record, views) {
201
- const json = utf8Bytes(JSON.stringify(record));
202
- const text = utf8Bytes(renderEntityRecord(record, views).join('\n'));
203
- return Math.max(json, text) + 1;
204
- }
205
- const frameBytes = (bytes) => Math.max(bytes.structured, bytes.text);
206
- /**
207
- * Largest n in [0, limit] with `fits(n)`, given `fits(0)` holds and `fits` stays false once
208
- * it turns false. Gallops up from 0 before bisecting, so each probe renders about as many
209
- * elements as the answer holds rather than half the array.
210
- */
211
- function largestFitting(limit, fits) {
212
- let low = 0;
213
- let high = 1;
214
- while (high <= limit && fits(high)) {
215
- low = high;
216
- high *= 2;
217
- }
218
- high = Math.min(high, limit + 1);
219
- while (high - low > 1) {
220
- const mid = Math.floor((low + high) / 2);
221
- if (fits(mid))
222
- low = mid;
223
- else
224
- high = mid;
225
- }
226
- return low;
227
- }
228
- // ---------------------------------------------------------------------------
229
- // Disclosure construction
230
- // ---------------------------------------------------------------------------
231
- function arrayWindow(entityType, record, field, view) {
232
- const id = bareId(record.id);
233
- const end = Math.min(view.offset, view.total) + view.shown;
234
- return {
235
- id,
236
- field,
237
- offset: view.offset,
238
- shown: view.shown,
239
- total: view.total,
240
- possibly_capped: view.possiblyCapped,
241
- next: end < view.total || view.recoverable
242
- ? {
243
- tool: CONTINUATION_TOOL,
244
- arguments: { entity_type: entityType, id, slice: { field, offset: end } },
245
- }
246
- : null,
247
- };
248
- }
249
- /** Author arrays holding exactly the cap for this request path. */
250
- function cappedAuthorFields(record, cap) {
251
- if (cap === undefined)
252
- return [];
253
- return CAPPED_AUTHOR_FIELDS.filter((field) => {
254
- const items = record[field];
255
- return Array.isArray(items) && items.length === cap;
256
- });
257
- }
258
- function capWindow(entityType, record, field) {
259
- const total = record[field].length;
260
- return arrayWindow(entityType, record, field, {
261
- offset: 0,
262
- shown: total,
263
- total,
264
- possiblyCapped: true,
265
- recoverable: total === LIST_AUTHORSHIPS_CAP,
266
- });
267
- }
268
- function budgetNotice(parts) {
269
- const { cappedCount, kept, omitted, overBudget, windowedCount } = parts;
270
- return joinNotices([
271
- omitted.length > 0
272
- ? `The ${BUDGET_LABEL} response budget held ${kept.length} of ${kept.length + omitted.length} records; \`omitted\` names the other ${omitted.length} and the openalex_search_entities call that returns them.`
273
- : undefined,
274
- windowedCount > 0
275
- ? `${windowedCount} array field(s) were windowed to fit the budget; each \`windows\` entry gives the \`id\` + \`slice\` call that continues it.`
276
- : undefined,
277
- overBudget
278
- ? "The first record's non-array fields alone exceed the budget, so this response runs over it."
279
- : undefined,
280
- cappedCount > 0
281
- ? `${cappedCount} record(s) carry exactly ${LIST_AUTHORSHIPS_CAP} authorships or author_list entries, the most OpenAlex returns on a list record, so the author list may be longer; each such array's \`windows\` entry gives the \`id\` + \`slice\` call for more stored authors, up to the singleton storage ceiling of 5,000.`
282
- : undefined,
283
- parts.windows.some((window) => window.possibly_capped && window.total >= STORED_AUTHORSHIPS_CAP)
284
- ? STORAGE_CAP_NOTICE
285
- : undefined,
286
- ]);
287
- }
288
- function assemblePage(parts, entityType, select) {
289
- const disclosure = {};
290
- if (parts.omitted.length > 0) {
291
- const ids = parts.omitted.map((record) => bareId(record.id));
292
- // Keywords have no `openalex` filter upstream (400); their `id` filter takes the keyword URLs.
293
- const idFilter = entityType === 'keywords' ? 'id' : 'openalex';
294
- disclosure.omitted = {
295
- ids,
296
- next: {
297
- tool: CONTINUATION_TOOL,
298
- arguments: {
299
- entity_type: entityType,
300
- filters: { [idFilter]: ids.join('|') },
301
- per_page: ids.length,
302
- ...(select !== undefined && { select: [...select] }),
303
- },
304
- },
305
- };
306
- }
307
- if (parts.windows.length > 0)
308
- disclosure.windows = [...parts.windows];
309
- if (parts.overBudget)
310
- disclosure.over_budget = true;
311
- return { results: [...parts.kept], disclosure, notice: budgetNotice(parts) };
312
- }
313
- /**
314
- * Fit a page of records to the budget. Keeps the longest prefix whose records, charged
315
- * `max(JSON bytes, rendered bytes)` each, fit beside the page frame; the rest become `omitted`.
316
- * When even the first record does not fit alone, its largest arrays are windowed instead.
317
- * Returns new arrays and, for a windowed record, a new record — never the caller's objects
318
- * mutated.
319
- */
320
- export function fitRecordsToBudget(request) {
321
- const { entityType, measureFrame, path, records, select } = request;
322
- const cap = entityType === 'works'
323
- ? path === 'list'
324
- ? LIST_AUTHORSHIPS_CAP
325
- : STORED_AUTHORSHIPS_CAP
326
- : undefined;
327
- const charges = records.map((record) => recordCharge(record));
328
- let recordBytes = charges.reduce((sum, charge) => sum + charge, 0);
329
- for (let kept = records.length; kept >= 1; kept--) {
330
- const keptRecords = records.slice(0, kept);
331
- const capped = keptRecords
332
- .map((record) => ({ record, fields: cappedAuthorFields(record, cap) }))
333
- .filter(({ fields }) => fields.length > 0);
334
- const page = assemblePage({
335
- kept: keptRecords,
336
- omitted: records.slice(kept),
337
- windows: capped.flatMap(({ record, fields }) => fields.map((field) => capWindow(entityType, record, field))),
338
- windowedCount: 0,
339
- cappedCount: path === 'list' ? capped.length : 0,
340
- overBudget: false,
341
- }, entityType, select);
342
- if (frameBytes(measureFrame(page.disclosure, page.notice)) + recordBytes <=
343
- RESPONSE_BUDGET_BYTES) {
344
- return page;
345
- }
346
- recordBytes -= charges[kept - 1] ?? 0;
347
- }
348
- const [first, ...rest] = records;
349
- if (!first)
350
- return { results: [], disclosure: {}, notice: undefined };
351
- return windowRecord(first, rest, cappedAuthorFields(first, cap), request);
352
- }
353
- /**
354
- * Fill windowed arrays round-robin: each array in turn takes its next leading element while it
355
- * fits, so every array shows elements for as long as any of its elements would fit. A record's
356
- * charge only grows as elements are added, so an array whose next element does not fit never
357
- * fits again and drops out. Whole rounds are found by bisection and the round that ends a run
358
- * is played one array at a time, so the result is exactly the one-element-at-a-time fill at a
359
- * cost of a few renders per array. Returns the count shown per field.
360
- */
361
- function fillRoundRobin(base, arrays, fits) {
362
- const counts = new Map(arrays.map((array) => [array.field, 0]));
363
- const shownOf = (array) => counts.get(array.field) ?? 0;
364
- const build = (extra) => {
365
- const record = { ...base };
366
- for (const array of arrays) {
367
- record[array.field] = array.items.slice(0, shownOf(array) + extra(array));
368
- }
369
- return record;
370
- };
371
- let active = [...arrays];
372
- while (active.length > 0) {
373
- const inPlay = new Set(active);
374
- const raise = (rounds) => (array) => inPlay.has(array) ? Math.min(rounds, array.items.length - shownOf(array)) : 0;
375
- const headroom = Math.max(...active.map((array) => array.items.length - shownOf(array)));
376
- const rounds = largestFitting(headroom, (n) => fits(build(raise(n))));
377
- for (const array of active)
378
- counts.set(array.field, shownOf(array) + raise(rounds)(array));
379
- active = active.filter((array) => {
380
- if (shownOf(array) >= array.items.length)
381
- return false;
382
- const grown = build((other) => (other === array ? 1 : 0));
383
- if (!fits(grown))
384
- return false;
385
- counts.set(array.field, shownOf(array) + 1);
386
- return true;
387
- });
388
- }
389
- return counts;
390
- }
391
- /**
392
- * Window the arrays of a record too large to fit whole. Tries windowing the largest array
393
- * alone, then the two largest, and so on, until the record with those arrays emptied fits;
394
- * then fills the windowed arrays round-robin. The disclosure is sized at its upper bound while
395
- * fitting — every count at its array length — so the final, smaller disclosure can only fit too.
396
- */
397
- function windowRecord(record, rest, capped, request) {
398
- const { entityType, measureFrame, select } = request;
399
- const arrays = Object.entries(record)
400
- .filter((entry) => Array.isArray(entry[1]) && entry[1].length > 0)
401
- .map(([field, items]) => ({ field, items, bytes: utf8Bytes(JSON.stringify(items)) }))
402
- .sort((a, b) => b.bytes - a.bytes);
403
- /** Window entries for `shown` counts per windowed field, plus the cap entries that apply. */
404
- const windowsFor = (shown) => {
405
- const entries = [];
406
- for (const [field, items] of Object.entries(record)) {
407
- if (!Array.isArray(items))
408
- continue;
409
- const count = shown.get(field);
410
- const cappedField = capped.includes(field);
411
- if (count !== undefined && count < items.length) {
412
- entries.push(arrayWindow(entityType, record, field, {
413
- offset: 0,
414
- shown: count,
415
- total: items.length,
416
- possiblyCapped: cappedField,
417
- recoverable: cappedField && request.path === 'list',
418
- }));
419
- }
420
- else if (cappedField) {
421
- entries.push(capWindow(entityType, record, field));
422
- }
423
- }
424
- return entries;
425
- };
426
- const partsFor = (kept, windows, overBudget) => ({
427
- kept: [kept],
428
- omitted: rest,
429
- windows,
430
- windowedCount: windows.filter((w) => w.shown < w.total).length,
431
- cappedCount: capped.length > 0 && request.path === 'list' ? 1 : 0,
432
- overBudget,
433
- });
434
- for (let count = 1; count <= arrays.length; count++) {
435
- const windowed = arrays.slice(0, count);
436
- // Upper bound: every windowed count at its full length, each still continuing.
437
- const bound = windowed.map((array) => arrayWindow(entityType, record, array.field, {
438
- offset: 0,
439
- shown: array.items.length,
440
- total: array.items.length + 1,
441
- possiblyCapped: capped.includes(array.field),
442
- }));
443
- const boundWindows = [
444
- ...bound,
445
- ...capped
446
- .filter((field) => !windowed.some((array) => array.field === field))
447
- .map((field) => capWindow(entityType, record, field)),
448
- ];
449
- const boundPage = assemblePage(partsFor(record, boundWindows, false), entityType, select);
450
- const available = RESPONSE_BUDGET_BYTES - frameBytes(measureFrame(boundPage.disclosure, boundPage.notice));
451
- // Charged with the views `format()` passes, so each window's note is paid for.
452
- const views = new Map(windowed.map((array) => [array.field, { offset: 0, total: array.items.length }]));
453
- const fits = (candidate) => recordCharge(candidate, views) <= available;
454
- const emptied = { ...record };
455
- for (const array of windowed)
456
- emptied[array.field] = [];
457
- if (!fits(emptied))
458
- continue;
459
- const shown = fillRoundRobin(record, windowed, fits);
460
- const kept = { ...record };
461
- for (const array of windowed) {
462
- kept[array.field] = array.items.slice(0, shown.get(array.field));
463
- }
464
- return assemblePage(partsFor(kept, windowsFor(shown), false), entityType, select);
465
- }
466
- // The record's non-array fields alone exceed the budget: return them whole, arrays empty.
467
- const emptied = { ...record };
468
- for (const array of arrays)
469
- emptied[array.field] = [];
470
- const shown = new Map(arrays.map((array) => [array.field, 0]));
471
- return assemblePage(partsFor(emptied, windowsFor(shown), true), entityType, select);
472
- }
473
- /**
474
- * Fit one array window of an `id` lookup to the budget: the elements of `field` from `offset`,
475
- * as many as fit. A window holds at least one element whenever any remain, so a caller walking
476
- * the array always advances; when that one element alone does not fit, the response runs over
477
- * the budget and is flagged `over_budget`.
478
- */
479
- export function fitSliceToBudget(request) {
480
- const { entityType, field, measureFrame, offset, record } = request;
481
- const items = record[field];
482
- const total = items.length;
483
- const possiblyCapped = cappedAuthorFields(record, entityType === 'works' ? STORED_AUTHORSHIPS_CAP : undefined).includes(field);
484
- const storageNotice = possiblyCapped ? STORAGE_CAP_NOTICE : undefined;
485
- const start = Math.min(offset, total);
486
- const remaining = total - start;
487
- const views = new Map([[field, { offset, total }]]);
488
- const view = (shown) => ({ offset, shown, total, possiblyCapped });
489
- // Upper bound: the whole remainder shown, with a continuation call.
490
- const bound = arrayWindow(entityType, record, field, { ...view(remaining), total: total + 1 });
491
- const available = RESPONSE_BUDGET_BYTES - frameBytes(measureFrame({ windows: [bound] }, storageNotice));
492
- const fitted = largestFitting(remaining, (n) => recordCharge({ ...record, [field]: items.slice(start, start + n) }, views) <= available);
493
- const overBudget = remaining > 0 && fitted === 0;
494
- const shown = overBudget ? 1 : fitted;
495
- return {
496
- results: [{ ...record, [field]: items.slice(start, start + shown) }],
497
- disclosure: {
498
- windows: [arrayWindow(entityType, record, field, view(shown))],
499
- ...(overBudget && { over_budget: true }),
500
- },
501
- notice: joinNotices([
502
- storageNotice,
503
- overBudget
504
- ? `The element at offset ${start} of \`${field}\` alone exceeds the ${BUDGET_LABEL} response budget, so this response runs over it; ${start + 1 < total ? "the `windows` entry's `next` call continues after it" : 'it is the last element'}.`
505
- : undefined,
506
- ]),
507
- };
508
- }
509
- //# sourceMappingURL=response-budget.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"response-budget.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/response-budget.ts"],"names":[],"mappings":"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"}