diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6848e4c46..4af5aeefb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,6 +114,21 @@ jobs: grep -q "Ready" /tmp/mcpb-smoke.log working-directory: examples/pdf-server + # import.meta.filename/dirname are undefined before Node 20.11; servers + # must still start on the oldest Node their package.json engines allows. + - uses: actions/setup-node@v6 + if: runner.os == 'Linux' && matrix.name == 'Linux x64' + with: + node-version: "20.0.0" + + - name: Smoke-test pdf-server starts on the oldest supported Node + if: runner.os == 'Linux' && matrix.name == 'Linux x64' + run: | + node --version + node .mcpb-smoke/dist/index.js --stdio < /dev/null 2>&1 | tee /tmp/mcpb-smoke-node20.log + grep -q "Ready" /tmp/mcpb-smoke-node20.log + working-directory: examples/pdf-server + dependency-isolation: name: Dependency isolation runs-on: ubuntu-latest diff --git a/docs/quickstart.md b/docs/quickstart.md index a0219122b..7235ceeda 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -183,9 +183,13 @@ import { import { McpServer } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -const DIST_DIR = path.join(import.meta.dirname, "dist"); +const DIST_DIR = path.join( + path.dirname(fileURLToPath(import.meta.url)), + "dist", +); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-preact/package.json b/examples/basic-server-preact/package.json index 60aa40d31..94eae1cd4 100644 --- a/examples/basic-server-preact/package.json +++ b/examples/basic-server-preact/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-preact" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/basic-server-preact/server.ts b/examples/basic-server-preact/server.ts index dfec94aa1..81a590173 100644 --- a/examples/basic-server-preact/server.ts +++ b/examples/basic-server-preact/server.ts @@ -5,12 +5,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-react/package.json b/examples/basic-server-react/package.json index ea51a8a1a..6fa515856 100644 --- a/examples/basic-server-react/package.json +++ b/examples/basic-server-react/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-react" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "types": "dist/server.d.ts", "bin": { diff --git a/examples/basic-server-react/server.ts b/examples/basic-server-react/server.ts index d77c908c4..38b4bbfb0 100644 --- a/examples/basic-server-react/server.ts +++ b/examples/basic-server-react/server.ts @@ -6,12 +6,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-solid/package.json b/examples/basic-server-solid/package.json index b3ca909bd..6e953bad4 100644 --- a/examples/basic-server-solid/package.json +++ b/examples/basic-server-solid/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-solid" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/basic-server-solid/server.ts b/examples/basic-server-solid/server.ts index addb52260..df077f2ce 100644 --- a/examples/basic-server-solid/server.ts +++ b/examples/basic-server-solid/server.ts @@ -5,12 +5,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-svelte/package.json b/examples/basic-server-svelte/package.json index 19fe4c9d7..a1b484539 100644 --- a/examples/basic-server-svelte/package.json +++ b/examples/basic-server-svelte/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-svelte" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/basic-server-svelte/server.ts b/examples/basic-server-svelte/server.ts index 941428514..c432061d8 100644 --- a/examples/basic-server-svelte/server.ts +++ b/examples/basic-server-svelte/server.ts @@ -5,12 +5,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-vanillajs/package.json b/examples/basic-server-vanillajs/package.json index ebfebbb70..9eaf55688 100644 --- a/examples/basic-server-vanillajs/package.json +++ b/examples/basic-server-vanillajs/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-vanillajs" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/basic-server-vanillajs/server.ts b/examples/basic-server-vanillajs/server.ts index 693d86148..451673dd9 100644 --- a/examples/basic-server-vanillajs/server.ts +++ b/examples/basic-server-vanillajs/server.ts @@ -6,11 +6,15 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/basic-server-vue/package.json b/examples/basic-server-vue/package.json index 858dd8906..f317b2b29 100644 --- a/examples/basic-server-vue/package.json +++ b/examples/basic-server-vue/package.json @@ -9,6 +9,9 @@ "directory": "examples/basic-server-vue" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/basic-server-vue/server.ts b/examples/basic-server-vue/server.ts index 9adb9111e..c952db237 100644 --- a/examples/basic-server-vue/server.ts +++ b/examples/basic-server-vue/server.ts @@ -5,12 +5,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/budget-allocator-server/package.json b/examples/budget-allocator-server/package.json index 6e41622b3..05c5bb504 100644 --- a/examples/budget-allocator-server/package.json +++ b/examples/budget-allocator-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/budget-allocator-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/budget-allocator-server/server.ts b/examples/budget-allocator-server/server.ts index 01f5dbfb6..4849aa2a4 100755 --- a/examples/budget-allocator-server/server.ts +++ b/examples/budget-allocator-server/server.ts @@ -11,16 +11,20 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; import { RESOURCE_MIME_TYPE, registerAppResource, registerAppTool, } from "@modelcontextprotocol/ext-apps/server"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // --------------------------------------------------------------------------- // Schemas - types are derived from these using z.infer diff --git a/examples/cohort-heatmap-server/package.json b/examples/cohort-heatmap-server/package.json index 7e2d2e22e..4b2b67a53 100644 --- a/examples/cohort-heatmap-server/package.json +++ b/examples/cohort-heatmap-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/cohort-heatmap-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/cohort-heatmap-server/server.ts b/examples/cohort-heatmap-server/server.ts index 129e2dc9e..fe54f5b20 100644 --- a/examples/cohort-heatmap-server/server.ts +++ b/examples/cohort-heatmap-server/server.ts @@ -4,16 +4,20 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; import { RESOURCE_MIME_TYPE, registerAppResource, registerAppTool, } from "@modelcontextprotocol/ext-apps/server"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // Schemas - types are derived from these using z.infer const GetCohortDataInputSchema = z.object({ diff --git a/examples/customer-segmentation-server/package.json b/examples/customer-segmentation-server/package.json index bac3b89bd..3d79ee4a5 100644 --- a/examples/customer-segmentation-server/package.json +++ b/examples/customer-segmentation-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/customer-segmentation-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/customer-segmentation-server/server.ts b/examples/customer-segmentation-server/server.ts index 7cc1c1fe2..83a7b4041 100644 --- a/examples/customer-segmentation-server/server.ts +++ b/examples/customer-segmentation-server/server.ts @@ -5,6 +5,7 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; import { RESOURCE_MIME_TYPE, @@ -17,10 +18,13 @@ import { } from "./src/data-generator.js"; import { SEGMENTS, type Customer, type SegmentSummary } from "./src/types.js"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // Schemas - types are derived from these using z.infer const GetCustomerDataInputSchema = z.object({ diff --git a/examples/debug-server/package.json b/examples/debug-server/package.json index e28f4d32a..7dd3242f0 100644 --- a/examples/debug-server/package.json +++ b/examples/debug-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/debug-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "types": "dist/server.d.ts", "bin": { diff --git a/examples/debug-server/server.ts b/examples/debug-server/server.ts index 068f94da3..821e4074c 100644 --- a/examples/debug-server/server.ts +++ b/examples/debug-server/server.ts @@ -11,12 +11,16 @@ import { import fs from "node:fs/promises"; import { appendFileSync } from "node:fs"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // Track call counter across requests (stateful for demo purposes) let callCounter = 0; diff --git a/examples/integration-server/server.ts b/examples/integration-server/server.ts index 346f4f7a8..a41af15ba 100644 --- a/examples/integration-server/server.ts +++ b/examples/integration-server/server.ts @@ -10,11 +10,15 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const RESOURCE_URI = "ui://get-time/mcp-app.html"; const SAMPLE_DOWNLOAD_URI = "resource:///sample-report.txt"; diff --git a/examples/lazy-auth-server/package.json b/examples/lazy-auth-server/package.json index dbd4601e2..716d86def 100644 --- a/examples/lazy-auth-server/package.json +++ b/examples/lazy-auth-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/lazy-auth-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/map-server/package.json b/examples/map-server/package.json index cc4585f2f..06e043e77 100644 --- a/examples/map-server/package.json +++ b/examples/map-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/map-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/map-server/server.ts b/examples/map-server/server.ts index 5767d46ba..fe31e1e6f 100644 --- a/examples/map-server/server.ts +++ b/examples/map-server/server.ts @@ -12,6 +12,7 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; import { registerAppTool, @@ -20,10 +21,13 @@ import { } from "@modelcontextprotocol/ext-apps/server"; import { randomUUID } from "crypto"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const resourceUri = "ui://cesium-map/mcp-app.html"; // Nominatim API response type diff --git a/examples/pdf-server/package.json b/examples/pdf-server/package.json index c8d9cf868..69deedf0a 100644 --- a/examples/pdf-server/package.json +++ b/examples/pdf-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/pdf-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/pdf-server/server.ts b/examples/pdf-server/server.ts index e67cd4731..629ace85f 100644 --- a/examples/pdf-server/server.ts +++ b/examples/pdf-server/server.ts @@ -13,6 +13,7 @@ import { randomUUID } from "crypto"; import fs from "node:fs"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppResource, registerAppTool, @@ -145,10 +146,13 @@ export function isWritablePath(resolved: string): boolean { }); } -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // ============================================================================= // Command Queue (shared across stateless server instances) diff --git a/examples/quickstart/server.ts b/examples/quickstart/server.ts index 611d0f072..7f9e1201f 100644 --- a/examples/quickstart/server.ts +++ b/examples/quickstart/server.ts @@ -6,9 +6,13 @@ import { import { McpServer } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -const DIST_DIR = path.join(import.meta.dirname, "dist"); +const DIST_DIR = path.join( + path.dirname(fileURLToPath(import.meta.url)), + "dist", +); /** * Creates a new MCP server instance with tools and resources registered. diff --git a/examples/scenario-modeler-server/package.json b/examples/scenario-modeler-server/package.json index e6f37c010..9ba247c63 100644 --- a/examples/scenario-modeler-server/package.json +++ b/examples/scenario-modeler-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/scenario-modeler-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/scenario-modeler-server/server.ts b/examples/scenario-modeler-server/server.ts index c5fa05d35..864a5c47f 100644 --- a/examples/scenario-modeler-server/server.ts +++ b/examples/scenario-modeler-server/server.ts @@ -10,11 +10,15 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // ============================================================================ // Schemas - types are derived from these using z.infer diff --git a/examples/shadertoy-server/package.json b/examples/shadertoy-server/package.json index aec56c63c..fd2d4c2b2 100644 --- a/examples/shadertoy-server/package.json +++ b/examples/shadertoy-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/shadertoy-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/shadertoy-server/server.ts b/examples/shadertoy-server/server.ts index 50c27bc66..1f901b285 100644 --- a/examples/shadertoy-server/server.ts +++ b/examples/shadertoy-server/server.ts @@ -10,11 +10,15 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const TOOL_DESCRIPTION = `Renders a ShaderToy-compatible GLSL fragment shader in real-time using WebGL 2.0. diff --git a/examples/sheet-music-server/package.json b/examples/sheet-music-server/package.json index 85ca6bb33..15998c8d3 100644 --- a/examples/sheet-music-server/package.json +++ b/examples/sheet-music-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/sheet-music-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/sheet-music-server/server.ts b/examples/sheet-music-server/server.ts index be7214ae0..36e35801b 100644 --- a/examples/sheet-music-server/server.ts +++ b/examples/sheet-music-server/server.ts @@ -5,6 +5,7 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; import ABCJS from "abcjs"; import { @@ -12,10 +13,13 @@ import { registerAppResource, registerAppTool, } from "@modelcontextprotocol/ext-apps/server"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const DEFAULT_ABC_NOTATION_INPUT = `X:1 T:Twinkle, Twinkle Little Star diff --git a/examples/system-monitor-server/package.json b/examples/system-monitor-server/package.json index 2dc3ef164..b702800bc 100644 --- a/examples/system-monitor-server/package.json +++ b/examples/system-monitor-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/system-monitor-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/system-monitor-server/server.ts b/examples/system-monitor-server/server.ts index a17bcf6c9..fcabf9bc6 100644 --- a/examples/system-monitor-server/server.ts +++ b/examples/system-monitor-server/server.ts @@ -11,13 +11,17 @@ import { import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import si from "systeminformation"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // ============================================================================= // Types and schemas diff --git a/examples/threejs-server/package.json b/examples/threejs-server/package.json index 68864d997..5a2601fcb 100644 --- a/examples/threejs-server/package.json +++ b/examples/threejs-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/threejs-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/threejs-server/server.ts b/examples/threejs-server/server.ts index 0a13c19ef..81ff8ad0b 100644 --- a/examples/threejs-server/server.ts +++ b/examples/threejs-server/server.ts @@ -14,12 +14,16 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); // Default code example for the Three.js view const DEFAULT_THREEJS_CODE = `const scene = new THREE.Scene(); diff --git a/examples/transcript-server/package.json b/examples/transcript-server/package.json index 46a8f9831..d184e0151 100644 --- a/examples/transcript-server/package.json +++ b/examples/transcript-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/transcript-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/transcript-server/server.ts b/examples/transcript-server/server.ts index 863eb2922..183f6c0c5 100644 --- a/examples/transcript-server/server.ts +++ b/examples/transcript-server/server.ts @@ -5,16 +5,20 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, } from "@modelcontextprotocol/ext-apps/server"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const resourceUri = "ui://transcript/mcp-app.html"; /** diff --git a/examples/video-resource-server/package.json b/examples/video-resource-server/package.json index 4a7a61f19..631360c20 100644 --- a/examples/video-resource-server/package.json +++ b/examples/video-resource-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/video-resource-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/video-resource-server/server.ts b/examples/video-resource-server/server.ts index 8ae624029..27070ca61 100644 --- a/examples/video-resource-server/server.ts +++ b/examples/video-resource-server/server.ts @@ -17,11 +17,15 @@ import { } from "@modelcontextprotocol/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); const RESOURCE_URI = "ui://video-player/mcp-app.html"; /** diff --git a/examples/wiki-explorer-server/package.json b/examples/wiki-explorer-server/package.json index 52304cf18..f32775028 100644 --- a/examples/wiki-explorer-server/package.json +++ b/examples/wiki-explorer-server/package.json @@ -9,6 +9,9 @@ "directory": "examples/wiki-explorer-server" }, "license": "MIT", + "engines": { + "node": ">=20" + }, "main": "dist/server.js", "files": [ "dist" diff --git a/examples/wiki-explorer-server/server.ts b/examples/wiki-explorer-server/server.ts index 8bc4eb7cb..20169c298 100644 --- a/examples/wiki-explorer-server/server.ts +++ b/examples/wiki-explorer-server/server.ts @@ -11,11 +11,15 @@ import { import * as cheerio from "cheerio"; import fs from "node:fs/promises"; import path from "node:path"; +import { fileURLToPath } from "node:url"; import { z } from "zod"; -// Works both from source (server.ts) and compiled (dist/server.js) -const DIST_DIR = import.meta.filename.endsWith(".ts") - ? path.join(import.meta.dirname, "dist") - : import.meta.dirname; +// Works both from source (server.ts) and compiled (dist/server.js). Derived +// from import.meta.url rather than import.meta.filename/dirname, which are +// undefined on Node older than 20.11. +const SERVER_FILE = fileURLToPath(import.meta.url); +const DIST_DIR = SERVER_FILE.endsWith(".ts") + ? path.join(path.dirname(SERVER_FILE), "dist") + : path.dirname(SERVER_FILE); type PageInfo = { url: string; title: string }; diff --git a/package-lock.json b/package-lock.json index 0189ca20b..751696dab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,6 +143,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-preact/node_modules/@types/node": { @@ -193,6 +196,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-react/node_modules/@types/node": { @@ -240,6 +246,9 @@ "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0", "vite-plugin-solid": "^2.11.12" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-solid/node_modules/@types/node": { @@ -287,6 +296,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-svelte/node_modules/@types/node": { @@ -332,6 +344,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-vanillajs/node_modules/@types/node": { @@ -379,6 +394,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/basic-server-vue/node_modules/@types/node": { @@ -424,6 +442,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/budget-allocator-server/node_modules/@types/node": { @@ -473,6 +494,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/cohort-heatmap-server/node_modules/@types/node": { @@ -518,6 +542,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/customer-segmentation-server/node_modules/@types/node": { @@ -562,6 +589,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/debug-server/node_modules/@types/node": { @@ -653,6 +683,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/lazy-auth-server/node_modules/@types/node": { @@ -698,6 +731,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/map-server/node_modules/@types/node": { @@ -745,6 +781,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/pdf-server/node_modules/@types/node": { @@ -845,6 +884,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/scenario-modeler-server/node_modules/@types/node": { @@ -889,6 +931,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/shadertoy-server/node_modules/@types/node": { @@ -934,6 +979,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/sheet-music-server/node_modules/@types/node": { @@ -980,6 +1028,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/system-monitor-server/node_modules/@types/node": { @@ -1032,6 +1083,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/threejs-server/node_modules/@types/node": { @@ -1077,6 +1131,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/transcript-server/node_modules/@types/node": { @@ -1122,6 +1179,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/video-resource-server/node_modules/@types/node": { @@ -1169,6 +1229,9 @@ "typescript": "^5.9.3", "vite": "^6.0.0", "vite-plugin-singlefile": "^2.3.0" + }, + "engines": { + "node": ">=20" } }, "examples/wiki-explorer-server/node_modules/@types/node": {