fix(examples): resolve DIST_DIR path for npm package execution (#277)

* fix(examples): resolve DIST_DIR path for npm package execution

When servers are compiled to dist/server.js and published to npm,
`import.meta.dirname` already points to dist/, so joining with "dist"
results in dist/dist/ which doesn't exist.

This fix detects whether we're running from TypeScript source or
compiled JavaScript and adjusts the path accordingly:
- From source (server.ts): use dist/ subdirectory
- From compiled (dist/server.js): use current directory

Fixes ENOENT errors like:
"ENOENT: no such file or directory, open '.../dist/dist/mcp-app.html'"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(pdf-server): mark pdfjs-dist as external in bundle

The pdf.worker.mjs file wasn't being found when running from npm
because bun bundled pdfjs-dist but didn't include the worker file.

By marking pdfjs-dist as external, it uses the installed package
from node_modules at runtime where the worker is available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Olivier Chafik 2026-01-15 12:23:13 +00:00 • committed by GitHub
commit 89a684546b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 81 additions and 21 deletions

View file

@ -3,7 +3,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -4,7 +4,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -3,7 +3,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -3,7 +3,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -4,7 +4,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -3,7 +3,10 @@ import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/s
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
/**
* Creates a new MCP server instance with tools and resources registered.

View file

@ -17,7 +17,10 @@ import {
registerAppResource,
registerAppTool,
} from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// ---------------------------------------------------------------------------
// Schemas - types are derived from these using z.infer

View file

@ -8,7 +8,10 @@ import {
registerAppResource,
registerAppTool,
} from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// Schemas - types are derived from these using z.infer
const GetCohortDataInputSchema = z.object({

View file

@ -17,7 +17,10 @@ import {
} from "./src/data-generator.js";
import { SEGMENTS, type Customer, type SegmentSummary } from "./src/types.js";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// Schemas - types are derived from these using z.infer
const GetCustomerDataInputSchema = z.object({

View file

@ -11,7 +11,10 @@ import type {
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const RESOURCE_URI = "ui://get-time/mcp-app.html";
/**

View file

@ -21,7 +21,10 @@ import {
} from "@modelcontextprotocol/ext-apps/server";
import { randomUUID } from "crypto";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const RESOURCE_URI = "ui://cesium-map/mcp-app.html";
// Nominatim API response type

View file

@ -14,7 +14,7 @@
"dist"
],
"scripts": {
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"",
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node --external pdfjs-dist && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --external pdfjs-dist --banner \"#!/usr/bin/env node\"",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun --watch main.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve",

View file

@ -37,7 +37,10 @@ import {
type PdfIndex,
} from "./src/types.js";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const RESOURCE_URI = "ui://pdf-viewer/mcp-app.html";
const DEFAULT_PDF = "https://arxiv.org/pdf/1706.03762"; // Attention Is All You Need

View file

@ -11,7 +11,10 @@ import type {
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// ============================================================================
// Schemas - types are derived from these using z.infer

View file

@ -11,7 +11,10 @@ import type {
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const TOOL_DESCRIPTION = `Renders a ShaderToy-compatible GLSL fragment shader in real-time using WebGL 2.0.

View file

@ -12,7 +12,10 @@ import {
registerAppResource,
registerAppTool,
} from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const DEFAULT_ABC_NOTATION_INPUT = `X:1
T:Twinkle, Twinkle Little Star

View file

@ -53,7 +53,10 @@ const SystemStatsSchema = z.object({
type CpuCore = z.infer<typeof CpuCoreSchema>;
type MemoryStats = z.infer<typeof MemoryStatsSchema>;
type SystemStats = z.infer<typeof SystemStatsSchema>;
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// Returns raw CPU timing data per core (client calculates usage from deltas)
function getCpuSnapshots(): CpuCore[] {

View file

@ -14,7 +14,10 @@ import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
// Default code example for the Three.js widget
const DEFAULT_THREEJS_CODE = `const scene = new THREE.Scene();

View file

@ -11,7 +11,10 @@ import {
RESOURCE_MIME_TYPE,
RESOURCE_URI_META_KEY,
} from "@modelcontextprotocol/ext-apps/server";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const RESOURCE_URI = "ui://transcript/mcp-app.html";
/**

View file

@ -20,7 +20,10 @@ import type {
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
// 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;
const RESOURCE_URI = "ui://video-player/mcp-app.html";
/**

Some files were not shown because too many files have changed in this diff Show more