@cyanheads/openalex-mcp-server 0.7.7 → 0.7.9

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 +15 -11
  2. package/CLAUDE.md +15 -11
  3. package/Dockerfile +6 -5
  4. package/README.md +2 -2
  5. package/changelog/0.1.x/0.1.0.md +21 -0
  6. package/changelog/0.1.x/0.1.1.md +27 -0
  7. package/changelog/0.2.x/0.2.0.md +24 -0
  8. package/changelog/0.2.x/0.2.1.md +12 -0
  9. package/changelog/0.2.x/0.2.2.md +25 -0
  10. package/changelog/0.2.x/0.2.3.md +17 -0
  11. package/changelog/0.2.x/0.2.4.md +10 -0
  12. package/changelog/0.2.x/0.2.5.md +12 -0
  13. package/changelog/0.2.x/0.2.6.md +11 -0
  14. package/changelog/0.2.x/0.2.7.md +10 -0
  15. package/changelog/0.2.x/0.2.8.md +15 -0
  16. package/changelog/0.2.x/0.2.9.md +21 -0
  17. package/changelog/0.3.x/0.3.0.md +10 -0
  18. package/changelog/0.3.x/0.3.1.md +17 -0
  19. package/changelog/0.3.x/0.3.2.md +28 -0
  20. package/changelog/0.3.x/0.3.3.md +18 -0
  21. package/changelog/0.4.x/0.4.0.md +23 -0
  22. package/changelog/0.5.x/0.5.0.md +23 -0
  23. package/changelog/0.6.x/0.6.0.md +28 -0
  24. package/changelog/0.6.x/0.6.1.md +15 -0
  25. package/changelog/0.6.x/0.6.10.md +21 -0
  26. package/changelog/0.6.x/0.6.11.md +32 -0
  27. package/changelog/0.6.x/0.6.12.md +18 -0
  28. package/changelog/0.6.x/0.6.13.md +23 -0
  29. package/changelog/0.6.x/0.6.14.md +13 -0
  30. package/changelog/0.6.x/0.6.15.md +21 -0
  31. package/changelog/0.6.x/0.6.16.md +23 -0
  32. package/changelog/0.6.x/0.6.17.md +22 -0
  33. package/changelog/0.6.x/0.6.18.md +18 -0
  34. package/changelog/0.6.x/0.6.19.md +17 -0
  35. package/changelog/0.6.x/0.6.2.md +28 -0
  36. package/changelog/0.6.x/0.6.20.md +16 -0
  37. package/changelog/0.6.x/0.6.21.md +23 -0
  38. package/changelog/0.6.x/0.6.3.md +30 -0
  39. package/changelog/0.6.x/0.6.4.md +16 -0
  40. package/changelog/0.6.x/0.6.5.md +29 -0
  41. package/changelog/0.6.x/0.6.6.md +20 -0
  42. package/changelog/0.6.x/0.6.7.md +16 -0
  43. package/changelog/0.6.x/0.6.8.md +23 -0
  44. package/changelog/0.6.x/0.6.9.md +26 -0
  45. package/changelog/0.7.x/0.7.0.md +15 -0
  46. package/changelog/0.7.x/0.7.1.md +34 -0
  47. package/changelog/0.7.x/0.7.2.md +24 -0
  48. package/changelog/0.7.x/0.7.3.md +31 -0
  49. package/changelog/0.7.x/0.7.4.md +13 -0
  50. package/changelog/0.7.x/0.7.5.md +38 -0
  51. package/changelog/0.7.x/0.7.6.md +16 -0
  52. package/changelog/0.7.x/0.7.7.md +18 -0
  53. package/changelog/0.7.x/0.7.8.md +11 -0
  54. package/changelog/0.7.x/0.7.9.md +31 -0
  55. package/changelog/template.md +168 -0
  56. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +3 -3
  57. package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -1
  58. package/dist/mcp-server/tools/definitions/search-entities.tool.js +28 -18
  59. package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -1
  60. package/dist/services/openalex/openalex-service.d.ts.map +1 -1
  61. package/dist/services/openalex/openalex-service.js +4 -15
  62. package/dist/services/openalex/openalex-service.js.map +1 -1
  63. package/package.json +17 -8
  64. package/server.json +3 -3
@@ -0,0 +1,32 @@
1
+ ---
2
+ summary: "Add openalex_get_citation_graph for one-hop citation traversal; polish analyze_trends (per_page, chronological year sort, broader recovery hint); redact polite-pool mailto from error messages."
3
+ breaking: false
4
+ security: true
5
+ ---
6
+
7
+ # 0.6.11 — 2026-05-20
8
+
9
+ ## Added
10
+
11
+ - **`openalex_get_citation_graph`** ([#13](https://github.com/cyanheads/openalex-mcp-server/issues/13)) — one-hop citation graph traversal from a seed work. `direction` picks the edge: `cites` (incoming citations), `cited_by` (the seed's reference list), or `related_to` (OpenAlex algorithmic related works). Wraps the underlying `cites`/`cited_by`/`related_to` filters so callers do not have to know their names. Accepts OpenAlex IDs, DOIs, PMIDs, PMCIDs as `seed_id`; non-W-IDs resolve via a singleton `/works/{id}` lookup because the citation filters reject anything other than a bare W-ID. Stacks with `filters`/`sort`/`select` to narrow the graph.
12
+ - **`per_page`** on `openalex_analyze_trends` ([#16](https://github.com/cyanheads/openalex-mcp-server/issues/16)) — caps groups per page (1-200, default 200). Useful when only the top-N groups are relevant.
13
+ - **Response metrics logging** ([#16](https://github.com/cyanheads/openalex-mcp-server/issues/16)) — service emits OpenAlex's per-request `cost_usd` and `db_response_time_ms` at debug level via `logResponseMetrics()`. Stays out of the wire shape; per-tool output schemas don't declare these fields.
14
+
15
+ ## Changed
16
+
17
+ - **`openalex_analyze_trends` `format()`** ([#15](https://github.com/cyanheads/openalex-mcp-server/issues/15)) — time-series groupings (year or `YYYY-MM-DD` keys) now render in chronological order; non-time-series groupings keep upstream count-desc order. `structuredContent` stays in upstream order regardless.
18
+ - **`openalex_analyze_trends` `upstream_invalid_params` recovery hint** ([#18](https://github.com/cyanheads/openalex-mcp-server/issues/18)) — points at both `group_by` AND `filters`, and names concrete full-text filter keys (`abstract.search`, `title.search`, `default.search`) so callers stop reaching for the non-existent bare `search` filter. `filters` arg description carries the same idiom.
19
+ - **`renderEntityRecord`** extracted from `search-entities.tool.ts` into `src/mcp-server/tools/render-entity-record.ts` so `openalex_get_citation_graph` shares the same markdown formatter.
20
+ - **`normalizeId`** now exported from `openalex-service.ts` for the citation-graph seed pre-trim.
21
+
22
+ ## Fixed
23
+
24
+ - **`throwNormalizedRequestError`** falls back to upstream `error` when `message` is missing and handles non-JSON 4xx bodies without dropping classification.
25
+
26
+ ## Security
27
+
28
+ - **Polite-pool `mailto` redaction** — strip operator-injected query params from URLs before they surface to MCP clients via thrown error text. Framework fetch errors format messages as `Fetch failed for <URL>. Status: …`, and the URL carries the polite-pool `mailto` (and any future internal additions). New `src/services/openalex/url-redaction.ts` runs an allowlist over caller-controlled params (`q`, `search`, `filter`, `sort`, `select`, `per_page`, `cursor`, `group_by`, `sample`, `seed`) so a future internal param won't silently leak.
29
+
30
+ ## Maintenance
31
+
32
+ - `@types/node` `^25.8.0 → ^25.9.1`, `tsx` `^4.22.0 → ^4.22.3`, `vitest` `^4.1.6 → ^4.1.7` (devDeps).
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: "Citation-graph seed validation and reserved-filter-key rejection; recover truncated upstream 400 messages; true population count under sample."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.12 — 2026-05-20
8
+
9
+ ## Fixed
10
+
11
+ - **`openalex_get_citation_graph` seed validation** ([#20](https://github.com/cyanheads/openalex-mcp-server/issues/20)) — non-existent `seed_id` silently returned empty results, indistinguishable from a valid seed with zero edges. Always issue a singleton `/works/{id}` lookup before walking the graph: bad seeds surface as `NotFound` (`entity_not_found`), good seeds with empty graphs return honest empty results. Removes the W-ID skip path that bypassed validation.
12
+ - **`openalex_get_citation_graph` reserved filter keys** ([#21](https://github.com/cyanheads/openalex-mcp-server/issues/21)) — `cites`/`cited_by`/`related_to` passed in `filters` were silently dropped but still echoed in `meta.echo`, so callers debugging "why isn't my filter narrowing" saw confirmation their filter applied when it hadn't. Pre-check rejects the reserved key with `InvalidParams` (`reserved_filter_key`) before hitting upstream. `filters` arg description restated to name `direction` as the owner.
13
+ - **`parseOpenAlexErrorBody` truncated upstream messages** ([#19](https://github.com/cyanheads/openalex-mcp-server/issues/19)) — the framework caps `responseBody` at 500 bytes; OpenAlex 400s enumerating valid field names exceed that, so strict `JSON.parse` failed on the truncated tail and the useful prefix was dropped (callers saw only `Status: 400`). Regex fallback now extracts the leading `error`/`message` fields from a truncated body. A new `stripTruncatedValidFieldsList` drops the alphabetically-cut "Valid fields are: …" enumeration so agents don't mistake the early-alphabet prefix for the full set; raw upstream stays on `data.upstreamMessage` for debugging.
14
+ - **`meta.count` under `sample`** — sampled searches returned the sample size as `count`, contradicting the output schema's "Total results matching the query/filters" contract. Issue a parallel `per_page=1` lookup without `sample`/`seed` and overwrite `count` with the true population.
15
+
16
+ ## Changed
17
+
18
+ - **`openalex_get_citation_graph` description** ([#22](https://github.com/cyanheads/openalex-mcp-server/issues/22)) — dropped the "thin wrapper over `openalex_search_entities` scoped to works — exposes the direction explicitly so callers do not have to know the underlying filter names" sentence. Implementation leak plus consumer-aware phrasing; the surrounding sentences carry the meaning.
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.9.1 → ^0.9.6, zod added, manifest.json + .mcpbignore scaffolded, install badges"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.13 — 2026-05-23
8
+
9
+ ## Added
10
+
11
+ - **`manifest.json`** — MCPB bundle descriptor for one-click Claude Desktop install; `bun run bundle` produces `.mcpb` via `@anthropic-ai/mcpb pack`.
12
+ - **`.mcpbignore`** — excludes non-bundle files from the `.mcpb` artifact.
13
+ - **`lint:packaging` script** — verifies env var name parity between `server.json` and `manifest.json`; runs as part of `devcheck`.
14
+ - **`bundle` script** — `bun run build && npx -y @anthropic-ai/mcpb pack . dist/@cyanheads/openalex-mcp-server.mcpb`.
15
+ - **Install badges** (README) — one-click install links for Claude Desktop (`.mcpb`), Cursor, and VS Code.
16
+
17
+ ## Changed
18
+
19
+ - **`@cyanheads/mcp-ts-core`** `^0.9.1 → ^0.9.6`.
20
+ - **`zod`** `^4.4.3` — added as a direct dependency (re-exported by mcp-ts-core; direct pin avoids range divergence).
21
+ - **`OPENALEX_API_KEY`** — corrected from required to optional across `server.json`, `manifest.json`, README, and AGENTS.md; anonymous access works without it, polite pool requires an email.
22
+ - **`devcheck`** — now includes `lint:packaging` and `list-skills` steps.
23
+ - **Skills synced** to current `@cyanheads/mcp-ts-core` versions: `maintenance`, `field-test`, `polish-docs-meta`, `release-and-publish`.
@@ -0,0 +1,13 @@
1
+ ---
2
+ summary: "cursor pagination for non-boolean group_by, corrected citation direction semantics, scope optional"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.14 — 2026-05-25
8
+
9
+ ## Fixed
10
+
11
+ - **`openalex_analyze_trends`** — non-boolean `group_by` fields now send `cursor=*` on the first request to enable pagination; previously, `next_cursor` was never returned. Boolean fields (`is_retracted`, `is_oa`, `has_orcid`, etc.) continue without cursor — they only produce two groups and upstream rejects cursor on them. ([#23](https://github.com/cyanheads/openalex-mcp-server/issues/23))
12
+ - **`openalex_literature_review`** — step 4 now directs `openalex_get_citation_graph` with `direction "cites"` for subsequent work and `direction "cited_by"` for foundational work; previous description inverted the filter semantics. ([#24](https://github.com/cyanheads/openalex-mcp-server/issues/24))
13
+ - **`openalex_literature_review`** `scope` — changed from `.default('narrow')` to `.optional()` so `prompts/list` advertises `required: false`; `generate` resolves `args.scope ?? 'narrow'` internally. ([#25](https://github.com/cyanheads/openalex-mcp-server/issues/25))
@@ -0,0 +1,21 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.9.6 → ^0.9.13: body limit guard, session-init gate, quieter client-error logs, GET /mcp keywords; dep refresh"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.15 — 2026-05-28
8
+
9
+ ## Added
10
+
11
+ - **`landing.requireAuth: false`** set explicitly in `src/index.ts` to preserve the full landing-page inventory on the hosted HTTP endpoint (framework default changed in mcp-ts-core 0.9.13).
12
+
13
+ ## Changed
14
+
15
+ - **`@cyanheads/mcp-ts-core`** ^0.9.6 → ^0.9.13. User-facing changes adopted:
16
+ - **`MCP_HTTP_MAX_BODY_BYTES`** — inbound HTTP request-body cap (default 1 MiB); oversized requests rejected with `413` before the SDK parses the body.
17
+ - **HTTP session-init gate** — stateful HTTP mode now rejects non-`initialize` requests that arrive without `Mcp-Session-Id` with HTTP 400.
18
+ - **Client error log levels** — 401/403/400/404 responses now use `warning`-level logging rather than full error pipeline; reduces noise in production logs.
19
+ - **`GET /mcp` keywords** — `package.json` `keywords` surfaced on the HTTP status JSON alongside `name`, `version`, and `description`.
20
+ - **`package.json` keywords** — `bun`, `stdio`, `streamable-http` added; picked up by `GET /mcp` keywords surface.
21
+ - **`@biomejs/biome`** ^2.4.15 → ^2.4.16.
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: "enrichment block on search/analyze/citation/resolve_name tools; query echo, true totals, and empty-result guidance in both structuredContent and content[]"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.16 — 2026-05-30
8
+
9
+ ## Added
10
+
11
+ - **`enrichment` block** on `openalex_search_entities`, `openalex_analyze_trends`, `openalex_get_citation_graph`, and `openalex_resolve_name` — query/filter echoes, true result totals, and empty-result recovery guidance now surface in a typed `enrichment` block that reaches both the `structuredContent` JSON and the `content[]` markdown trailer via `ctx.enrich()`.
12
+ - `search_entities`: `echo`, `totalCount`, and optional `notice` on empty results.
13
+ - `analyze_trends`: `echo`, `entityTotal`, and optional `notice` on zero groups.
14
+ - `get_citation_graph`: `echo`, `totalEdges`, and optional `notice` on empty traversals.
15
+ - `resolve_name`: optional `notice` on no-match results.
16
+ - **`AGENTS.md`** added to the npm `files[]` list so agent-protocol docs ship with the package.
17
+
18
+ ## Changed
19
+
20
+ - **`openalex_search_entities` / `openalex_analyze_trends` / `openalex_get_citation_graph`** — `output.meta.echo` removed; the query echo now appears in `enrichment.echo` (value and semantics unchanged; only the structuredContent key changed).
21
+ - **`@cyanheads/mcp-ts-core`** ^0.9.13 → ^0.9.16.
22
+ - **`format` script** split into `format` (safe) and `format:unsafe` (--unsafe flag); `format` no longer passes `--unsafe`.
23
+ - **`skills/devcheck/SKILL.md`** removed — content merged into `api-linter` skill in the framework.
@@ -0,0 +1,22 @@
1
+ ---
2
+ summary: "tool contract fixes: upstream_timeout/unavailable recovery hints, tightened invalid-params hints, direction-inversion note, consumer-phrasing scrub; remove unused tsx devDependency"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.17 — 2026-06-01
8
+
9
+ ## Added
10
+
11
+ - **`upstream_timeout` and `upstream_unavailable` error contracts** declared on all four tool definitions (`openalex_search_entities`, `openalex_analyze_trends`, `openalex_get_citation_graph`, `openalex_resolve_name`) — recovery hints now surface on the wire for HTTP 408/504 (timeout) and HTTP 503 (unavailable) responses. ([#35](https://github.com/cyanheads/openalex-mcp-server/issues/35))
12
+
13
+ ## Changed
14
+
15
+ - **`openalex_search_entities` / `openalex_analyze_trends` / `openalex_get_citation_graph`** `upstream_invalid_params` recovery hints tightened: no longer direct callers to read a valid-fields list that may be absent due to upstream body truncation; hints now acknowledge the truncated case and give an actionable path (`select`: retry without the field to see curated defaults). ([#26](https://github.com/cyanheads/openalex-mcp-server/issues/26))
16
+ - **`openalex_get_citation_graph`** tool description now includes a note that `direction` follows OpenAlex's filter convention (`cites` = works that cite the seed; `cited_by` = works the seed cites), which inverts the common English reading. ([#28](https://github.com/cyanheads/openalex-mcp-server/issues/28))
17
+ - **`meta.echo` descriptions** on `openalex_search_entities`, `openalex_analyze_trends`, and `openalex_get_citation_graph` rephrased to remove consumer-aware language (`callers`); `openalex_analyze_trends` `per_page` description drops `token spend` framing. ([#28](https://github.com/cyanheads/openalex-mcp-server/issues/28))
18
+ - **`select` field description** on `openalex_search_entities` corrects the claim that invalid names produce "an error listing the valid ones" — the list may be truncated.
19
+
20
+ ## Removed
21
+
22
+ - **`tsx`** devDependency removed — all scripts run via Bun; `tsx` was unused.
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: "openalex_search_entities: curated DEFAULT_SELECT applied to ID lookups; resolveSelect helper unifies ID and search paths; select: [\"*\"] sentinel for full record"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.18 — 2026-06-01
8
+
9
+ ## Changed
10
+
11
+ - **`openalex_search_entities` ID lookups** now apply the curated per-entity-type `DEFAULT_SELECT` when `select` is omitted — consistent with search/filter calls. A bare ID lookup previously returned the full ~49-field / ~32 KB record. ([#29](https://github.com/cyanheads/openalex-mcp-server/issues/29))
12
+ - **`select: ["*"]` sentinel** opts into the full upstream record on both ID lookups and search/filter calls. OpenAlex has no `select=*` wildcard; the sentinel is consumed in the service (not forwarded). ([#29](https://github.com/cyanheads/openalex-mcp-server/issues/29))
13
+ - **`resolveSelect` helper** introduced internally — single code path for `select` projection on ID lookups and search/filter calls: omitted/empty → `DEFAULT_SELECT`; contains `*` → full record; explicit list → those fields.
14
+ - **`openalex_search_entities` tool and field descriptions** updated to document the curated default on ID lookups and the `["*"]` full-record opt-in.
15
+
16
+ ## Dependency bumps
17
+
18
+ - `vitest` ^4.1.7 → ^4.1.8 (dev)
@@ -0,0 +1,17 @@
1
+ ---
2
+ summary: "Adopt @cyanheads/mcp-ts-core 0.9.21: per-request log context fix, fetchWithTimeout secret scrubbing, withRetry fail-fast on non-retryable errors"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.19 — 2026-06-02
8
+
9
+ ## Changed
10
+
11
+ - **HTTP transport** per-request logs and traces now carry fresh request + trace/span IDs instead of the frozen boot context — fixes log correlation for concurrent requests. (framework: `@cyanheads/mcp-ts-core` 0.9.21)
12
+ - **`fetchWithTimeout`** strips query-string secrets (e.g. `?api_key=`) from error messages and logs before surfacing them. (framework)
13
+ - **`withRetry`** fails fast on non-retryable errors rather than exhausting retry attempts; `ctx.fail` auto-populates the `retryable` flag on the error payload. (framework)
14
+
15
+ ## Dependencies
16
+
17
+ - `@cyanheads/mcp-ts-core` ^0.9.16 → ^0.9.21
@@ -0,0 +1,28 @@
1
+ ---
2
+ summary: "Framework bump to ^0.7.4 — fail-closed Origin guard for HTTP, framework-antipattern devcheck step, literal-variant linter exemption, issue templates"
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.2 — 2026-04-25
7
+
8
+ Picks up `@cyanheads/mcp-ts-core` 0.7.1 → 0.7.4 (HTTP security hardening, format-parity numeric tightening, linter union-literal exemption) and the skill/script updates that ship with them. No behavior changes in this server's tools or prompts — maintenance release.
9
+
10
+ ## Added
11
+
12
+ - **HTTP `MCP_ALLOWED_ORIGINS`** — documented in `.env.example` and the README env-var table. Framework 0.7.1 ships a fail-closed Origin allow-list for browser POSTs (loopback-only when unset, `*` to disable). Non-browser clients (no `Origin` header) are unaffected.
13
+ - **`scripts/check-framework-antipatterns.ts`** + **Framework Antipatterns devcheck step** — new check guards against three SDK-coupling shortcuts (inputSchema downgrade, post-register mutation, transport-layer error-text matching). Manually copied from the package as a workaround for [cyanheads/mcp-ts-core#69](https://github.com/cyanheads/mcp-ts-core/issues/69) and [#73](https://github.com/cyanheads/mcp-ts-core/issues/73), which prevent the script from being synced automatically by maintenance Phase C / `init`.
14
+ - **`.github/ISSUE_TEMPLATE/`** — bug, feature, and disabled blank-issue templates with a primary/secondary label split (`regression`/`performance`/`security`/`breaking-change`) matching the framework-side convention.
15
+
16
+ ## Changed
17
+
18
+ - Bumped `@cyanheads/mcp-ts-core` `^0.7.0` → `^0.7.4` (no breaking changes). Spans:
19
+ - **0.7.1** — HTTP transport security hardening (Origin guard, validated landing-page bearer check, raw-payload logging removed, opt-in LLM transcripts).
20
+ - **0.7.2** — `vitest.config` subpath ships as `.mjs` (fixes Node 22.7+ type-strip failure under `node_modules`); new framework-antipattern devcheck step.
21
+ - **0.7.3** — `format-parity` numeric normalization rejects lossy digit-shift transforms while preserving locale support; `fetchWithTimeout` SSRF guard documented as best-effort with DNS-rebinding caveat.
22
+ - **0.7.4** — linter exempts `z.literal` union variants from `describe-on-fields`; landing connect snippets resist Cloudflare email rewriting and accept operator overrides; maintenance skill surfaces new/changed skills at end-of-run.
23
+ - Resynced framework skills:
24
+ - **`api-linter`** 1.1 → 1.2 — adds the `z.literal` union-variant exemption row to the `describe-on-fields` table, with a worked form-client blank-tolerance example.
25
+ - **`maintenance`** 1.5 → 1.6 — adds a "New/changed skills available" section to the end-of-run summary so users learn about new framework skills (e.g. `security-pass`) without forcing auto-invocation.
26
+ - Resynced framework script: `scripts/devcheck.ts` — adds the Framework Antipatterns step.
27
+ - `CLAUDE.md` / `AGENTS.md` checklist — clarifies that when regex/length constraints matter on form-client-tolerant optional fields, `z.union([z.literal(''), z.string().regex(...).describe(...)])` is the canonical shape (literal variants are exempt from `describe-on-fields`).
28
+ - Regenerated `docs/tree.md`.
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: "openalex_analyze_trends: order parameter, count-desc default, cursor fix, truncation notice"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.20 — 2026-06-04
8
+
9
+ ## Added
10
+
11
+ - **`openalex_analyze_trends`** — new `order` input field (`"count"` | `"key"`). `"count"` (default) returns the top-N groups by count descending; `"key"` enumerates all distinct values in key-ascending order with cursor pagination. ([#37](https://github.com/cyanheads/openalex-mcp-server/issues/37))
12
+ - **`openalex_analyze_trends`** — truncation notice via `ctx.enrich.notice` when `groups.length === per_page`: reports the smallest shown count and advises narrowing with filters, raising `per_page`, or switching to `order: "key"` for full enumeration.
13
+
14
+ ## Fixed
15
+
16
+ - **`analyze()`** — first-page group-by requests no longer send `cursor=*` unconditionally. Count-descending mode (default) omits the cursor so OpenAlex returns groups ranked by count; `cursor=*` is now reserved for `order: "key"` (key-ascending full enumeration). This makes `per_page` a real top-N knob and removes the regression introduced by #23. ([#37](https://github.com/cyanheads/openalex-mcp-server/issues/37))
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: "openalex_describe_fields tool, ranked invalid-field suggestions, comma-safe filters"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.21 — 2026-06-08
8
+
9
+ ## Added
10
+
11
+ - **`openalex_describe_fields`** — new tool: lists valid `filter`, `group_by`, and `select` field names for any entity type. Accepts an optional `query` for similarity-ranked narrowing (token-set + Jaro-Winkler). Backed by a build-time-generated catalog (`src/services/openalex/field-catalog.json`) derived from OpenAlex's own field validation. ([#40](https://github.com/cyanheads/openalex-mcp-server/issues/40))
12
+ - **`field-ranker.ts`** — zero-dependency field ranking module: token-set overlap blended with Jaro-Winkler; used by `openalex_describe_fields` and the invalid-field suggestion path. ([#40](https://github.com/cyanheads/openalex-mcp-server/issues/40))
13
+ - **`scripts/generate-field-catalog.ts`** — build-time catalog generator; re-run via `bun run generate:field-catalog` when OpenAlex's field validation changes. ([#40](https://github.com/cyanheads/openalex-mcp-server/issues/40))
14
+
15
+ ## Changed
16
+
17
+ - **`throwNormalizedRequestError`** — invalid-field 400s now append ranked "did you mean" suggestions (top 5 matches from the catalog) and an `openalex_describe_fields` usage hint, replacing the previous `(list of valid fields omitted — was truncated upstream)` dead-end. ([#40](https://github.com/cyanheads/openalex-mcp-server/issues/40))
18
+ - **`search-entities`**, **`analyze-trends`**, **`citation-graph`** tools — invalid-field recovery hints updated to reference `openalex_describe_fields`. ([#40](https://github.com/cyanheads/openalex-mcp-server/issues/40))
19
+ - **`buildFilterString`** — `.search` filter values containing commas are now double-quote-wrapped for faithful phrase passthrough (e.g., `title.search:"climate, biodiversity"`). Non-search filters with commas raise a clear `comma_in_filter_value` pre-flight error suggesting `|` for OR logic. ([#38](https://github.com/cyanheads/openalex-mcp-server/issues/38))
20
+
21
+ ## Changed (deps)
22
+
23
+ - **`@types/node`** `^25.9.1 → ^25.9.2`
@@ -0,0 +1,30 @@
1
+ ---
2
+ summary: "Field-test issue triage — HTML entity decoding, abstract select alias, dense flat format, empty-result echo, semantic per_page guard, framework ^0.7.5"
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.3 — 2026-04-26
7
+
8
+ Patch release driven by the 0.6.2 field-test pass. Closes six issues with concrete behavior changes plus a framework bump. No tool/prompt API surface changes — all output schemas remain backward-compatible additions (`meta.echo`).
9
+
10
+ ## Added
11
+
12
+ - **`meta.echo` on `openalex_search_entities` and `openalex_analyze_trends`** — every response carries a compact echo of the input criteria (entity_type, query, filters, sort, search_mode for search; entity_type, group_by, filters for analyze). On empty results, the echo is also surfaced in the human-readable text along with a broadening hint, so an LLM can re-issue a corrected call without backscanning its prior tool call. ([#7](https://github.com/cyanheads/openalex-mcp-server/issues/7))
13
+ - **Pre-upstream `per_page ≤ 50` guard for semantic search** in `openalex_search_entities`. Caller-side `invalidParams` is thrown before the OpenAlex round-trip, with a clear message naming the cap. The `per_page` description now cross-references the cap and the 1 req/sec rate limit. ([#8](https://github.com/cyanheads/openalex-mcp-server/issues/8))
14
+ - **`select: ["abstract"]` alias** on `openalex_search_entities` for `entity_type: "works"` — input is translated to `abstract_inverted_index` before forwarding to OpenAlex, response is reconstructed back to plaintext `abstract`. Symmetric with the existing output-side normalization. ([#5](https://github.com/cyanheads/openalex-mcp-server/issues/5))
15
+
16
+ ## Changed
17
+
18
+ - **`openalex_search_entities` flat dense `format()` rendering for nested fields** — replaces the per-field JSON code blocks (`**Field:**\n\`\`\`json\n{...}\n\`\`\``) with one-line dot-notation key:value pairs (`**Primary Topic:** id: T11488, display_name: ..., subfield.id: S26041, subfield.display_name: ..., field.id: F26, ...`). Arrays of objects render one item per line with bracket-indexed prefixes. **Every terminal field is preserved** — `structuredContent` and `format()` stay in parity per the framework's `format-parity` rule; the savings come from formatting density, not from dropping data. Roughly 50–70% smaller per-record output on default-select works queries. ([#9](https://github.com/cyanheads/openalex-mcp-server/issues/9))
19
+ - **`openalex_search_entities` sort field description** warns that an explicit `sort` overrides relevance ranking entirely when combined with a keyword `query`. ([#3](https://github.com/cyanheads/openalex-mcp-server/issues/3))
20
+ - **`openalex_analyze_trends` cursor description** clarifies that the first page is sorted by count descending; only subsequent (cursor) pages are sorted by key. ([#4](https://github.com/cyanheads/openalex-mcp-server/issues/4))
21
+ - Bumped `@cyanheads/mcp-ts-core` `^0.7.4` → `^0.7.5` (non-breaking). Skill resyncs in this release: `add-tool` 1.x adds the "seed orientation context" guidance section; `api-utils`, `design-mcp-server`, `field-test`, `polish-docs-meta`, `setup` carry minor authoring updates from the framework.
22
+
23
+ ## Fixed
24
+
25
+ - **HTML entity decoding at the service boundary** — `display_name`, `raw_source_name`, autocomplete `hint`, and group-by labels coming back from OpenAlex are now decoded from numeric (`&#38;`), hex (`&#x27E9;`), and named (`&amp;`, `&lt;`, etc.) entities before they reach tool output. Decoder is lenient about the trailing semicolon (real OpenAlex data sometimes returns `&#38 Hepatology` without it — surfaced live during the 0.6.3 field-test). Out-of-range numeric code points pass through unchanged instead of throwing `RangeError`. Entities living in `abstract_inverted_index` keys are also decoded via the reconstructed plaintext. ([#2](https://github.com/cyanheads/openalex-mcp-server/issues/2))
26
+
27
+ ## Closed without code changes
28
+
29
+ - [#6 — truncate verbose `hint` in `resolve_name`](https://github.com/cyanheads/openalex-mcp-server/issues/6) — closed as won't-fix. `resolve-name` has a fully-typed output schema (no `passthrough`); truncating the `hint` field in `format()` while keeping the full string in `structuredContent` violates `format-parity`. The hint length is intentional disambiguation context.
30
+ - [#4 part 1 — trim verbose URL keys in analyze_trends](https://github.com/cyanheads/openalex-mcp-server/issues/4) — closed as won't-fix for the same reason. `key` is a typed terminal field; rendering only the URL tail in `format()` would drop the canonical identifier from the human-readable surface.
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: search_entities — caller-supplied select missing id/display_name no longer breaks output validation; framework ^0.7.5 adoption (vitest projects shape)
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.4 — 2026-04-27
7
+
8
+ Bug-fix release for [#11](https://github.com/cyanheads/openalex-mcp-server/issues/11) plus a small framework-adoption pass picked up during the maintenance flow.
9
+
10
+ ## Fixed
11
+
12
+ - **`openalex_search_entities` — caller-supplied `select` no longer breaks output validation ([#11](https://github.com/cyanheads/openalex-mcp-server/issues/11))** — `translateSelect` in `src/services/openalex/openalex-service.ts` now prepends and dedupes `id` / `display_name` (a new `REQUIRED_SEARCH_FIELDS` invariant) before forwarding to OpenAlex. Previously, a caller passing e.g. `select: ["doi", "title", "publication_year"]` got an upstream 200, but the framework's output Zod schema then rejected the response (`results.0.id: expected string, received undefined`) because OpenAlex projects out exactly the requested fields. The failure ate the full upstream cost (one observed case wasted 369 KB and 1.3 s) before surfacing — and the wire error blamed the response, not the caller's `select`. Both call sites are covered: search/list and singleton id-lookup. The `select` field description tightened to make the invariant explicit: *"Always returned: `id`, `display_name` — additional fields you list are appended."* Added 4 regression tests in `tests/services/openalex/openalex-service.test.ts`.
13
+
14
+ ## Changed
15
+
16
+ - **`vitest.config.ts` adopted Vitest 4 `projects` shape** — matches the `@cyanheads/mcp-ts-core` 0.7.5 template; positions the suite to split into smoke/integration/fuzz projects as it grows. Current `unit` project includes the existing `src/**/*.test.ts` and `tests/**/*.test.ts` and excludes the named subdirs. No test behavior change today.
@@ -0,0 +1,29 @@
1
+ ---
2
+ summary: "Adopt @cyanheads/mcp-ts-core 0.7.5 → 0.8.7: typed error contracts on every tool, service-layer reason carrying via ctx.recoveryFor, httpStatusToErrorCode replaces manual status mapping (fixes 422 → ValidationError, other 4xx → InvalidRequest)"
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.5 — 2026-04-30
7
+
8
+ Maintenance release picking up nine versions of `@cyanheads/mcp-ts-core` (0.7.5 → 0.8.7), led by 0.8.0's typed error contracts. Every tool now declares a public failure surface; the OpenAlex service routes upstream errors through `httpStatusToErrorCode` and carries the matching `reason` (plus contract `recovery.hint`) onto the wire, so agents can switch on `error.data.reason` instead of parsing message text. No wire-shape regressions in practice — the only contracts we relied on (`_meta.error` from 0.8.3, retired) weren't read by any caller.
9
+
10
+ ## Added
11
+
12
+ - **Typed error contracts on every tool** — `errors[]` declared on `openalex_search_entities` (7 reasons: `semantic_per_page_cap`, `entity_not_found`, `rate_limited`, `upstream_unauthorized`, `upstream_forbidden`, `upstream_invalid_params`, `upstream_validation_failed`), `openalex_analyze_trends` and `openalex_resolve_name` (5 reasons each, sans the id-lookup-specific entries). Every entry carries a ≥5-word `recovery` string per 0.8.4's lint rule. The `semantic_per_page_cap` handler-direct throw now routes through `ctx.fail(reason, …)` so `data.reason` is auto-populated and the conformance lint can enforce coverage.
13
+ - **Service-layer reason carrying** — `OpenAlexService.throwNormalizedRequestError` consults a single `JsonRpcErrorCode → { factory, reason }` map driven by `httpStatusToErrorCode` from `@cyanheads/mcp-ts-core/utils`. Each factory throw now spreads `ctx.recoveryFor(reason)` so the calling tool's contract recovery flows through to `data.recovery.hint` automatically. Same pattern in `parseResponse` for the `upstream_unavailable` reason.
14
+
15
+ ## Changed
16
+
17
+ - **`OpenAlexService` HTTP-status mapping uses `httpStatusToErrorCode`** — replaces the hand-rolled switch in `src/services/openalex/openalex-service.ts`. Two visible behavior shifts: HTTP 422 now classifies as `ValidationError` (was `InvalidParams`) and other 4xx (e.g. 413, 410) classify as `InvalidRequest` (was `InvalidParams`). Both align with the framework's canonical table and improve `mcp_error_classified_code` observability. Tests updated to match.
18
+ - **`CLAUDE.md` / `AGENTS.md`** — Errors section rewritten to lead with typed contracts (factories demoted to fallback). Context table adds `ctx.fail` and `ctx.recoveryFor`. `tenantId` row covers HTTP+`MCP_AUTH_MODE=none` (`'default'` per 0.8.5).
19
+ - **Project skills resynced from `@cyanheads/mcp-ts-core`** — `add-service` 1.3 → 1.5, `add-tool` 1.8 → 2.4, `api-context` 1.1 → 1.2, `api-errors` 1.0 → 1.4, `design-mcp-server` 2.7 → 2.8, `field-test` 2.0 → 2.3, `maintenance` 1.6 → 2.0, `release-and-publish` 2.1 → 2.2, `report-issue-framework` 1.3 → 1.4, `security-pass` 1.1 → 1.2, `setup` 1.5 → 1.6.
20
+ - **Framework `scripts/` resynced** — added `scripts/split-changelog.ts`; no other scripts changed.
21
+
22
+ ## Removed
23
+
24
+ - **`dev:stdio` and `dev:http` scripts in `package.json`** — both gone from `@cyanheads/mcp-ts-core` 0.8.6/0.8.7. Use `bun run rebuild && bun run start:stdio` (or `start:http`) for production-shape smoke tests; the `Commands` table in `CLAUDE.md`/`AGENTS.md` was updated to match.
25
+
26
+ ## Maintenance
27
+
28
+ - `@cyanheads/mcp-ts-core` ^0.7.5 → ^0.8.7. No other dependency changes.
29
+ - Field-tested live against OpenAlex: `openalex_resolve_name`, `openalex_search_entities` by DOI, `openalex_analyze_trends` group-by-year, plus both new error paths (`semantic_per_page_cap` via `ctx.fail` and `entity_not_found` via service factory) — wire shape verified clean on `structuredContent.error` and mirrored into `content[]` text per 0.8.3's parity invariant.
@@ -0,0 +1,20 @@
1
+ ---
2
+ summary: "search_entities — coerce bare relevance_score sort to descending so OpenAlex stops rejecting it; document that relevance_score requires an active search"
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.6 — 2026-05-01
7
+
8
+ Bug-fix release. The `openalex_search_entities` tool's `sort` description recommended `relevance_score` (bare), but OpenAlex defaults bare-direction sorts to `:asc` and forbids ascending relevance — every such call returned `400 Bad Request: "Sorting relevance score ascending is not allowed."` Verified live against the API: ascending relevance is rejected, descending succeeds, and the field additionally requires an active search query.
9
+
10
+ ## Fixed
11
+
12
+ - **`normalizeSort` coerces bare `relevance_score` to `relevance_score:desc`** — `src/services/openalex/openalex-service.ts`. Information-preserving (ascending relevance has no semantic meaning), so it isn't a guess at intent. The existing `-` prefix path (`-relevance_score` → `relevance_score:desc`) is unchanged. Other ascending sorts continue to pass through untouched. Closes [#12](https://github.com/cyanheads/openalex-mcp-server/issues/12).
13
+
14
+ ## Changed
15
+
16
+ - **`openalex_search_entities` `sort` description** — recommends `-relevance_score` to match the documented `-` prefix convention, and now warns that `relevance_score` requires an active search via `query` or a `filter:search` filter. The previous wording (*"Use `relevance_score` or omit sort"*) actively encouraged the failing pattern.
17
+
18
+ ## Maintenance
19
+
20
+ - 4 unit tests added for `normalizeSort` covering bare passthrough, the new `relevance_score` coercion, the `-relevance_score` translation, and no-sort omission. Field-tested live against OpenAlex: the issue's exact reproduction (`query: "natural remedy edema feet"`, `sort: "relevance_score"`) now returns 200 with relevance ranking; `-relevance_score` without a query surfaces the documented "must include a search query" constraint with the contract recovery hint.
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: "Maintenance: pick up @cyanheads/mcp-ts-core 0.8.7 → 0.8.12, biome 2.4.13 → 2.4.14, tsc-alias 1.8.16 → 1.8.17; resync 7 framework skills + add api-canvas reference. No tool/service code changes."
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.7 — 2026-05-03
7
+
8
+ Pure maintenance release. Five framework versions of `@cyanheads/mcp-ts-core` (0.8.8 → 0.8.12) — all additive (DataCanvas Tier-3 primitive, `disabledTool()` wrapper, mutability-bucket annotations, `RequestContext` widening, SQL-gate hardening). None of the new surfaces apply to this server: there's no canvas usage, no feature-flagged tools to disable, and the existing `readOnlyHint`/`idempotentHint` annotations already place all three tools in the `read` mutability bucket. Audited the current `OpenAlexService` HTTP-error pattern (`fetchWithTimeout` + `httpStatusToErrorCode` + factory throw with `data.reason`) against the `httpErrorFromResponse` helper introduced earlier in 0.8.x — both helpers operate at different layers (transport vs. plain-fetch classification) and the current pattern is correct, not suboptimal.
9
+
10
+ ## Maintenance
11
+
12
+ - `@cyanheads/mcp-ts-core` ^0.8.7 → ^0.8.12.
13
+ - `@biomejs/biome` ^2.4.13 → ^2.4.14, `tsc-alias` ^1.8.16 → ^1.8.17 (devDeps).
14
+ - Project skills resynced from package: `add-tool` 2.4 → 2.6, `api-config` 1.2 → 1.3, `api-workers` 1.1 → 1.2, `design-mcp-server` 2.8 → 2.9, `report-issue-framework` 1.4 → 1.5, `report-issue-local` 1.3 → 1.4, `security-pass` 1.2 → 1.3. Added `api-canvas` (new external skill) for reference.
15
+ - Phase B agent-skill mirrors (`.claude/skills/`, `.agents/skills/`) refreshed from the project `skills/` tree.
16
+ - Phase C framework `scripts/` already in sync; no script changes.
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: "search_entities — random sampling via sample/seed (#14); alias common LLM-prior field/filter names to OpenAlex canonical names (#17)."
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.8 — 2026-05-05
7
+
8
+ Two field-test follow-ups against `openalex_search_entities`. Both close gaps surfaced from production traffic where LLM callers either lacked an OpenAlex feature surface (random sampling) or guessed intuitive names that don't match upstream's vocabulary (`year` for `publication_year`, `cited_works` for `cites`, `id` for `openalex`).
9
+
10
+ ## Added
11
+
12
+ - `openalex_search_entities` — `sample` (1-100) and `seed` parameters expose OpenAlex's native random sampling. Single page only; mutually exclusive with `cursor`. `seed` requires `sample`. Both rejections wired through typed error contracts (`sample_with_cursor`, `seed_without_sample`) so the recovery hint reaches the LLM. Service layer aligns `per_page` to `sample` to prevent silent truncation when `sample > per_page`. Closes [#14](https://github.com/cyanheads/openalex-mcp-server/issues/14).
13
+ - `tool-defs-analysis` skill — read-only audit of LLM-facing definition language across tools/resources/prompts (voice, leaks, recovery, sparsity, structure).
14
+
15
+ ## Changed
16
+
17
+ - `openalex_search_entities` filter description anchors positive priors with concrete common keys (`openalex`, `cites`, `publication_year`, `authorships.author.id`, `type`, `is_oa`) and resolves the most-mistaken names server-side: see Fixed.
18
+ - `semantic_per_page_cap` error code reclassified `InvalidParams` → `ValidationError` for parity with the other pre-upstream input-shape rejections in the contract.
19
+
20
+ ## Fixed
21
+
22
+ - `openalex_search_entities` filter aliases — works-only `cited_works` → `cites`, `year` → `publication_year`, plus a universal `id` → `openalex` rewrite when the value matches an OpenAlex ID pattern (bare or URL-form, pipe-joined OR supported). Pure key renames; values pass through. Misses fall through so upstream's helpful 400 still fires for typos. Closes [#17](https://github.com/cyanheads/openalex-mcp-server/issues/17).
23
+ - `openalex_search_entities` select aliases — works-only `year` → `publication_year`, `authors` → `authorships`, joining the existing `abstract` → `abstract_inverted_index` rewrite. Same shape as filter aliases.
@@ -0,0 +1,26 @@
1
+ ---
2
+ summary: "Adopt @cyanheads/mcp-ts-core ^0.8.15 → ^0.8.19; bump Node engine ≥24, pin Docker base to oven/bun:1.3; tighten tool/prompt copy."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.6.9 — 2026-05-08
8
+
9
+ Maintenance release. Picks up four framework versions (`@cyanheads/mcp-ts-core` 0.8.15 → 0.8.19) — HTTP SSE leak fix, `ctx.sessionId` for HTTP handlers, `ctx.auth.token` forwarding, telemetry visualization docs. None of the new surfaces require code changes here; the upstream engine bump is the one consumer-visible knock-on.
10
+
11
+ ## Changed
12
+
13
+ - **Node engine** ≥22 → ≥24 to match `@cyanheads/mcp-ts-core` ^0.8.19.
14
+ - **Dockerfile** base pinned `oven/bun:1` → `oven/bun:1.3` (build + production stages) — track Bun engine floor explicitly instead of drifting on the `1` rolling tag.
15
+ - **`openalex_search_entities`** — `general_failure` recovery now points at the upstream message + the rejected token rather than a generic "check the docs" hint. Description drops the "(free, unlimited API calls)" aside on `id` lookup.
16
+ - **`openalex_analyze_trends`** — `general_failure` recovery names valid `group_by` fields per entity_type (e.g. `publication_year`/`type`/`oa_status` for works, `country_code`/`has_orcid` for authors) instead of pointing at the docs.
17
+ - **`openalex_resolve_name`** — `entity_type` output description enumerates the concrete set (`work, author, source, institution, topic, keyword, publisher, funder`); description drops the "Response time ~200ms" aside.
18
+ - **`openalex_literature_review`** / **`openalex_research_landscape`** — `topic` arg descriptions now carry a concrete example so LLMs anchor on shape, not on prose.
19
+
20
+ ## Maintenance
21
+
22
+ - `@cyanheads/mcp-ts-core` ^0.8.15 → ^0.8.19.
23
+ - `@types/node` ^25.6.0 → ^25.6.2 (devDep).
24
+ - New `api-telemetry` skill mirrored from the framework (OTel catalog: spans, metrics, completion logs, env config, cardinality rules).
25
+ - Framework skills resynced: `api-context`, `api-utils`, `maintenance`, `report-issue-framework`, `report-issue-local`, `setup`.
26
+ - `changelog/template.md` + `scripts/build-changelog.ts` — new `security: true` frontmatter flag + 🛡️ Security badge in the rollup, parallel to the existing `breaking` flag.
@@ -0,0 +1,15 @@
1
+ ---
2
+ summary: "openalex_analyze_trends: gated page-truncation notice on sort order; 0.7.0 recognizes openalex_describe_fields as a minor addition"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.0 — 2026-06-08
8
+
9
+ ## Fixed
10
+
11
+ - **`openalex_analyze_trends`** — the page-truncation notice is now gated on sort order. In `order: "key"` mode, the tool emits a key-ascending pagination notice keyed off `next_cursor` instead of the count-descending "top N by count" wording, whose count-bound claims were false on key-ordered pages. The count-bound notice is unchanged for the default count-descending mode. ([#41](https://github.com/cyanheads/openalex-mcp-server/issues/41))
12
+
13
+ ## Notes
14
+
15
+ 0.7.0 is a minor version bump. The `openalex_describe_fields` tool shipped in 0.6.21 — a new tool falls under semver's minor convention; the 0.6.x designation was a patch-series overstep. No API or behavior changes beyond the fix above.
@@ -0,0 +1,34 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.9.21 → ^0.10.6: identity pair, sampling removed, elicitation wired, DataCanvas SQL gate hardened; enrichment key renames totalCount; bundle cleaner; skill sync"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.1 — 2026-06-11
8
+
9
+ ## Changed
10
+
11
+ - **`createApp()`** — explicit `name: 'openalex-mcp-server'` / `title: 'openalex-mcp-server'` identity pair added to `src/index.ts`; required by `lint:packaging` check 9 (0.10.6).
12
+ - **`openalex_analyze_trends`** — enrichment trailer key renamed: `entityTotal` → `totalCount`. Matches the framework's `capped-list-no-truncation` lint rule convention; output field Zod schema and `enrichmentTrailer` label updated, `ctx.enrich()` call updated, tests updated.
13
+ - **`openalex_get_citation_graph`** — enrichment trailer key renamed: `totalEdges` → `totalCount`. Same convention alignment; output field Zod schema and `enrichmentTrailer` label updated, `ctx.enrich()` call updated, tests updated.
14
+ - **`.mcpbignore`** — `/.claude/` and `/.agents/` re-anchored to root (from `.claude/`, `.agents/`); prevents patterns from matching nested `node_modules/` runtime paths (framework fix [#207](https://github.com/cyanheads/mcp-ts-core/issues/207)).
15
+ - **`bundle` script** — appended `&& bun run scripts/clean-mcpb.ts dist/openalex-mcp-server.mcpb`; the post-pack cleaner strips `node_modules/**` agent-doc entries that root-anchored `.mcpbignore` cannot reach (0.10.6).
16
+ - **`scripts/build.ts`** — removed unused `copyAssets` function and its `copyFile`/`mkdir` imports; no field-catalog JSON to copy in this server.
17
+ - **Skills sync** — `add-prompt`, `add-resource`, `add-service`, `add-test`, `add-tool`, `api-canvas`, `api-config`, `api-context`, `api-linter`, `api-mirror`, `api-testing`, `api-workers`, `code-simplifier`, `design-mcp-server`, `orchestrations`, `polish-docs-meta`, `release-and-publish`, `report-issue-framework`, `security-pass` — all updated from mcp-ts-core 0.10.x; new `techniques/` skill directory added.
18
+ - **`scripts/lint-packaging.ts`** — large update: post-bundle content guard (check 8), entrypoint identity checks (check 9), `AGENT_DOC_ENTRY` regex, `KNOWN_DEV_DIRS`/`CRITICAL_RUNTIME_PATHS` exports.
19
+ - **`scripts/check-framework-antipatterns.ts`** — updated to skip comment lines (prevents false-positives on docs that name an antipattern).
20
+
21
+ ## Dependencies
22
+
23
+ - `@cyanheads/mcp-ts-core` ^0.9.21 → ^0.10.6 (picks up 0.10.0–0.10.6; relevant changes below)
24
+ - `@types/node` ^25.9.2 → ^25.9.3
25
+
26
+ ### Framework 0.10.x changes relevant to this server
27
+
28
+ - **`ctx.sample` removed** (0.10.3) — sampling surface deleted from `Context`; `AGENTS.md`/`CLAUDE.md` references to `ctx.sample` removed accordingly.
29
+ - **`ctx.elicit` wired on the wire** (0.10.3) — presence is now gated at request time on the client's advertised capability; previously always `undefined`.
30
+ - **`createApp()` identity fields** (0.10.3/0.10.6) — `name`, `title`, `websiteUrl`, `description` forwarded to `initialize` serverInfo and `/.well-known/mcp.json`; `lint:packaging` check 9 enforces the `name`/`title` pair matches the unscoped package name.
31
+ - **DataCanvas SQL gate hardened** (0.10.1) — non-SELECT statements fail closed; `pragma_*` table functions denied across the gate. Applies to any future canvas use in this server.
32
+ - **`ctx.enrich.truncated()` helper** (0.10.2) — eliminates cap-disclosure boilerplate; `capped-list-no-truncation` lint rule now warns on missing `truncated`/`totalCount` (the enrichment key renames above satisfy it).
33
+ - **Env-boolean stringbool** (0.10.0) — unrecognized boolean env values now throw at startup rather than silently coercing to false.
34
+ - **Bundle cleaner** (0.10.6) — `scripts/clean-mcpb.ts` strips agent-doc entries that root-anchored `.mcpbignore` cannot reach; synced to `bundle` script.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.10.6 → ^0.10.9 maintenance: fresh-scaffold devcheck guards, new floating-dependency-specifier check, plugin-manifest packaging checks; dev-dependency refresh. No behavior change."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.2 — 2026-06-20
8
+
9
+ Framework-maintenance only — no source or tool-surface changes.
10
+
11
+ ## Changed
12
+
13
+ - **`devcheck.config.json`** — added `packaging.pluginManifests: true`, enabling `lint:packaging` check 10 over `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json` (non-empty descriptions, unscoped machine name in display fields, full scoped name in the `npx -y` install arg). ([cyanheads/mcp-ts-core#240](https://github.com/cyanheads/mcp-ts-core/issues/240))
14
+ - **`scripts/check-dependency-specifiers.ts`** — new devcheck step (`Dependency Specifiers`, flag `--no-dep-specifiers`) rejecting floating specifiers (`latest`, `*`, pre-release dist-tags) in `package.json` dependency sections and `bun.lock`'s `workspaces` map. ([cyanheads/mcp-ts-core#246](https://github.com/cyanheads/mcp-ts-core/issues/246))
15
+ - **`scripts/lint-packaging.ts`** — gained the plugin-marketplace manifest validation (check 10) gated by the new `packaging.pluginManifests` flag. ([cyanheads/mcp-ts-core#240](https://github.com/cyanheads/mcp-ts-core/issues/240))
16
+ - **Fresh-scaffold devcheck guards** — `scripts/devcheck.ts` skips the git-dependent checks (TODOs/FIXMEs, Tracked Secrets, Framework Antipatterns) via a shared `isGitRepo()` guard; `scripts/build-changelog.ts --check` exits cleanly with no per-version files; `scripts/check-framework-antipatterns.ts` self-guards outside a repo; `scripts/check-skill-versions.ts` skips a `SKILL.md` deleted from the worktree. ([cyanheads/mcp-ts-core#237](https://github.com/cyanheads/mcp-ts-core/issues/237), [#242](https://github.com/cyanheads/mcp-ts-core/issues/242), [#243](https://github.com/cyanheads/mcp-ts-core/issues/243))
17
+ - **Skills sync** — `add-tool`, `api-auth`, `api-canvas`, `api-config`, `api-context`, `api-errors`, `api-services` (+ `graph`/`speech` references), `api-telemetry`, `field-test`, `git-wrapup`, `orchestrations`, `polish-docs-meta`, `report-issue-local`, `tool-defs-analysis` re-synced from mcp-ts-core 0.10.7–0.10.9.
18
+
19
+ ## Dependencies
20
+
21
+ - `@cyanheads/mcp-ts-core` ^0.10.6 → ^0.10.9
22
+ - `@biomejs/biome` ^2.4.16 → ^2.5.0
23
+ - `@types/node` ^25.9.3 → ^26.0.0
24
+ - `vitest` ^4.1.8 → ^4.1.9
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: "Breaking: OPENALEX_API_KEY now authenticates as api_key= (the old mailto= was ignored) — an email previously set there must move to the new OPENALEX_MAILTO; mcp-ts-core ^0.10.14 supply-chain guard adopted."
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.3 — 2026-07-09
8
+
9
+ > ⚠️ **Breaking for existing setups.** `OPENALEX_API_KEY` now goes upstream as `api_key=`, not the previously-ignored `mailto=`. If you had set it to an **email address** (the old polite-pool convention), OpenAlex will now reject it as an invalid key (HTTP 401). Move the email to the new `OPENALEX_MAILTO`, and set `OPENALEX_API_KEY` to a real [account key](https://openalex.org/settings/api) or leave it unset for anonymous access. See Migration below.
10
+
11
+ ## Added
12
+
13
+ - **`OPENALEX_MAILTO`** — optional email sent upstream as `mailto=` to identify yourself to OpenAlex (the polite pool), decoupled from the account credential.
14
+
15
+ ## Changed
16
+
17
+ - **`Dockerfile`** — pinned to `oven/bun:1.3.14`; build stage adds `--ignore-scripts` and a BuildKit cache mount for Bun's install cache.
18
+ - **Skills** — 12 skills re-synced from mcp-ts-core (`add-tool`, `api-canvas`, `api-linter`, `api-utils`, `api-workers`, `code-simplifier`, `design-mcp-server`, `git-wrapup`, `orchestrations`, `polish-docs-meta`, `release-and-publish`, `techniques`).
19
+
20
+ ## Fixed
21
+
22
+ - **`OPENALEX_API_KEY` now authenticates upstream** — sent as `api_key=` instead of the ignored `mailto=`, so a configured key actually authenticates under OpenAlex's usage-based pricing. ([#47](https://github.com/cyanheads/openalex-mcp-server/issues/47))
23
+ - **`api_key` redacted from surfaced error URLs** — the caller-param allowlist in `url-redaction.ts` strips it (and `mailto`) from any URL that reaches an MCP client via a thrown error.
24
+ - **Unauthorized recovery hint corrected** — all 4 tools' `upstream_unauthorized` contract now points to a real OpenAlex account API key instead of the old "email-format key" wording.
25
+
26
+ **Migration:** `OPENALEX_API_KEY` must now be an OpenAlex account API key (free from [openalex.org/settings/api](https://openalex.org/settings/api)), sent as `api_key=`. If you previously placed an email address there for polite-pool identification, move it to the new `OPENALEX_MAILTO` above.
27
+
28
+ ## Dependencies
29
+
30
+ - `@cyanheads/mcp-ts-core` ^0.10.9 → ^0.10.14 — adopts the 0.10.13 supply-chain guard: `bunfig.toml` Socket scanner (`@socketsecurity/bun-security-scanner`) plus `minimumReleaseAge` (3-day hold on freshly published packages, excluding same-day framework releases), a new `.github/SECURITY.md`, and a new `.gitattributes`.
31
+ - Transitive bumps via the lock re-resolve: `js-yaml`, `vite`, `hono`. `bun audit` reports zero vulnerabilities.
@@ -0,0 +1,13 @@
1
+ ---
2
+ summary: "Fix: research_landscape funding step resolves funder IDs correctly; invalid-params 400 recovery branches by upstream failure shape; describe_fields(group_by) no longer advertises non-groupable fields."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.7.4 — 2026-07-09
8
+
9
+ ## Fixed
10
+
11
+ - **`openalex_research_landscape` funding step** — the "Funding" step now resolves `awards.funder_id` values via `openalex_search_entities` (`entity_type: "funders"`, `id: <funder_id>`); `openalex_resolve_name` is a name-autocomplete endpoint and cannot resolve an ID. Also notes `awards.funder_display_name` as a zero-hop `group_by` when readable labels suffice and exact counts aren't critical. ([#46](https://github.com/cyanheads/openalex-mcp-server/issues/46))
12
+ - **Invalid-params 400 recovery now branches by upstream failure shape** — `openalex-service.ts` adds `classifyInvalidParamsReason()`, so a rejected 400 no longer always claims a rejected field name. Rejected field name keeps `upstream_invalid_params` (describe_fields + close matches); a relevance sort without an active search maps to the new `upstream_sort_requires_search`; an ungroupable `group_by` target maps to the new `upstream_ungroupable_group_by`; any other 400 falls to the new neutral `upstream_invalid_params_other`. `search-entities`, `analyze-trends`, and `citation-graph` each declare the reasons they can actually produce, with matching recovery text. ([#43](https://github.com/cyanheads/openalex-mcp-server/issues/43))
13
+ - **`openalex_describe_fields(context: "group_by")` no longer advertises non-groupable fields** — prunes `*.search`/`*.search.exact` operators, `from_*`/`to_*` range-modifier keys, and the raw date fields (`publication_date`, `created_date`, `updated_date`) from the `group_by` view; integer count fields stay groupable. For `works`, 24 of 206 filter fields are excluded, so `group_by` now returns 182. The `context` param description and the `getFieldCatalog()` JSDoc no longer claim group_by shares the same valid set as filter. ([#42](https://github.com/cyanheads/openalex-mcp-server/issues/42))