@digital-science-dsl/dimensions-analytics-mcp 1.2.0 → 1.3.1

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 (102) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/dist/http-main.js +2 -0
  4. package/dist/http-main.js.map +1 -1
  5. package/dist/main.d.ts +0 -5
  6. package/dist/main.d.ts.map +1 -1
  7. package/dist/main.js +3 -1
  8. package/dist/main.js.map +1 -1
  9. package/dist/mcp/auto-update.d.ts +63 -0
  10. package/dist/mcp/auto-update.d.ts.map +1 -0
  11. package/dist/mcp/auto-update.js +295 -0
  12. package/dist/mcp/auto-update.js.map +1 -0
  13. package/dist/mcp/examples/dsl-examples.d.ts +2 -2
  14. package/dist/mcp/examples/dsl-examples.d.ts.map +1 -1
  15. package/dist/mcp/examples/dsl-examples.js +3 -1
  16. package/dist/mcp/examples/dsl-examples.js.map +1 -1
  17. package/dist/mcp/examples/usage-scenarios.d.ts.map +1 -1
  18. package/dist/mcp/examples/usage-scenarios.js +19 -0
  19. package/dist/mcp/examples/usage-scenarios.js.map +1 -1
  20. package/dist/mcp/http-server.js +3 -3
  21. package/dist/mcp/http-server.js.map +1 -1
  22. package/dist/mcp/middleware/field-aliases.d.ts +1 -1
  23. package/dist/mcp/middleware/field-aliases.d.ts.map +1 -1
  24. package/dist/mcp/middleware/field-aliases.js +0 -6
  25. package/dist/mcp/middleware/field-aliases.js.map +1 -1
  26. package/dist/mcp/resources/schema.d.ts +1 -1
  27. package/dist/mcp/resources/schema.d.ts.map +1 -1
  28. package/dist/mcp/resources/schema.js +11 -11
  29. package/dist/mcp/resources/schema.js.map +1 -1
  30. package/dist/mcp/server.d.ts +2 -2
  31. package/dist/mcp/server.d.ts.map +1 -1
  32. package/dist/mcp/server.js +2 -2
  33. package/dist/mcp/server.js.map +1 -1
  34. package/dist/mcp/tools/analytics.d.ts +1 -1
  35. package/dist/mcp/tools/analytics.d.ts.map +1 -1
  36. package/dist/mcp/tools/analytics.js +21 -21
  37. package/dist/mcp/tools/analytics.js.map +1 -1
  38. package/dist/mcp/tools/fetch-search-pages.d.ts +1 -1
  39. package/dist/mcp/tools/fetch-search-pages.d.ts.map +1 -1
  40. package/dist/mcp/tools/fetch-search-pages.js +4 -9
  41. package/dist/mcp/tools/fetch-search-pages.js.map +1 -1
  42. package/dist/mcp/tools/functions.d.ts +1 -1
  43. package/dist/mcp/tools/functions.d.ts.map +1 -1
  44. package/dist/mcp/tools/functions.js +8 -13
  45. package/dist/mcp/tools/functions.js.map +1 -1
  46. package/dist/mcp/tools/lookup.d.ts +1 -1
  47. package/dist/mcp/tools/lookup.d.ts.map +1 -1
  48. package/dist/mcp/tools/lookup.js +12 -17
  49. package/dist/mcp/tools/lookup.js.map +1 -1
  50. package/dist/mcp/tools/query.d.ts +1 -1
  51. package/dist/mcp/tools/query.d.ts.map +1 -1
  52. package/dist/mcp/tools/query.js +4 -9
  53. package/dist/mcp/tools/query.js.map +1 -1
  54. package/dist/mcp/tools/schema.d.ts +1 -1
  55. package/dist/mcp/tools/schema.d.ts.map +1 -1
  56. package/dist/mcp/tools/schema.js +7 -11
  57. package/dist/mcp/tools/schema.js.map +1 -1
  58. package/dist/mcp/tools/search.d.ts +1 -1
  59. package/dist/mcp/tools/search.d.ts.map +1 -1
  60. package/dist/mcp/tools/search.js +4 -9
  61. package/dist/mcp/tools/search.js.map +1 -1
  62. package/dist/mcp/tools/similar-documents.d.ts +1 -1
  63. package/dist/mcp/tools/similar-documents.d.ts.map +1 -1
  64. package/dist/mcp/tools/similar-documents.js +4 -9
  65. package/dist/mcp/tools/similar-documents.js.map +1 -1
  66. package/dist/mcp/usage-tracking.d.ts +1 -1
  67. package/dist/mcp/usage-tracking.d.ts.map +1 -1
  68. package/dist/mcp/utils.d.ts +1 -2
  69. package/dist/mcp/utils.d.ts.map +1 -1
  70. package/dist/mcp/utils.js +0 -4
  71. package/dist/mcp/utils.js.map +1 -1
  72. package/package.json +6 -2
  73. package/src/http-main.ts +3 -0
  74. package/src/main.ts +4 -2
  75. package/src/mcp/auto-update.ts +379 -0
  76. package/src/mcp/examples/dsl-examples.ts +3 -1
  77. package/src/mcp/examples/usage-scenarios.ts +19 -0
  78. package/src/mcp/http-server.ts +3 -3
  79. package/src/mcp/middleware/field-aliases.ts +1 -2
  80. package/src/mcp/resources/schema.ts +12 -12
  81. package/src/mcp/server.ts +3 -3
  82. package/src/mcp/tools/analytics.ts +26 -26
  83. package/src/mcp/tools/fetch-search-pages.ts +5 -6
  84. package/src/mcp/tools/functions.ts +9 -10
  85. package/src/mcp/tools/lookup.ts +13 -14
  86. package/src/mcp/tools/query.ts +5 -6
  87. package/src/mcp/tools/schema.ts +8 -9
  88. package/src/mcp/tools/search.ts +5 -6
  89. package/src/mcp/tools/similar-documents.ts +5 -6
  90. package/src/mcp/usage-tracking.ts +1 -1
  91. package/src/mcp/utils.ts +1 -3
  92. package/test/examples/dsl-examples.test.ts +8 -0
  93. package/test/examples/usage-scenarios.test.ts +3 -3
  94. package/test/integration/harness.ts +1 -3
  95. package/test/integration/hosted-client.ts +1 -3
  96. package/test/integration/hosted.e2e.test.ts +1 -1
  97. package/test/integration/verify-usage-scenarios.ts +1 -3
  98. package/test/mcp/auto-update.test.ts +347 -0
  99. package/test/middleware/field-aliases.test.ts +1 -1
  100. package/test/resources/schema.test.ts +5 -1
  101. package/test/server.test.ts +15 -3
  102. package/tsconfig.tsbuildinfo +1 -1
package/src/main.ts CHANGED
@@ -4,10 +4,12 @@
4
4
  * Starts the Dimensions Analytics MCP server with stdio transport.
5
5
  * @module main
6
6
  */
7
-
8
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
8
+ import { maybeAutoUpdateAndReexec } from "./mcp/auto-update.js";
9
9
  import { createMcpServerAsync } from "./mcp/server.js";
10
10
 
11
+ maybeAutoUpdateAndReexec();
12
+
11
13
  let close: () => Promise<void>;
12
14
 
13
15
  try {
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Best-effort version check and prefix-only auto-update for stdio installs.
3
+ * @module mcp/auto-update
4
+ */
5
+
6
+ import { spawnSync } from "node:child_process";
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
8
+ import { homedir, tmpdir } from "node:os";
9
+ import { dirname, join } from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ export const NPM_PACKAGE = "@digital-science-dsl/dimensions-analytics-mcp";
13
+ export const UPDATING_DOCS_URL =
14
+ "https://github.com/digital-science/dimensions-analytics-mcp/blob/main/docs/INSTALLATION.md#updating";
15
+ export const DEFAULT_UPDATE_INTERVAL_MS = 86_400_000;
16
+ export const NPM_VIEW_TIMEOUT_MS = 3_000;
17
+ export const NPM_INSTALL_TIMEOUT_MS = 12_000;
18
+ export const PREFIX_DIR_NAME = ".dimensions-analytics-mcp";
19
+
20
+ const REGISTRY = "https://registry.npmjs.org";
21
+ const INSTALL_SH = `bash -c "$(curl -fsSL https://raw.githubusercontent.com/digital-science/dimensions-analytics-mcp/main/scripts/install.sh)"`;
22
+ const INSTALL_PS1 =
23
+ "irm https://raw.githubusercontent.com/digital-science/dimensions-analytics-mcp/main/scripts/install.ps1 | iex";
24
+
25
+ export type InstallLayout = "prefix" | "npx" | "global" | "source" | "hosted";
26
+ export type VersionRelation =
27
+ | "same"
28
+ | "older"
29
+ | "newer-same-major"
30
+ | "newer-major"
31
+ | "incomparable";
32
+ export type UpdateCheckResult = "skipped" | "current" | "warned" | "updated";
33
+
34
+ export interface UpdateStamp {
35
+ readonly checkedAt: number;
36
+ readonly from?: string;
37
+ readonly to?: string;
38
+ readonly skippedReason?: string;
39
+ }
40
+
41
+ export interface AutoUpdateIo {
42
+ readonly now: () => number;
43
+ readonly env: NodeJS.ProcessEnv;
44
+ readonly layout: InstallLayout;
45
+ readonly currentVersion: string;
46
+ readonly allowInstall: boolean;
47
+ readonly stampPath: string;
48
+ readonly readStamp: (path: string) => UpdateStamp | undefined;
49
+ readonly writeStamp: (path: string, stamp: UpdateStamp) => void;
50
+ readonly npmView: () => string | undefined;
51
+ readonly npmInstall: (version: string) => boolean;
52
+ readonly log: (message: string) => void;
53
+ readonly reexec: () => void;
54
+ }
55
+
56
+ export function envFlagOff(value: string | undefined): boolean {
57
+ if (value == null) return false;
58
+ return ["0", "false", "off", "no"].includes(value.trim().toLowerCase());
59
+ }
60
+
61
+ export function resolvePackageRoot(moduleUrl: string = import.meta.url): string {
62
+ return join(dirname(fileURLToPath(moduleUrl)), "..", "..");
63
+ }
64
+
65
+ export function readCurrentVersion(packageRoot: string): string {
66
+ const raw = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8")) as {
67
+ version?: unknown;
68
+ };
69
+ if (typeof raw.version !== "string" || raw.version.length === 0) {
70
+ throw new Error(`Missing version in ${join(packageRoot, "package.json")}`);
71
+ }
72
+ return raw.version;
73
+ }
74
+
75
+ export function normalizePath(path: string): string {
76
+ return path.replace(/\\/g, "/");
77
+ }
78
+
79
+ export function detectInstallLayout(
80
+ packageRoot: string,
81
+ homeDir: string,
82
+ ): Exclude<InstallLayout, "hosted"> {
83
+ const root = normalizePath(packageRoot);
84
+ const prefixRoot = normalizePath(
85
+ join(
86
+ homeDir,
87
+ PREFIX_DIR_NAME,
88
+ "node_modules",
89
+ "@digital-science-dsl",
90
+ "dimensions-analytics-mcp",
91
+ ),
92
+ );
93
+ if (root === prefixRoot || root.startsWith(`${prefixRoot}/`)) return "prefix";
94
+ if (root.includes("/_npx/") || root.includes("/_npx")) return "npx";
95
+ if (root.includes("/node_modules/@digital-science-dsl/dimensions-analytics-mcp")) return "global";
96
+ return "source";
97
+ }
98
+
99
+ export function parseSemver(
100
+ version: string,
101
+ ): { major: number; minor: number; patch: number } | undefined {
102
+ const match = version
103
+ .trim()
104
+ .replace(/^v/i, "")
105
+ .match(/^(\d+)\.(\d+)\.(\d+)/);
106
+ if (!match) return undefined;
107
+ return { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) };
108
+ }
109
+
110
+ export function versionRelation(current: string, latest: string): VersionRelation {
111
+ const a = parseSemver(current);
112
+ const b = parseSemver(latest);
113
+ if (!a || !b) return "incomparable";
114
+ if (a.major === b.major && a.minor === b.minor && a.patch === b.patch) return "same";
115
+ const cmp =
116
+ a.major !== b.major
117
+ ? a.major - b.major
118
+ : a.minor !== b.minor
119
+ ? a.minor - b.minor
120
+ : a.patch - b.patch;
121
+ if (cmp > 0) return "older";
122
+ if (b.major > a.major) return "newer-major";
123
+ return "newer-same-major";
124
+ }
125
+
126
+ export function upgradeGuidance(
127
+ layout: InstallLayout,
128
+ current: string,
129
+ latest: string,
130
+ options: { major?: boolean; installFailed?: boolean } = {},
131
+ ): string {
132
+ const lines = [`Dimensions Analytics MCP ${current} is behind npm ${latest}.`];
133
+ if (options.major) {
134
+ lines.push("This is a new major version; auto-update will not apply it.");
135
+ }
136
+ if (options.installFailed) {
137
+ lines.push("Automatic update failed; install the new version manually.");
138
+ }
139
+ lines.push(upgradeRecipe(layout));
140
+ lines.push(`See ${UPDATING_DOCS_URL}`);
141
+ return lines.join("\n");
142
+ }
143
+
144
+ export function upgradeRecipe(layout: InstallLayout): string {
145
+ switch (layout) {
146
+ case "prefix":
147
+ return [
148
+ "Update with the installer, then restart your AI app:",
149
+ ` Mac/Linux: ${INSTALL_SH}`,
150
+ ` Windows PowerShell: ${INSTALL_PS1}`,
151
+ ` Or: npm install ${NPM_PACKAGE}@latest --prefix ~/${PREFIX_DIR_NAME}`,
152
+ ].join("\n");
153
+ case "npx":
154
+ return [
155
+ `Set MCP args to ["-y", "${NPM_PACKAGE}@latest"] (or clear the npx cache) and restart.`,
156
+ "Without @latest, npx keeps the cached tarball.",
157
+ ].join("\n");
158
+ case "global":
159
+ return `Run: npm install -g ${NPM_PACKAGE}@latest\nThen restart your AI app.`;
160
+ case "source":
161
+ return "Run: git pull && pnpm install && pnpm run build";
162
+ case "hosted":
163
+ return "Bump the deployed image / npm pin and redeploy. Do not run the stdio installer on the host.";
164
+ }
165
+ }
166
+
167
+ export function resolveNpmBin(
168
+ execPath: string = process.execPath,
169
+ platform: NodeJS.Platform = process.platform,
170
+ exists: (path: string) => boolean = existsSync,
171
+ ): string {
172
+ const dir = dirname(execPath);
173
+ const names = platform === "win32" ? ["npm.cmd", "npm.exe", "npm"] : ["npm"];
174
+ for (const name of names) {
175
+ const candidate = join(dir, name);
176
+ if (exists(candidate)) return candidate;
177
+ }
178
+ return platform === "win32" ? "npm.cmd" : "npm";
179
+ }
180
+
181
+ export function stampPathFor(layout: InstallLayout, homeDir: string, tmpDir: string): string {
182
+ if (layout === "hosted") {
183
+ return join(tmpDir, "dimensions-analytics-mcp-auto-update.json");
184
+ }
185
+ return join(homeDir, PREFIX_DIR_NAME, ".auto-update.json");
186
+ }
187
+
188
+ export function readStampFile(path: string): UpdateStamp | undefined {
189
+ try {
190
+ const raw = JSON.parse(readFileSync(path, "utf8")) as Partial<UpdateStamp>;
191
+ if (typeof raw.checkedAt !== "number") return undefined;
192
+ return {
193
+ checkedAt: raw.checkedAt,
194
+ ...(typeof raw.from === "string" ? { from: raw.from } : {}),
195
+ ...(typeof raw.to === "string" ? { to: raw.to } : {}),
196
+ ...(typeof raw.skippedReason === "string" ? { skippedReason: raw.skippedReason } : {}),
197
+ };
198
+ } catch {
199
+ return undefined;
200
+ }
201
+ }
202
+
203
+ export function writeStampFile(path: string, stamp: UpdateStamp): void {
204
+ mkdirSync(dirname(path), { recursive: true });
205
+ writeFileSync(path, `${JSON.stringify(stamp)}\n`, "utf8");
206
+ }
207
+
208
+ function updateIntervalMs(env: NodeJS.ProcessEnv): number {
209
+ const raw = env.DIMENSIONS_MCP_AUTO_UPDATE_INTERVAL_MS;
210
+ if (raw == null || raw.trim() === "") return DEFAULT_UPDATE_INTERVAL_MS;
211
+ const parsed = Number(raw);
212
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_UPDATE_INTERVAL_MS;
213
+ }
214
+
215
+ export function runUpdateCheck(io: AutoUpdateIo): UpdateCheckResult {
216
+ if (io.env.DIMENSIONS_MCP_UPDATED === "1") return "skipped";
217
+ if (envFlagOff(io.env.DIMENSIONS_MCP_UPDATE_CHECK)) return "skipped";
218
+
219
+ const stamp = io.readStamp(io.stampPath);
220
+ if (stamp && io.now() - stamp.checkedAt < updateIntervalMs(io.env)) {
221
+ return "skipped";
222
+ }
223
+
224
+ const latest = io.npmView();
225
+ if (latest == null) {
226
+ io.writeStamp(io.stampPath, {
227
+ checkedAt: io.now(),
228
+ from: io.currentVersion,
229
+ skippedReason: "view-failed",
230
+ });
231
+ return "current";
232
+ }
233
+
234
+ const relation = versionRelation(io.currentVersion, latest);
235
+ if (relation === "same" || relation === "older" || relation === "incomparable") {
236
+ io.writeStamp(io.stampPath, { checkedAt: io.now(), from: io.currentVersion, to: latest });
237
+ return "current";
238
+ }
239
+
240
+ const canInstall =
241
+ io.allowInstall &&
242
+ io.layout === "prefix" &&
243
+ !envFlagOff(io.env.DIMENSIONS_MCP_AUTO_UPDATE) &&
244
+ relation === "newer-same-major";
245
+
246
+ if (canInstall) {
247
+ const ok = io.npmInstall(latest);
248
+ if (ok) {
249
+ io.writeStamp(io.stampPath, { checkedAt: io.now(), from: io.currentVersion, to: latest });
250
+ io.reexec();
251
+ return "updated";
252
+ }
253
+ io.log(
254
+ upgradeGuidance(io.layout, io.currentVersion, latest, {
255
+ installFailed: true,
256
+ major: false,
257
+ }),
258
+ );
259
+ io.writeStamp(io.stampPath, {
260
+ checkedAt: io.now(),
261
+ from: io.currentVersion,
262
+ to: latest,
263
+ skippedReason: "install-failed",
264
+ });
265
+ return "warned";
266
+ }
267
+
268
+ io.log(
269
+ upgradeGuidance(io.layout, io.currentVersion, latest, {
270
+ major: relation === "newer-major",
271
+ }),
272
+ );
273
+ io.writeStamp(io.stampPath, {
274
+ checkedAt: io.now(),
275
+ from: io.currentVersion,
276
+ to: latest,
277
+ skippedReason: relation === "newer-major" ? "major" : "manual",
278
+ });
279
+ return "warned";
280
+ }
281
+
282
+ function spawnNpm(
283
+ args: string[],
284
+ timeout: number,
285
+ ): { status: number | null; stdout: string; stderr: string } {
286
+ const npmBin = resolveNpmBin();
287
+ const result = spawnSync(npmBin, args, {
288
+ encoding: "utf8",
289
+ timeout,
290
+ windowsHide: true,
291
+ shell: process.platform === "win32",
292
+ });
293
+ return {
294
+ status: result.status,
295
+ stdout: result.stdout ?? "",
296
+ stderr: result.stderr ?? "",
297
+ };
298
+ }
299
+
300
+ function npmViewLatest(): string | undefined {
301
+ const result = spawnNpm(
302
+ ["view", NPM_PACKAGE, "version", "--registry", REGISTRY],
303
+ NPM_VIEW_TIMEOUT_MS,
304
+ );
305
+ if (result.status !== 0) return undefined;
306
+ const version = result.stdout.trim().replace(/^"+|"+$/g, "");
307
+ return parseSemver(version) ? version : undefined;
308
+ }
309
+
310
+ function npmInstallVersion(version: string, prefix: string): boolean {
311
+ const result = spawnNpm(
312
+ [
313
+ "install",
314
+ `${NPM_PACKAGE}@${version}`,
315
+ "--prefix",
316
+ prefix,
317
+ "--registry",
318
+ REGISTRY,
319
+ "--no-fund",
320
+ "--no-audit",
321
+ ],
322
+ NPM_INSTALL_TIMEOUT_MS,
323
+ );
324
+ return result.status === 0;
325
+ }
326
+
327
+ function reexecCurrentProcess(): void {
328
+ const result = spawnSync(process.execPath, process.argv.slice(1), {
329
+ env: { ...process.env, DIMENSIONS_MCP_UPDATED: "1" },
330
+ stdio: "inherit",
331
+ windowsHide: true,
332
+ });
333
+ process.exit(result.status ?? 1);
334
+ }
335
+
336
+ function createIo(options: { allowInstall: boolean; layout?: InstallLayout }): AutoUpdateIo {
337
+ const home = homedir();
338
+ const packageRoot = resolvePackageRoot();
339
+ const layout = options.layout ?? detectInstallLayout(packageRoot, home);
340
+ const prefix = join(home, PREFIX_DIR_NAME);
341
+ return {
342
+ now: () => Date.now(),
343
+ env: process.env,
344
+ layout,
345
+ currentVersion: readCurrentVersion(packageRoot),
346
+ allowInstall: options.allowInstall,
347
+ stampPath: stampPathFor(layout, home, tmpdir()),
348
+ readStamp: readStampFile,
349
+ writeStamp: writeStampFile,
350
+ npmView: npmViewLatest,
351
+ npmInstall: (version) => npmInstallVersion(version, prefix),
352
+ log: (message) => console.error(message),
353
+ reexec: reexecCurrentProcess,
354
+ };
355
+ }
356
+
357
+ /**
358
+ * Stdio entry: may install + re-exec for prefix layouts.
359
+ */
360
+ export function maybeAutoUpdateAndReexec(): void {
361
+ try {
362
+ runUpdateCheck(createIo({ allowInstall: true }));
363
+ } catch (error: unknown) {
364
+ const message = error instanceof Error ? error.message : String(error);
365
+ console.error(`Dimensions Analytics MCP update check failed: ${message}`);
366
+ }
367
+ }
368
+
369
+ /**
370
+ * Hosted HTTP entry: version warning only, never install or re-exec.
371
+ */
372
+ export function maybeWarnStaleHostedVersion(): void {
373
+ try {
374
+ runUpdateCheck(createIo({ allowInstall: false, layout: "hosted" }));
375
+ } catch (error: unknown) {
376
+ const message = error instanceof Error ? error.message : String(error);
377
+ console.error(`Dimensions Analytics MCP update check failed: ${message}`);
378
+ }
379
+ }
@@ -55,13 +55,15 @@ export const DSL_EXAMPLES_BY_ENTITY: Record<string, readonly string[]> = {
55
55
  ],
56
56
  };
57
57
 
58
- /** General DSL patterns (describe, functions, pagination). */
58
+ /** General DSL patterns (describe, functions, pagination, similarity). */
59
59
  export const DSL_GENERAL_EXAMPLES = [
60
60
  "describe version",
61
61
  "describe schema",
62
62
  "describe source publications",
63
63
  'extract_concepts(text: "CRISPR gene editing enables precise DNA modification")',
64
64
  'classify(text: "Stem cell therapy for diabetes", system: "for")',
65
+ 'search publications for similar_documents("After spinal cord injury, macrophages infiltrate the lesion site") where year > 2015 return publications[id+title+year] sort by score desc limit 5',
66
+ 'search grants for similar_documents("Cancer immunotherapy with checkpoint inhibitors and CAR-T") where start_year >= 2020 return grants[id+title] sort by score desc limit 5',
65
67
  ] as const;
66
68
 
67
69
  /** Link to official DSL documentation. */
@@ -183,6 +183,25 @@ export const USAGE_SCENARIOS: readonly UsageScenario[] = [
183
183
  "limit 10",
184
184
  ],
185
185
  },
186
+ {
187
+ id: "similar-grants",
188
+ goal: "Similar grants from a description",
189
+ prompt: "Find grants similar to this description of CAR-T cancer immunotherapy.",
190
+ tool: "similar_documents",
191
+ args: {
192
+ entityType: "grants",
193
+ text: "Development of novel cancer immunotherapy approaches using checkpoint inhibitors and CAR-T cell engineering for solid tumors.",
194
+ yearFrom: 2020,
195
+ limit: 10,
196
+ fields: ["id", "title", "funding_usd", "start_year"],
197
+ },
198
+ dslContains: [
199
+ "search grants for similar_documents(",
200
+ "start_year >= 2020",
201
+ "sort by score desc",
202
+ "limit 10",
203
+ ],
204
+ },
186
205
  {
187
206
  id: "build-complex-query",
188
207
  goal: "Build a complex query",
@@ -5,8 +5,8 @@
5
5
 
6
6
  import { randomUUID } from "node:crypto";
7
7
  import type { IncomingMessage, Server } from "node:http";
8
- import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
9
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8
+ import { createMcpExpressApp } from "@modelcontextprotocol/express";
9
+ import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
10
10
  import type { Request, Response } from "express";
11
11
  import type { HostedEnvConfig } from "../client/deployment-config.js";
12
12
  import { AuthenticationError } from "../client/errors.js";
@@ -73,7 +73,7 @@ export function startHostedHttpServer(options: HostedHttpServerOptions): HostedH
73
73
  mcpClient,
74
74
  });
75
75
 
76
- const transport = new StreamableHTTPServerTransport({
76
+ const transport = new NodeStreamableHTTPServerTransport({
77
77
  sessionIdGenerator: undefined,
78
78
  });
79
79
 
@@ -4,8 +4,7 @@
4
4
  * via a higher-order function (decorator) pattern.
5
5
  * @module mcp/middleware/field-aliases
6
6
  */
7
-
8
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
7
+ import type { CallToolResult } from "@modelcontextprotocol/server";
9
8
  import type { EntityType } from "../../dsl/index.js";
10
9
 
11
10
  // ---------------------------------------------------------------------------
@@ -3,8 +3,8 @@
3
3
  * @module mcp/resources/schema
4
4
  */
5
5
 
6
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
- import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import type { McpServer } from "@modelcontextprotocol/server";
7
+ import { ResourceTemplate } from "@modelcontextprotocol/server";
8
8
  import {
9
9
  buildUsagePolicy,
10
10
  type DescribeField,
@@ -32,7 +32,7 @@ import type { SchemaContext } from "../schema/context.js";
32
32
  */
33
33
  export function registerSchemaResources(server: McpServer, context: SchemaContext): void {
34
34
  const schemaStore = () => context.store;
35
- server.resource(
35
+ server.registerResource(
36
36
  "schema-summary",
37
37
  "dimensions://schema/summary",
38
38
  {
@@ -52,7 +52,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
52
52
  );
53
53
 
54
54
  // Full schema
55
- server.resource(
55
+ server.registerResource(
56
56
  "schema-full",
57
57
  "dimensions://schema",
58
58
  {
@@ -72,7 +72,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
72
72
  );
73
73
 
74
74
  // Version
75
- server.resource(
75
+ server.registerResource(
76
76
  "schema-version",
77
77
  "dimensions://schema/version",
78
78
  {
@@ -95,7 +95,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
95
95
  );
96
96
 
97
97
  // Limits (static until upstream `describe limits` exists)
98
- server.resource(
98
+ server.registerResource(
99
99
  "schema-limits",
100
100
  "dimensions://schema/limits",
101
101
  {
@@ -113,7 +113,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
113
113
  }),
114
114
  );
115
115
 
116
- server.resource(
116
+ server.registerResource(
117
117
  "schema-policy",
118
118
  "dimensions://schema/policy",
119
119
  {
@@ -132,7 +132,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
132
132
  }),
133
133
  );
134
134
 
135
- server.resource(
135
+ server.registerResource(
136
136
  "dsl-examples",
137
137
  "dimensions://examples",
138
138
  {
@@ -160,7 +160,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
160
160
  }),
161
161
  );
162
162
 
163
- server.resource(
163
+ server.registerResource(
164
164
  "dsl-examples-by-source",
165
165
  new ResourceTemplate("dimensions://examples/{source}", {
166
166
  list: async () => ({
@@ -219,7 +219,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
219
219
  );
220
220
 
221
221
  const sourceNames = () => schemaStore().sourceNames();
222
- server.resource(
222
+ server.registerResource(
223
223
  "schema-sources",
224
224
  new ResourceTemplate("dimensions://schema/sources/{sourceName}", {
225
225
  list: async () => ({
@@ -256,7 +256,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
256
256
  );
257
257
 
258
258
  const entityNames = () => schemaStore().entityNames();
259
- server.resource(
259
+ server.registerResource(
260
260
  "schema-entities",
261
261
  new ResourceTemplate("dimensions://schema/entities/{entityName}", {
262
262
  list: async () => ({
@@ -294,7 +294,7 @@ export function registerSchemaResources(server: McpServer, context: SchemaContex
294
294
 
295
295
  // Compatibility view for structured search tools
296
296
  const entityTypes = () => schemaStore().structuredEntityTypes();
297
- server.resource(
297
+ server.registerResource(
298
298
  "fields",
299
299
  new ResourceTemplate("dimensions://fields/{entityType}", {
300
300
  list: async () => ({
package/src/mcp/server.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  * @module mcp/server
5
5
  */
6
6
 
7
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
- import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
7
+ import type { Transport } from "@modelcontextprotocol/server";
8
+ import { McpServer } from "@modelcontextprotocol/server";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
10
10
  import pkg from "../../package.json" with { type: "json" };
11
11
  import { type HostedEnvConfig, loadDeploymentConfig } from "../client/index.js";
12
12
  import { createBootstrapDimensionsClient, createDimensionsClient } from "../dsl/create-client.js";