@cyanheads/openalex-mcp-server 0.6.15 → 0.6.17
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 +355 -0
- package/CLAUDE.md +2 -2
- package/README.md +1 -1
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts +18 -3
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.js +47 -8
- package/dist/mcp-server/tools/definitions/analyze-trends.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts +18 -3
- package/dist/mcp-server/tools/definitions/citation-graph.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/citation-graph.tool.js +42 -9
- package/dist/mcp-server/tools/definitions/citation-graph.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/resolve-name.tool.d.ts +15 -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 +26 -0
- package/dist/mcp-server/tools/definitions/resolve-name.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +18 -3
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-entities.tool.js +44 -8
- package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -1
- package/package.json +5 -5
- package/server.json +3 -3
package/AGENTS.md
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Agent Protocol
|
|
2
|
+
|
|
3
|
+
**Server:** openalex-mcp-server
|
|
4
|
+
**Version:** 0.6.17
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.16`
|
|
6
|
+
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
|
+
|
|
8
|
+
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Domain
|
|
13
|
+
|
|
14
|
+
[OpenAlex](https://openalex.org) is a fully open catalog of the global research system — 270M+ works, 90M+ authors, 100K+ sources. CC0 data, no API key required (email address optional for polite pool access).
|
|
15
|
+
|
|
16
|
+
**Entity types:** works, authors, sources, institutions, topics, keywords, publishers, funders. All share a uniform API (list/filter, search, get-by-ID, group-by, autocomplete).
|
|
17
|
+
|
|
18
|
+
**Critical workflow:** Names are ambiguous, IDs are not. Always resolve names to IDs first via `openalex_resolve_name` before using them in filters.
|
|
19
|
+
|
|
20
|
+
**Reference docs:** `README.md` covers the current tool and prompt surface; `docs/tree.md` shows the current repository layout.
|
|
21
|
+
|
|
22
|
+
### MCP Surface
|
|
23
|
+
|
|
24
|
+
| Type | Name | Purpose |
|
|
25
|
+
|:-----|:-----|:--------|
|
|
26
|
+
| Tool | `openalex_search_entities` | Search, filter, sort, or retrieve by ID |
|
|
27
|
+
| Tool | `openalex_analyze_trends` | Group-by aggregation for trends/distributions |
|
|
28
|
+
| Tool | `openalex_resolve_name` | Name-to-ID resolution via autocomplete |
|
|
29
|
+
| Tool | `openalex_get_citation_graph` | One-hop citation graph traversal (cites/cited_by/related_to) |
|
|
30
|
+
| Prompt | `openalex_literature_review` | Guided systematic literature search workflow |
|
|
31
|
+
| Prompt | `openalex_research_landscape` | Quantitative research landscape analysis |
|
|
32
|
+
|
|
33
|
+
No resources — entity lookups need `select` for payload control, which fits tools better than URI templates.
|
|
34
|
+
|
|
35
|
+
### Config
|
|
36
|
+
|
|
37
|
+
| Env Var | Required | Description |
|
|
38
|
+
|:--------|:---------|:------------|
|
|
39
|
+
| `OPENALEX_API_KEY` | No | Email for the OpenAlex polite pool (10x faster rate limits); omit for anonymous access |
|
|
40
|
+
| `OPENALEX_BASE_URL` | No | Default: `https://api.openalex.org` |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## What's Next?
|
|
45
|
+
|
|
46
|
+
When the user asks what's next or needs direction, suggest options based on the current project state. Common next steps:
|
|
47
|
+
|
|
48
|
+
1. **Re-run the `setup` skill** — ensures CLAUDE.md, skills, structure, and metadata are populated and up to date with the current codebase
|
|
49
|
+
2. **Run the `design-mcp-server` skill** — if the tool/resource surface hasn't been mapped yet, work through domain design
|
|
50
|
+
3. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-app-tool`, `add-resource`, `add-prompt` skills
|
|
51
|
+
4. **Add services** — scaffold domain service integrations using the `add-service` skill
|
|
52
|
+
5. **Add tests** — scaffold tests for existing definitions using the `add-test` skill
|
|
53
|
+
6. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill, get a report of issues and pain points
|
|
54
|
+
7. **Run `devcheck`** — lint, format, typecheck, and security audit
|
|
55
|
+
8. **Run the `security-pass` skill** — audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation
|
|
56
|
+
9. **Run the `polish-docs-meta` skill** — finalize README, CHANGELOG, metadata, and agent protocol for shipping
|
|
57
|
+
10. **Run the `maintenance` skill** — investigate changelogs, adopt upstream changes, and sync skills after `bun update --latest`
|
|
58
|
+
|
|
59
|
+
Tailor suggestions to what's actually missing or stale — don't recite the full list every time.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Core Rules
|
|
64
|
+
|
|
65
|
+
- **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `validationError()`, etc.) when the error code matters.
|
|
66
|
+
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
67
|
+
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
68
|
+
- **Check `ctx.elicit` / `ctx.sample`** for presence before calling.
|
|
69
|
+
- **Secrets in env vars only** — never hardcoded.
|
|
70
|
+
- **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped. The comment is for future readers — state the concrete changes, not the conversation that produced them.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Patterns
|
|
75
|
+
|
|
76
|
+
### Tool
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
80
|
+
import { getOpenAlexService } from '@/services/openalex/openalex-service.js';
|
|
81
|
+
import { ENTITY_TYPES } from '@/services/openalex/types.js';
|
|
82
|
+
|
|
83
|
+
export const resolveNameTool = tool('openalex_resolve_name', {
|
|
84
|
+
description: 'Resolve a name or partial name to an OpenAlex ID. Returns up to 10 matches with disambiguation hints.',
|
|
85
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
86
|
+
input: z.object({
|
|
87
|
+
entity_type: z.enum(ENTITY_TYPES).optional().describe('Entity type to search. Omit for cross-entity search.'),
|
|
88
|
+
query: z.string().describe('Name or partial name to resolve.'),
|
|
89
|
+
}),
|
|
90
|
+
output: z.object({
|
|
91
|
+
results: z.array(z.object({
|
|
92
|
+
id: z.string().describe('OpenAlex ID.'),
|
|
93
|
+
display_name: z.string().describe('Human-readable name.'),
|
|
94
|
+
entity_type: z.string().describe('Entity type.'),
|
|
95
|
+
})).describe('Autocomplete matches, up to 10.'),
|
|
96
|
+
}),
|
|
97
|
+
|
|
98
|
+
async handler(input, ctx) {
|
|
99
|
+
const service = getOpenAlexService();
|
|
100
|
+
const result = await service.autocomplete({ entityType: input.entity_type, query: input.query }, ctx);
|
|
101
|
+
ctx.log.info('Name resolved', { query: input.query, matchCount: result.results.length });
|
|
102
|
+
return result;
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// format() populates content[] — the markdown twin of structuredContent.
|
|
106
|
+
// Different clients forward different surfaces (Claude Code → structuredContent,
|
|
107
|
+
// Claude Desktop → content[]); both must carry the same data.
|
|
108
|
+
// Enforced at lint time: every terminal field in `output` must appear in format()'s
|
|
109
|
+
// rendered text via sentinel injection. The linter is locale-aware — digit-group
|
|
110
|
+
// separators (commas, periods, spaces) are stripped before matching, so
|
|
111
|
+
// `.toLocaleString()` is fine on linted numbers. Compact/scientific forms still fail.
|
|
112
|
+
format: (result) => {
|
|
113
|
+
if (result.results.length === 0) {
|
|
114
|
+
return [{ type: 'text', text: 'No matches found.' }];
|
|
115
|
+
}
|
|
116
|
+
const lines = result.results.map((r) => `**${r.display_name}** (${r.entity_type}) — ${r.id}`);
|
|
117
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Prompt
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { prompt, z } from '@cyanheads/mcp-ts-core';
|
|
126
|
+
|
|
127
|
+
export const researchLandscapePrompt = prompt('openalex_research_landscape', {
|
|
128
|
+
description: 'Analyzes the research landscape for a topic: volume trends, top authors/institutions, open access rates.',
|
|
129
|
+
args: z.object({
|
|
130
|
+
topic: z.string().describe('Research area to analyze.'),
|
|
131
|
+
}),
|
|
132
|
+
generate: (args) => [
|
|
133
|
+
{ role: 'user', content: { type: 'text', text: `Analyze the research landscape for: "${args.topic}"\n\nUse the OpenAlex tools to build a quantitative profile...` } },
|
|
134
|
+
],
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Context
|
|
141
|
+
|
|
142
|
+
Handlers receive a unified `ctx` object. Key properties:
|
|
143
|
+
|
|
144
|
+
| Property | Description |
|
|
145
|
+
|:---------|:------------|
|
|
146
|
+
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
147
|
+
| `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
|
|
148
|
+
| `ctx.elicit` | Ask user for structured input. **Check for presence first:** `if (ctx.elicit) { ... }` |
|
|
149
|
+
| `ctx.sample` | Request LLM completion from the client. **Check for presence first:** `if (ctx.sample) { ... }` |
|
|
150
|
+
| `ctx.signal` | `AbortSignal` for cancellation. Passed to `fetch()` in the OpenAlex service. |
|
|
151
|
+
| `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
|
|
152
|
+
| `ctx.fail` | Typed throw keyed by a declared `errors[]` contract — `ctx.fail(reason, msg?, data?)`. Auto-populates `data.reason` and resolves `code` from the contract. |
|
|
153
|
+
| `ctx.recoveryFor` | Opt-in resolver returning `{ recovery: { hint } }` for a declared reason. Spread into `data` at throw site to surface contract recovery on the wire. |
|
|
154
|
+
| `ctx.requestId` | Unique request ID. |
|
|
155
|
+
| `ctx.tenantId` | `'default'` for stdio and `MCP_AUTH_MODE=none` over HTTP; JWT `tid` claim for `MCP_AUTH_MODE=jwt`/`oauth`. |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Errors
|
|
160
|
+
|
|
161
|
+
Handlers throw — the framework catches, classifies, and formats.
|
|
162
|
+
|
|
163
|
+
**Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union — `ctx.fail('typo')` is a TS error, `data.reason` is auto-populated, and the linter enforces conformance against the handler. The `recovery` field is required (≥5 words). Spread `ctx.recoveryFor('reason')` into `data` to opt the contract recovery onto the wire.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
167
|
+
|
|
168
|
+
errors: [
|
|
169
|
+
{ reason: 'semantic_per_page_cap', code: JsonRpcErrorCode.ValidationError,
|
|
170
|
+
when: 'per_page exceeds the semantic-search cap',
|
|
171
|
+
recovery: 'Reduce per_page to 50 or less, or switch search_mode to keyword.' },
|
|
172
|
+
],
|
|
173
|
+
async handler(input, ctx) {
|
|
174
|
+
if (overCap) throw ctx.fail('semantic_per_page_cap', message, { ...ctx.recoveryFor('semantic_per_page_cap') });
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Declare contracts inline on each tool, even when similar across tools.** The contract is part of the tool's documented public surface — reading one tool definition file should give the full picture. Don't extract a shared `errors[]` constant; per-tool repetition is the intended cost of locality.
|
|
179
|
+
|
|
180
|
+
The OpenAlex service throws factory errors (`notFound`, `rateLimited`, etc.) based on upstream status codes; those bubble through and are auto-classified. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely without needing to be declared on a contract.
|
|
181
|
+
|
|
182
|
+
**Fallback for ad-hoc throws:** error factories or plain `Error`.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { notFound, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
186
|
+
throw notFound('Item not found', { itemId });
|
|
187
|
+
throw serviceUnavailable('API unavailable', { url }, { cause: err });
|
|
188
|
+
throw new Error('Item not found'); // → auto-classified to NotFound
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
See framework CLAUDE.md for the full auto-classification table and all available factories.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Structure
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
src/
|
|
199
|
+
index.ts # createApp() entry point
|
|
200
|
+
config/
|
|
201
|
+
server-config.ts # OPENALEX_API_KEY, OPENALEX_BASE_URL
|
|
202
|
+
services/
|
|
203
|
+
openalex/
|
|
204
|
+
openalex-service.ts # API client (init/accessor pattern)
|
|
205
|
+
types.ts # Domain types
|
|
206
|
+
mcp-server/
|
|
207
|
+
tools/definitions/
|
|
208
|
+
search-entities.tool.ts # openalex_search_entities
|
|
209
|
+
analyze-trends.tool.ts # openalex_analyze_trends
|
|
210
|
+
resolve-name.tool.ts # openalex_resolve_name
|
|
211
|
+
citation-graph.tool.ts # openalex_get_citation_graph
|
|
212
|
+
prompts/definitions/
|
|
213
|
+
literature-review.prompt.ts # openalex_literature_review
|
|
214
|
+
research-landscape.prompt.ts # openalex_research_landscape
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Naming
|
|
220
|
+
|
|
221
|
+
| What | Convention | Example |
|
|
222
|
+
|:-----|:-----------|:--------|
|
|
223
|
+
| Files | kebab-case with suffix | `search-entities.tool.ts` |
|
|
224
|
+
| Tool/prompt names | snake_case with `openalex_` prefix | `openalex_search_entities` |
|
|
225
|
+
| Directories | kebab-case | `src/services/openalex/` |
|
|
226
|
+
| Descriptions | Single string or template literal, no `+` concatenation | `'Search items by query and filter.'` |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Skills
|
|
231
|
+
|
|
232
|
+
Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
|
|
233
|
+
|
|
234
|
+
**Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). This makes skills available as context without needing to reference `skills/` paths manually. After framework updates, run the `maintenance` skill — it re-syncs the agent directory automatically (Phase B).
|
|
235
|
+
|
|
236
|
+
Available skills:
|
|
237
|
+
|
|
238
|
+
| Skill | Purpose |
|
|
239
|
+
|:------|:--------|
|
|
240
|
+
| `setup` | Post-init project orientation |
|
|
241
|
+
| `design-mcp-server` | Design tool surface, resources, and services for a new server |
|
|
242
|
+
| `add-tool` | Scaffold a new tool definition |
|
|
243
|
+
| `add-app-tool` | Scaffold an MCP App tool + paired UI resource |
|
|
244
|
+
| `add-resource` | Scaffold a new resource definition |
|
|
245
|
+
| `add-prompt` | Scaffold a new prompt definition |
|
|
246
|
+
| `add-service` | Scaffold a new service integration |
|
|
247
|
+
| `add-test` | Scaffold test file for a tool, resource, or service |
|
|
248
|
+
| `field-test` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
|
|
249
|
+
| `tool-defs-analysis` | Read-only audit of LLM-facing definition language (voice, leaks, recovery, sparsity, structure) across tools/resources/prompts |
|
|
250
|
+
| `security-pass` | Audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation |
|
|
251
|
+
| `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
|
|
252
|
+
| `devcheck` | Lint, format, typecheck, audit |
|
|
253
|
+
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
254
|
+
| `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
|
|
255
|
+
| `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
|
|
256
|
+
| `maintenance` | Investigate changelogs, adopt upstream changes, sync skills |
|
|
257
|
+
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` |
|
|
258
|
+
| `report-issue-local` | File a bug or feature request against this server's own repo |
|
|
259
|
+
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
260
|
+
| `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper — Tier 3 opt-in |
|
|
261
|
+
| `api-config` | AppConfig, parseConfig, env vars |
|
|
262
|
+
| `api-context` | Context interface, logger, state, progress |
|
|
263
|
+
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
264
|
+
| `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
|
|
265
|
+
| `api-services` | LLM, Speech, Graph services |
|
|
266
|
+
| `api-testing` | createMockContext, test patterns |
|
|
267
|
+
| `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
|
|
268
|
+
| `api-telemetry` | OTel catalog: spans, metrics, completion logs, env config, cardinality rules |
|
|
269
|
+
| `api-workers` | Cloudflare Workers runtime |
|
|
270
|
+
|
|
271
|
+
When you complete a skill's checklist, check the boxes and add a completion timestamp at the end (e.g., `Completed: 2026-03-11`).
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Commands
|
|
276
|
+
|
|
277
|
+
| Command | Purpose |
|
|
278
|
+
|:--------|:--------|
|
|
279
|
+
| `bun run build` | Compile TypeScript |
|
|
280
|
+
| `bun run rebuild` | Clean + build |
|
|
281
|
+
| `bun run clean` | Remove build artifacts |
|
|
282
|
+
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
283
|
+
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory — stale lockfile can mask already-patched deps. If advisory survives, it's real. |
|
|
284
|
+
| `bun run tree` | Generate directory structure doc |
|
|
285
|
+
| `bun run format` | Auto-fix formatting |
|
|
286
|
+
| `bun run lint:mcp` | Validate MCP tool/prompt definitions |
|
|
287
|
+
| `bun run list-skills` | List available skills |
|
|
288
|
+
| `bun run test` | Run tests |
|
|
289
|
+
| `bun run start:stdio` | Production mode (stdio, after `rebuild`) |
|
|
290
|
+
| `bun run start:http` | Production mode (HTTP, after `rebuild`) |
|
|
291
|
+
| `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
|
|
292
|
+
| `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
|
|
293
|
+
| `bun run bundle` | Build and pack as `.mcpb` for one-click Claude Desktop install |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Bundling
|
|
298
|
+
|
|
299
|
+
`bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. MCPB is stdio-only — HTTP deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
300
|
+
|
|
301
|
+
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Changelog
|
|
306
|
+
|
|
307
|
+
Directory-based, grouped by minor series via the `.x` semver-wildcard convention. Source of truth: `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.6.x/0.6.12.md`) — one file per release, shipped in the npm package. At release, author the per-version file with a concrete version and date, then run `bun run changelog:build` to regenerate the rollup. `changelog/template.md` is a **pristine format reference** — never edited or moved. `CHANGELOG.md` is a **navigation index** regenerated by `bun run changelog:build` — devcheck hard-fails on drift; never hand-edit it.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Publishing
|
|
312
|
+
|
|
313
|
+
Run the `release-and-publish` skill — it runs the verification gate (`devcheck`, `rebuild`, `test`), pushes commits and tags, then publishes to every applicable destination. The full reference:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
bun publish --access public
|
|
317
|
+
|
|
318
|
+
docker buildx build --platform linux/amd64,linux/arm64 \
|
|
319
|
+
-t ghcr.io/cyanheads/openalex-mcp-server:<version> \
|
|
320
|
+
-t ghcr.io/cyanheads/openalex-mcp-server:latest \
|
|
321
|
+
--push .
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Imports
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
// Framework — z is re-exported, no separate zod import needed
|
|
330
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
331
|
+
import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
332
|
+
|
|
333
|
+
// Server's own code — via path alias
|
|
334
|
+
import { getOpenAlexService } from '@/services/openalex/openalex-service.js';
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Checklist
|
|
340
|
+
|
|
341
|
+
- [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()`)
|
|
342
|
+
- [ ] Optional nested objects: handler guards for empty inner values from form-based clients (`if (input.obj?.field && ...)`, not just `if (input.obj)`). When regex/length constraints matter, use `z.union([z.literal(''), z.string().regex(...).describe(...)])` — literal variants are exempt from `describe-on-fields`.
|
|
343
|
+
- [ ] `format()` renders every terminal field in `output` — enforced by `format-parity` linter via sentinel injection (locale-aware: digit-group separators stripped before matching)
|
|
344
|
+
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
345
|
+
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
346
|
+
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
347
|
+
- [ ] OpenAlex wrapping: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
|
|
348
|
+
- [ ] OpenAlex wrapping: normalization and `format()` preserve uncertainty — do not fabricate facts from missing upstream data
|
|
349
|
+
- [ ] OpenAlex wrapping: tests include at least one sparse payload case with omitted upstream fields
|
|
350
|
+
- [ ] Registered in `createApp()` arrays (directly or via barrel exports)
|
|
351
|
+
- [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
|
|
352
|
+
- [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = package name; `interface.shortDescription` from `package.json` description
|
|
353
|
+
- [ ] `.codex-plugin/mcp.json` updated — server name key matches `package.json` name; env vars added for any required API keys
|
|
354
|
+
- [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; inline `mcpServers` entry with server name key, env vars for any required API keys
|
|
355
|
+
- [ ] `bun run devcheck` passes
|
package/CLAUDE.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** openalex-mcp-server
|
|
4
|
-
**Version:** 0.6.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.
|
|
4
|
+
**Version:** 0.6.17
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.16`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
|
|
8
8
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/openalex-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/openalex-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -25,7 +25,6 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
25
25
|
count: z.ZodNumber;
|
|
26
26
|
groups_count: z.ZodNullable<z.ZodNumber>;
|
|
27
27
|
next_cursor: z.ZodNullable<z.ZodString>;
|
|
28
|
-
echo: z.ZodString;
|
|
29
28
|
}, z.core.$strip>;
|
|
30
29
|
groups: z.ZodArray<z.ZodObject<{
|
|
31
30
|
key: z.ZodString;
|
|
@@ -38,6 +37,18 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
38
37
|
readonly when: "OpenAlex throttled the request (HTTP 429).";
|
|
39
38
|
readonly retryable: true;
|
|
40
39
|
readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
|
|
40
|
+
}, {
|
|
41
|
+
readonly reason: "upstream_timeout";
|
|
42
|
+
readonly code: JsonRpcErrorCode.Timeout;
|
|
43
|
+
readonly when: "OpenAlex did not respond within the request deadline.";
|
|
44
|
+
readonly retryable: true;
|
|
45
|
+
readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
|
|
46
|
+
}, {
|
|
47
|
+
readonly reason: "upstream_unavailable";
|
|
48
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
49
|
+
readonly when: "OpenAlex returned HTTP 503 (service unavailable).";
|
|
50
|
+
readonly retryable: true;
|
|
51
|
+
readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
|
|
41
52
|
}, {
|
|
42
53
|
readonly reason: "upstream_unauthorized";
|
|
43
54
|
readonly code: JsonRpcErrorCode.Unauthorized;
|
|
@@ -52,11 +63,15 @@ export declare const analyzeTrendsTool: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
52
63
|
readonly reason: "upstream_invalid_params";
|
|
53
64
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
54
65
|
readonly when: "OpenAlex rejected the group_by or filter as malformed (HTTP 400).";
|
|
55
|
-
readonly recovery: "
|
|
66
|
+
readonly recovery: "The upstream message names the rejected key in group_by or filters; the valid-fields list it appends may be truncated. Retry with a valid group_by field for the entity_type, or a valid filter key — for full-text inside filters use abstract.search, title.search, or default.search.";
|
|
56
67
|
}, {
|
|
57
68
|
readonly reason: "upstream_validation_failed";
|
|
58
69
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
59
70
|
readonly when: "OpenAlex rejected the request as semantically invalid (HTTP 422).";
|
|
60
71
|
readonly recovery: "Read the upstream message for the specific field, then adjust the request to satisfy validation.";
|
|
61
|
-
}]
|
|
72
|
+
}], {
|
|
73
|
+
readonly echo: z.ZodString;
|
|
74
|
+
readonly entityTotal: z.ZodNumber;
|
|
75
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
76
|
+
}>;
|
|
62
77
|
//# sourceMappingURL=analyze-trends.tool.d.ts.map
|
|
@@ -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;AAIjE,eAAO,MAAM,iBAAiB
|
|
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;AAIjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyN5B,CAAC"}
|
|
@@ -18,6 +18,20 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
18
18
|
retryable: true,
|
|
19
19
|
recovery: 'Wait several seconds and retry; consider lowering request frequency for this caller.',
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
reason: 'upstream_timeout',
|
|
23
|
+
code: JsonRpcErrorCode.Timeout,
|
|
24
|
+
when: 'OpenAlex did not respond within the request deadline.',
|
|
25
|
+
retryable: true,
|
|
26
|
+
recovery: 'Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
reason: 'upstream_unavailable',
|
|
30
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
31
|
+
when: 'OpenAlex returned HTTP 503 (service unavailable).',
|
|
32
|
+
retryable: true,
|
|
33
|
+
recovery: 'Wait and retry; check https://openalex.org for service status if the outage persists.',
|
|
34
|
+
},
|
|
21
35
|
{
|
|
22
36
|
reason: 'upstream_unauthorized',
|
|
23
37
|
code: JsonRpcErrorCode.Unauthorized,
|
|
@@ -34,7 +48,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
34
48
|
reason: 'upstream_invalid_params',
|
|
35
49
|
code: JsonRpcErrorCode.ValidationError,
|
|
36
50
|
when: 'OpenAlex rejected the group_by or filter as malformed (HTTP 400).',
|
|
37
|
-
recovery: '
|
|
51
|
+
recovery: 'The upstream message names the rejected key in group_by or filters; the valid-fields list it appends may be truncated. Retry with a valid group_by field for the entity_type, or a valid filter key — for full-text inside filters use abstract.search, title.search, or default.search.',
|
|
38
52
|
},
|
|
39
53
|
{
|
|
40
54
|
reason: 'upstream_validation_failed',
|
|
@@ -62,7 +76,7 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
62
76
|
.min(1)
|
|
63
77
|
.max(200)
|
|
64
78
|
.default(200)
|
|
65
|
-
.describe('Maximum groups per page (1-200). Default 200 (the upstream cap).
|
|
79
|
+
.describe('Maximum groups per page (1-200). Default 200 (the upstream cap). Reduce when only the top-N groups matter — same aggregation, smaller payload.'),
|
|
66
80
|
cursor: z
|
|
67
81
|
.string()
|
|
68
82
|
.optional()
|
|
@@ -77,9 +91,6 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
77
91
|
.string()
|
|
78
92
|
.nullable()
|
|
79
93
|
.describe('Cursor for next page of groups. null if no more groups.'),
|
|
80
|
-
echo: z
|
|
81
|
-
.string()
|
|
82
|
-
.describe('Compact echo of the input criteria (entity_type, group_by, filters) — useful when no groups are returned so callers see what was actually requested.'),
|
|
83
94
|
})
|
|
84
95
|
.describe('Aggregation metadata.'),
|
|
85
96
|
groups: z
|
|
@@ -92,6 +103,25 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
92
103
|
.describe('A single aggregation group with its key, display label, and entity count.'))
|
|
93
104
|
.describe('Aggregation groups with counts.'),
|
|
94
105
|
}),
|
|
106
|
+
// Agent-facing context for the success path — the criteria as parsed, the entity
|
|
107
|
+
// total, and recovery guidance for empty group results. Populated via ctx.enrich(...)
|
|
108
|
+
// so it reaches structuredContent and content[] alike.
|
|
109
|
+
enrichment: {
|
|
110
|
+
echo: z
|
|
111
|
+
.string()
|
|
112
|
+
.describe('Compact echo of the input criteria (entity_type, group_by, filters) — surfaces what was actually requested when no groups are returned.'),
|
|
113
|
+
entityTotal: z
|
|
114
|
+
.number()
|
|
115
|
+
.describe('Total entities matching the filters before grouping (across all pages).'),
|
|
116
|
+
notice: z
|
|
117
|
+
.string()
|
|
118
|
+
.optional()
|
|
119
|
+
.describe('Recovery guidance when no groups are returned — echoes the criteria and suggests how to adjust. Absent when groups are present.'),
|
|
120
|
+
},
|
|
121
|
+
enrichmentTrailer: {
|
|
122
|
+
echo: { label: 'Query' },
|
|
123
|
+
entityTotal: { label: 'Entity Total' },
|
|
124
|
+
},
|
|
95
125
|
async handler(input, ctx) {
|
|
96
126
|
const service = getOpenAlexService();
|
|
97
127
|
const result = await service.analyze({
|
|
@@ -108,18 +138,27 @@ export const analyzeTrendsTool = tool('openalex_analyze_trends', {
|
|
|
108
138
|
totalCount: result.meta.count,
|
|
109
139
|
groupCount: result.groups.length,
|
|
110
140
|
});
|
|
141
|
+
const echo = buildAnalyzeEcho(input);
|
|
142
|
+
ctx.enrich({ echo, entityTotal: result.meta.count });
|
|
143
|
+
if (result.groups.length === 0) {
|
|
144
|
+
ctx.enrich.notice(`No groups returned for ${echo}. Try removing filters or grouping by a different field.`);
|
|
145
|
+
}
|
|
111
146
|
return {
|
|
112
|
-
meta: {
|
|
147
|
+
meta: {
|
|
148
|
+
count: result.meta.count,
|
|
149
|
+
groups_count: result.meta.groups_count,
|
|
150
|
+
next_cursor: result.meta.next_cursor,
|
|
151
|
+
},
|
|
113
152
|
groups: result.groups,
|
|
114
153
|
};
|
|
115
154
|
},
|
|
116
155
|
format: (result) => {
|
|
117
|
-
const heading = `${result.meta.count} total entities across ${result.meta.groups_count ?? result.groups.length} groups on this page
|
|
156
|
+
const heading = `${result.meta.count} total entities across ${result.meta.groups_count ?? result.groups.length} groups on this page`;
|
|
118
157
|
if (result.groups.length === 0) {
|
|
119
158
|
return [
|
|
120
159
|
{
|
|
121
160
|
type: 'text',
|
|
122
|
-
text: `No groups found
|
|
161
|
+
text: `No groups found. (count=${result.meta.count}, groups_count=${result.meta.groups_count ?? 0})`,
|
|
123
162
|
},
|
|
124
163
|
];
|
|
125
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-trends.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/analyze-trends.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,yBAAyB,EAAE;IAC/D,WAAW,EACT,oXAAoX;IACtX,SAAS,EACP,oHAAoH;IACtH,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAC9E,MAAM,EAAE;QACN;YACE,MAAM,EAAE,cAAc;YACtB,IAAI,EAAE,gBAAgB,CAAC,WAAW;YAClC,IAAI,EAAE,4CAA4C;YAClD,SAAS,EAAE,IAAI;YACf,QAAQ,EACN,sFAAsF;SACzF;QACD;YACE,MAAM,EAAE,uBAAuB;YAC/B,IAAI,EAAE,gBAAgB,CAAC,YAAY;YACnC,IAAI,EAAE,2CAA2C;YACjD,QAAQ,EACN,0FAA0F;SAC7F;QACD;YACE,MAAM,EAAE,oBAAoB;YAC5B,IAAI,EAAE,gBAAgB,CAAC,SAAS;YAChC,IAAI,EAAE,8DAA8D;YACpE,QAAQ,EACN,yFAAyF;SAC5F;QACD;YACE,MAAM,EAAE,yBAAyB;YACjC,IAAI,EAAE,gBAAgB,CAAC,eAAe;YACtC,IAAI,EAAE,mEAAmE;YACzE,QAAQ,EACN,
|
|
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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"}
|
|
@@ -21,7 +21,6 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
21
21
|
count: z.ZodNumber;
|
|
22
22
|
per_page: z.ZodNumber;
|
|
23
23
|
next_cursor: z.ZodNullable<z.ZodString>;
|
|
24
|
-
echo: z.ZodString;
|
|
25
24
|
}, z.core.$strip>;
|
|
26
25
|
results: z.ZodArray<z.ZodObject<{
|
|
27
26
|
id: z.ZodString;
|
|
@@ -33,6 +32,18 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
33
32
|
readonly when: "OpenAlex throttled the request (HTTP 429).";
|
|
34
33
|
readonly retryable: true;
|
|
35
34
|
readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
|
|
35
|
+
}, {
|
|
36
|
+
readonly reason: "upstream_timeout";
|
|
37
|
+
readonly code: JsonRpcErrorCode.Timeout;
|
|
38
|
+
readonly when: "OpenAlex did not respond within the request deadline.";
|
|
39
|
+
readonly retryable: true;
|
|
40
|
+
readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
|
|
41
|
+
}, {
|
|
42
|
+
readonly reason: "upstream_unavailable";
|
|
43
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
44
|
+
readonly when: "OpenAlex returned HTTP 503 (service unavailable).";
|
|
45
|
+
readonly retryable: true;
|
|
46
|
+
readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
|
|
36
47
|
}, {
|
|
37
48
|
readonly reason: "upstream_unauthorized";
|
|
38
49
|
readonly code: JsonRpcErrorCode.Unauthorized;
|
|
@@ -47,7 +58,7 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
47
58
|
readonly reason: "upstream_invalid_params";
|
|
48
59
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
49
60
|
readonly when: "OpenAlex rejected the seed_id, filter, or sort as malformed (HTTP 400).";
|
|
50
|
-
readonly recovery: "
|
|
61
|
+
readonly recovery: "The upstream message names the rejected token; any valid-fields list it appends may be truncated. Pass a valid OpenAlex work ID (W…), DOI, or PMID for seed_id, or correct the filter or sort field name.";
|
|
51
62
|
}, {
|
|
52
63
|
readonly reason: "reserved_filter_key";
|
|
53
64
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
@@ -58,5 +69,9 @@ export declare const getCitationGraphTool: import("@cyanheads/mcp-ts-core").Tool
|
|
|
58
69
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
59
70
|
readonly when: "OpenAlex has no work matching the seed_id.";
|
|
60
71
|
readonly recovery: "Verify seed_id with openalex_resolve_name, or pass a known OpenAlex work ID (W…), DOI, PMID, or PMCID.";
|
|
61
|
-
}]
|
|
72
|
+
}], {
|
|
73
|
+
readonly echo: z.ZodString;
|
|
74
|
+
readonly totalEdges: z.ZodNumber;
|
|
75
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
76
|
+
}>;
|
|
62
77
|
//# sourceMappingURL=citation-graph.tool.d.ts.map
|
|
@@ -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;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA+CjE,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"citation-graph.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA+CjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+O/B,CAAC"}
|
|
@@ -35,7 +35,7 @@ function buildCitationEcho(input) {
|
|
|
35
35
|
return parts.join(' | ');
|
|
36
36
|
}
|
|
37
37
|
export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
38
|
-
description: "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`). Results use the works schema; combine with filters/sort to narrow further.",
|
|
38
|
+
description: "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.",
|
|
39
39
|
sourceUrl: 'https://github.com/cyanheads/openalex-mcp-server/blob/main/src/mcp-server/tools/definitions/citation-graph.tool.ts',
|
|
40
40
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
41
41
|
errors: [
|
|
@@ -46,6 +46,20 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
46
46
|
retryable: true,
|
|
47
47
|
recovery: 'Wait several seconds and retry; consider lowering request frequency for this caller.',
|
|
48
48
|
},
|
|
49
|
+
{
|
|
50
|
+
reason: 'upstream_timeout',
|
|
51
|
+
code: JsonRpcErrorCode.Timeout,
|
|
52
|
+
when: 'OpenAlex did not respond within the request deadline.',
|
|
53
|
+
retryable: true,
|
|
54
|
+
recovery: 'Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
reason: 'upstream_unavailable',
|
|
58
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
59
|
+
when: 'OpenAlex returned HTTP 503 (service unavailable).',
|
|
60
|
+
retryable: true,
|
|
61
|
+
recovery: 'Wait and retry; check https://openalex.org for service status if the outage persists.',
|
|
62
|
+
},
|
|
49
63
|
{
|
|
50
64
|
reason: 'upstream_unauthorized',
|
|
51
65
|
code: JsonRpcErrorCode.Unauthorized,
|
|
@@ -62,7 +76,7 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
62
76
|
reason: 'upstream_invalid_params',
|
|
63
77
|
code: JsonRpcErrorCode.ValidationError,
|
|
64
78
|
when: 'OpenAlex rejected the seed_id, filter, or sort as malformed (HTTP 400).',
|
|
65
|
-
recovery: '
|
|
79
|
+
recovery: 'The upstream message names the rejected token; any valid-fields list it appends may be truncated. Pass a valid OpenAlex work ID (W…), DOI, or PMID for seed_id, or correct the filter or sort field name.',
|
|
66
80
|
},
|
|
67
81
|
{
|
|
68
82
|
reason: 'reserved_filter_key',
|
|
@@ -120,9 +134,6 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
120
134
|
.string()
|
|
121
135
|
.nullable()
|
|
122
136
|
.describe('Cursor for next page. null if no more results.'),
|
|
123
|
-
echo: z
|
|
124
|
-
.string()
|
|
125
|
-
.describe('Compact echo of seed_id, direction, filters, sort — useful when empty.'),
|
|
126
137
|
})
|
|
127
138
|
.describe('Result metadata including pagination.'),
|
|
128
139
|
results: z
|
|
@@ -135,6 +146,23 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
135
146
|
.describe('A single OpenAlex work record on the citation graph. Additional fields vary by `select`.'))
|
|
136
147
|
.describe('Works on the citation graph in this direction.'),
|
|
137
148
|
}),
|
|
149
|
+
// Agent-facing context for the success path — the query as parsed (seed + direction),
|
|
150
|
+
// the total edge count, and recovery guidance for empty traversals. Populated via
|
|
151
|
+
// ctx.enrich(...) so it reaches structuredContent and content[] alike.
|
|
152
|
+
enrichment: {
|
|
153
|
+
echo: z
|
|
154
|
+
.string()
|
|
155
|
+
.describe('Compact echo of seed_id, direction, filters, sort — surfaces what was actually queried when no edges are returned.'),
|
|
156
|
+
totalEdges: z.number().describe('Total edges from seed_id in this direction across all pages.'),
|
|
157
|
+
notice: z
|
|
158
|
+
.string()
|
|
159
|
+
.optional()
|
|
160
|
+
.describe('Recovery guidance when no edges are returned — suggests verifying the seed_id, broadening filters, or trying a different direction. Absent when results are present.'),
|
|
161
|
+
},
|
|
162
|
+
enrichmentTrailer: {
|
|
163
|
+
echo: { label: 'Query' },
|
|
164
|
+
totalEdges: { label: 'Total Edges' },
|
|
165
|
+
},
|
|
138
166
|
async handler(input, ctx) {
|
|
139
167
|
if (input.filters) {
|
|
140
168
|
const reserved = Object.keys(input.filters).find((key) => RESERVED_FILTER_KEYS.has(key));
|
|
@@ -166,10 +194,16 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
166
194
|
resultCount: result.results.length,
|
|
167
195
|
totalCount: result.meta.count,
|
|
168
196
|
});
|
|
197
|
+
const echo = buildCitationEcho(input);
|
|
198
|
+
ctx.enrich({ echo, totalEdges: result.meta.count });
|
|
199
|
+
if (result.results.length === 0) {
|
|
200
|
+
ctx.enrich.notice(`No edges for ${echo}. Verify the seed_id with openalex_resolve_name, broaden filters, or try a different direction.`);
|
|
201
|
+
}
|
|
169
202
|
return {
|
|
170
203
|
meta: {
|
|
171
|
-
|
|
172
|
-
|
|
204
|
+
count: result.meta.count,
|
|
205
|
+
per_page: result.meta.per_page,
|
|
206
|
+
next_cursor: result.meta.next_cursor,
|
|
173
207
|
},
|
|
174
208
|
results: result.results,
|
|
175
209
|
};
|
|
@@ -180,9 +214,8 @@ export const getCitationGraphTool = tool('openalex_get_citation_graph', {
|
|
|
180
214
|
const header = result.meta.next_cursor
|
|
181
215
|
? `**${countLabel}** — next cursor: \`${result.meta.next_cursor}\``
|
|
182
216
|
: `**${countLabel}**`;
|
|
183
|
-
lines.push(
|
|
217
|
+
lines.push(header);
|
|
184
218
|
if (result.results.length === 0) {
|
|
185
|
-
lines.push('', `No edges for ${result.meta.echo}.`, 'Verify the seed_id (use openalex_resolve_name), broaden filters, or try a different direction.');
|
|
186
219
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
187
220
|
}
|
|
188
221
|
for (const record of result.results) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citation-graph.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAG7E,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AAEpD;;;;;;;GAOG;AACH,KAAK,UAAU,mBAAmB,CAChC,OAA8C,EAC9C,MAAc,EACd,GAAY;IAEZ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC9F,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,2BAA2B,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAU,CAAC;AAGhE,MAAM,oBAAoB,GAAwB,IAAI,GAAG,CAAS,UAAU,CAAC,CAAC;AAE9E,SAAS,iBAAiB,CAAC,KAK1B;IACC,MAAM,KAAK,GAAG,CAAC,WAAW,KAAK,CAAC,OAAO,EAAE,EAAE,aAAa,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC3E,IAAI,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,6BAA6B,EAAE;IACtE,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"citation-graph.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/citation-graph.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,18 @@ export declare const resolveNameTool: import("@cyanheads/mcp-ts-core").ToolDefin
|
|
|
33
33
|
readonly when: "OpenAlex throttled the autocomplete request (HTTP 429).";
|
|
34
34
|
readonly retryable: true;
|
|
35
35
|
readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
|
|
36
|
+
}, {
|
|
37
|
+
readonly reason: "upstream_timeout";
|
|
38
|
+
readonly code: JsonRpcErrorCode.Timeout;
|
|
39
|
+
readonly when: "OpenAlex did not respond within the request deadline.";
|
|
40
|
+
readonly retryable: true;
|
|
41
|
+
readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
|
|
42
|
+
}, {
|
|
43
|
+
readonly reason: "upstream_unavailable";
|
|
44
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
45
|
+
readonly when: "OpenAlex returned HTTP 503 (service unavailable).";
|
|
46
|
+
readonly retryable: true;
|
|
47
|
+
readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
|
|
36
48
|
}, {
|
|
37
49
|
readonly reason: "upstream_unauthorized";
|
|
38
50
|
readonly code: JsonRpcErrorCode.Unauthorized;
|
|
@@ -53,5 +65,7 @@ export declare const resolveNameTool: import("@cyanheads/mcp-ts-core").ToolDefin
|
|
|
53
65
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
54
66
|
readonly when: "OpenAlex rejected the autocomplete request as semantically invalid (HTTP 422).";
|
|
55
67
|
readonly recovery: "Read the upstream message for the specific field, then adjust the request to satisfy validation.";
|
|
56
|
-
}]
|
|
68
|
+
}], {
|
|
69
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}>;
|
|
57
71
|
//# sourceMappingURL=resolve-name.tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-name.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/resolve-name.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"resolve-name.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/resolve-name.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyK1B,CAAC"}
|
|
@@ -18,6 +18,20 @@ export const resolveNameTool = tool('openalex_resolve_name', {
|
|
|
18
18
|
retryable: true,
|
|
19
19
|
recovery: 'Wait several seconds and retry; consider lowering request frequency for this caller.',
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
reason: 'upstream_timeout',
|
|
23
|
+
code: JsonRpcErrorCode.Timeout,
|
|
24
|
+
when: 'OpenAlex did not respond within the request deadline.',
|
|
25
|
+
retryable: true,
|
|
26
|
+
recovery: 'Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
reason: 'upstream_unavailable',
|
|
30
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
31
|
+
when: 'OpenAlex returned HTTP 503 (service unavailable).',
|
|
32
|
+
retryable: true,
|
|
33
|
+
recovery: 'Wait and retry; check https://openalex.org for service status if the outage persists.',
|
|
34
|
+
},
|
|
21
35
|
{
|
|
22
36
|
reason: 'upstream_unauthorized',
|
|
23
37
|
code: JsonRpcErrorCode.Unauthorized,
|
|
@@ -85,6 +99,14 @@ export const resolveNameTool = tool('openalex_resolve_name', {
|
|
|
85
99
|
.describe('A single autocomplete match with its ID, name, entity type, activity stats, and a disambiguation hint.'))
|
|
86
100
|
.describe('Autocomplete matches, up to 10.'),
|
|
87
101
|
}),
|
|
102
|
+
// Agent-facing success-path context — a notice when the query matched nothing so the
|
|
103
|
+
// caller sees explicit guidance rather than a silent empty array.
|
|
104
|
+
enrichment: {
|
|
105
|
+
notice: z
|
|
106
|
+
.string()
|
|
107
|
+
.optional()
|
|
108
|
+
.describe('Recovery guidance when no matches were found — echoes the query and suggests corrections. Absent when results are present.'),
|
|
109
|
+
},
|
|
88
110
|
async handler(input, ctx) {
|
|
89
111
|
const service = getOpenAlexService();
|
|
90
112
|
const result = await service.autocomplete({
|
|
@@ -97,6 +119,10 @@ export const resolveNameTool = tool('openalex_resolve_name', {
|
|
|
97
119
|
entityType: input.entity_type ?? 'all',
|
|
98
120
|
matchCount: result.results.length,
|
|
99
121
|
});
|
|
122
|
+
if (result.results.length === 0) {
|
|
123
|
+
const scope = input.entity_type ? ` among ${input.entity_type}` : '';
|
|
124
|
+
ctx.enrich.notice(`No matches for "${input.query}"${scope}. Try a shorter name, alternate spelling, or omit entity_type to search across all types.`);
|
|
125
|
+
}
|
|
100
126
|
return result;
|
|
101
127
|
},
|
|
102
128
|
format: (result) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-name.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/resolve-name.tool.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resolve-name.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/resolve-name.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,7 +34,6 @@ export declare const searchEntitiesTool: import("@cyanheads/mcp-ts-core").ToolDe
|
|
|
34
34
|
count: z.ZodNumber;
|
|
35
35
|
per_page: z.ZodNumber;
|
|
36
36
|
next_cursor: z.ZodNullable<z.ZodString>;
|
|
37
|
-
echo: z.ZodString;
|
|
38
37
|
}, z.core.$strip>;
|
|
39
38
|
results: z.ZodArray<z.ZodObject<{
|
|
40
39
|
id: z.ZodString;
|
|
@@ -66,6 +65,18 @@ export declare const searchEntitiesTool: import("@cyanheads/mcp-ts-core").ToolDe
|
|
|
66
65
|
readonly when: "OpenAlex throttled the request (HTTP 429).";
|
|
67
66
|
readonly retryable: true;
|
|
68
67
|
readonly recovery: "Wait several seconds and retry; consider lowering request frequency for this caller.";
|
|
68
|
+
}, {
|
|
69
|
+
readonly reason: "upstream_timeout";
|
|
70
|
+
readonly code: JsonRpcErrorCode.Timeout;
|
|
71
|
+
readonly when: "OpenAlex did not respond within the request deadline.";
|
|
72
|
+
readonly retryable: true;
|
|
73
|
+
readonly recovery: "Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.";
|
|
74
|
+
}, {
|
|
75
|
+
readonly reason: "upstream_unavailable";
|
|
76
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
77
|
+
readonly when: "OpenAlex returned HTTP 503 (service unavailable).";
|
|
78
|
+
readonly retryable: true;
|
|
79
|
+
readonly recovery: "Wait and retry; check https://openalex.org for service status if the outage persists.";
|
|
69
80
|
}, {
|
|
70
81
|
readonly reason: "upstream_unauthorized";
|
|
71
82
|
readonly code: JsonRpcErrorCode.Unauthorized;
|
|
@@ -80,11 +91,15 @@ export declare const searchEntitiesTool: import("@cyanheads/mcp-ts-core").ToolDe
|
|
|
80
91
|
readonly reason: "upstream_invalid_params";
|
|
81
92
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
82
93
|
readonly when: "OpenAlex rejected the request as malformed (HTTP 400).";
|
|
83
|
-
readonly recovery: "
|
|
94
|
+
readonly recovery: "The upstream message names the rejected field; the valid-fields list it appends may be truncated. Drop or correct that filter, sort, or select field — for select, retry without it to see the curated valid fields, then re-add corrected names.";
|
|
84
95
|
}, {
|
|
85
96
|
readonly reason: "upstream_validation_failed";
|
|
86
97
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
87
98
|
readonly when: "OpenAlex rejected the request as semantically invalid (HTTP 422).";
|
|
88
99
|
readonly recovery: "Read the upstream message for the specific field, then adjust the request to satisfy validation.";
|
|
89
|
-
}]
|
|
100
|
+
}], {
|
|
101
|
+
readonly echo: z.ZodString;
|
|
102
|
+
readonly totalCount: z.ZodNumber;
|
|
103
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
104
|
+
}>;
|
|
90
105
|
//# sourceMappingURL=search-entities.tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-entities.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-entities.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAiCjE,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"search-entities.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-entities.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAiCjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsS7B,CAAC"}
|
|
@@ -65,6 +65,20 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
65
65
|
retryable: true,
|
|
66
66
|
recovery: 'Wait several seconds and retry; consider lowering request frequency for this caller.',
|
|
67
67
|
},
|
|
68
|
+
{
|
|
69
|
+
reason: 'upstream_timeout',
|
|
70
|
+
code: JsonRpcErrorCode.Timeout,
|
|
71
|
+
when: 'OpenAlex did not respond within the request deadline.',
|
|
72
|
+
retryable: true,
|
|
73
|
+
recovery: 'Retry after a short delay; if timeouts persist, narrow the request with tighter filters to reduce upstream load.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
reason: 'upstream_unavailable',
|
|
77
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
78
|
+
when: 'OpenAlex returned HTTP 503 (service unavailable).',
|
|
79
|
+
retryable: true,
|
|
80
|
+
recovery: 'Wait and retry; check https://openalex.org for service status if the outage persists.',
|
|
81
|
+
},
|
|
68
82
|
{
|
|
69
83
|
reason: 'upstream_unauthorized',
|
|
70
84
|
code: JsonRpcErrorCode.Unauthorized,
|
|
@@ -81,7 +95,7 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
81
95
|
reason: 'upstream_invalid_params',
|
|
82
96
|
code: JsonRpcErrorCode.ValidationError,
|
|
83
97
|
when: 'OpenAlex rejected the request as malformed (HTTP 400).',
|
|
84
|
-
recovery: '
|
|
98
|
+
recovery: 'The upstream message names the rejected field; the valid-fields list it appends may be truncated. Drop or correct that filter, sort, or select field — for select, retry without it to see the curated valid fields, then re-add corrected names.',
|
|
85
99
|
},
|
|
86
100
|
{
|
|
87
101
|
reason: 'upstream_validation_failed',
|
|
@@ -115,7 +129,7 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
115
129
|
select: z
|
|
116
130
|
.array(z.string())
|
|
117
131
|
.optional()
|
|
118
|
-
.describe('OpenAlex top-level field names to return. Always returned: `id`, `display_name` — additional fields you list are appended. Searches apply a curated default per entity type; pass to override. Single-entity lookups (by `id`) return the full record unless set. Invalid field names produce an error
|
|
132
|
+
.describe('OpenAlex top-level field names to return. Always returned: `id`, `display_name` — additional fields you list are appended. Searches apply a curated default per entity type; pass to override. Single-entity lookups (by `id`) return the full record unless set. Invalid field names produce an error identifying the rejected field. Example: ["doi", "authorships", "primary_topic"].'),
|
|
119
133
|
per_page: z
|
|
120
134
|
.number()
|
|
121
135
|
.int()
|
|
@@ -148,9 +162,6 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
148
162
|
.string()
|
|
149
163
|
.nullable()
|
|
150
164
|
.describe('Cursor for next page. null if no more results.'),
|
|
151
|
-
echo: z
|
|
152
|
-
.string()
|
|
153
|
-
.describe('Compact echo of the input criteria (entity_type, query, filters, sort, search_mode) — useful when results are empty so callers see what was actually searched.'),
|
|
154
165
|
})
|
|
155
166
|
.describe('Result metadata including pagination.'),
|
|
156
167
|
results: z
|
|
@@ -163,6 +174,23 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
163
174
|
.describe('A single OpenAlex entity record. Core `id` and `display_name` are guaranteed; additional fields vary by entity_type and `select`.'))
|
|
164
175
|
.describe('OpenAlex entity objects passed through unchanged. Additional fields depend on entity_type and select.'),
|
|
165
176
|
}),
|
|
177
|
+
// Agent-facing context for the success path — the query/filters as parsed, the
|
|
178
|
+
// total match count, and recovery guidance for empty results. Populated via
|
|
179
|
+
// ctx.enrich(...) so it reaches structuredContent and content[] alike.
|
|
180
|
+
enrichment: {
|
|
181
|
+
echo: z
|
|
182
|
+
.string()
|
|
183
|
+
.describe('Compact echo of the input criteria (entity_type, query, filters, sort, search_mode) — surfaces what was actually searched when results are empty.'),
|
|
184
|
+
totalCount: z.number().describe('Total results matching the query/filters across all pages.'),
|
|
185
|
+
notice: z
|
|
186
|
+
.string()
|
|
187
|
+
.optional()
|
|
188
|
+
.describe('Recovery guidance when results are empty — echoes the criteria and suggests how to broaden. Absent on successful result pages.'),
|
|
189
|
+
},
|
|
190
|
+
enrichmentTrailer: {
|
|
191
|
+
echo: { label: 'Query' },
|
|
192
|
+
totalCount: { label: 'Total' },
|
|
193
|
+
},
|
|
166
194
|
async handler(input, ctx) {
|
|
167
195
|
if (input.search_mode === 'semantic' && input.per_page > SEMANTIC_PER_PAGE_CAP) {
|
|
168
196
|
throw ctx.fail('semantic_per_page_cap', `Semantic search supports at most ${SEMANTIC_PER_PAGE_CAP} results per page. Reduce per_page or switch search_mode.`, {
|
|
@@ -199,8 +227,17 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
199
227
|
resultCount: result.results.length,
|
|
200
228
|
totalCount: result.meta.count,
|
|
201
229
|
});
|
|
230
|
+
const echo = buildSearchEcho(input);
|
|
231
|
+
ctx.enrich({ echo, totalCount: result.meta.count });
|
|
232
|
+
if (result.results.length === 0) {
|
|
233
|
+
ctx.enrich.notice(`No matches for ${echo}. Try broadening the query, removing filters, or switching search_mode.`);
|
|
234
|
+
}
|
|
202
235
|
return {
|
|
203
|
-
meta: {
|
|
236
|
+
meta: {
|
|
237
|
+
count: result.meta.count,
|
|
238
|
+
per_page: result.meta.per_page,
|
|
239
|
+
next_cursor: result.meta.next_cursor,
|
|
240
|
+
},
|
|
204
241
|
results: result.results,
|
|
205
242
|
};
|
|
206
243
|
},
|
|
@@ -210,9 +247,8 @@ export const searchEntitiesTool = tool('openalex_search_entities', {
|
|
|
210
247
|
const header = result.meta.next_cursor
|
|
211
248
|
? `**${countLabel}** — next cursor: \`${result.meta.next_cursor}\``
|
|
212
249
|
: `**${countLabel}**`;
|
|
213
|
-
lines.push(
|
|
250
|
+
lines.push(header);
|
|
214
251
|
if (result.results.length === 0) {
|
|
215
|
-
lines.push('', `No matches for ${result.meta.echo}.`, 'Try broadening the query, removing filters, or switching search_mode.');
|
|
216
252
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
217
253
|
}
|
|
218
254
|
for (const record of result.results) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-entities.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-entities.tool.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"search-entities.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-entities.tool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/openalex-mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.17",
|
|
4
4
|
"description": "Access the OpenAlex academic research catalog - 270M+ publications through MCP. STDIO & Streamable HTTP.",
|
|
5
5
|
"mcpName": "io.github.cyanheads/openalex-mcp-server",
|
|
6
6
|
"type": "module",
|
|
@@ -9,14 +9,15 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"openalex-mcp-server": "dist/index.js"
|
|
11
11
|
},
|
|
12
|
-
"files": ["dist/", "README.md", "LICENSE", "CLAUDE.md", "Dockerfile", "server.json"],
|
|
12
|
+
"files": ["dist/", "README.md", "LICENSE", "CLAUDE.md", "AGENTS.md", "Dockerfile", "server.json"],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "bun scripts/build.ts",
|
|
15
15
|
"rebuild": "bun scripts/clean.ts && bun scripts/build.ts",
|
|
16
16
|
"clean": "bun scripts/clean.ts",
|
|
17
17
|
"devcheck": "bun scripts/devcheck.ts",
|
|
18
18
|
"tree": "bun scripts/tree.ts",
|
|
19
|
-
"format": "biome check --write
|
|
19
|
+
"format": "biome check --write .",
|
|
20
|
+
"format:unsafe": "biome check --write --unsafe .",
|
|
20
21
|
"lint:mcp": "bun scripts/lint-mcp.ts",
|
|
21
22
|
"lint:packaging": "bun scripts/lint-packaging.ts",
|
|
22
23
|
"list-skills": "bun scripts/list-skills.ts",
|
|
@@ -75,7 +76,7 @@
|
|
|
75
76
|
"access": "public"
|
|
76
77
|
},
|
|
77
78
|
"dependencies": {
|
|
78
|
-
"@cyanheads/mcp-ts-core": "^0.9.
|
|
79
|
+
"@cyanheads/mcp-ts-core": "^0.9.16",
|
|
79
80
|
"pino-pretty": "^13.1.3",
|
|
80
81
|
"zod": "^4.4.3"
|
|
81
82
|
},
|
|
@@ -85,7 +86,6 @@
|
|
|
85
86
|
"depcheck": "^1.4.7",
|
|
86
87
|
"ignore": "^7.0.5",
|
|
87
88
|
"tsc-alias": "^1.8.17",
|
|
88
|
-
"tsx": "^4.22.3",
|
|
89
89
|
"typescript": "^6.0.3",
|
|
90
90
|
"vitest": "^4.1.7"
|
|
91
91
|
}
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/cyanheads/openalex-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.6.
|
|
9
|
+
"version": "0.6.17",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
20
20
|
"identifier": "@cyanheads/openalex-mcp-server",
|
|
21
21
|
"runtimeHint": "node",
|
|
22
|
-
"version": "0.6.
|
|
22
|
+
"version": "0.6.17",
|
|
23
23
|
"packageArguments": [
|
|
24
24
|
{
|
|
25
25
|
"type": "positional",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
62
62
|
"identifier": "@cyanheads/openalex-mcp-server",
|
|
63
63
|
"runtimeHint": "node",
|
|
64
|
-
"version": "0.6.
|
|
64
|
+
"version": "0.6.17",
|
|
65
65
|
"packageArguments": [
|
|
66
66
|
{
|
|
67
67
|
"type": "positional",
|