* fix(pdf-server): stub DOMMatrix/ImageData/Path2D for npx without @napi-rs/canvas
pdfjs-dist/legacy/build/pdf.mjs does `new DOMMatrix()` at module scope.
Its own polyfill loads @napi-rs/canvas (an optionalDependency), but npx
frequently misses the platform-native binary (npm/cli#4828), so the
server crashed on `npx @modelcontextprotocol/server-pdf --stdio`:
ReferenceError: DOMMatrix is not defined
at pdfjs-dist/legacy/build/pdf.mjs:17078
The server only uses pdfjs for text/metadata/form-field extraction —
never canvas rendering — so no-op stubs suffice and avoid shipping
~130MB of native binaries.
The polyfill is a separate ESM module kept --external in the bun bundle
so it executes before pdfjs's hoisted static import; inlined body code
would run too late.
Broken since 1.3.0 (#506). Thanks to Bryan Thompson for the analysis
and fix shape from the npm-to-mcpb pipeline.
* fix(pdf-server): MCPB bundle missing runtime deps + display_name with spaces
`mcpb pack` zips whatever is on disk; in this monorepo all runtime deps
are hoisted to root node_modules, so the published .mcpb shipped without
pdfjs-dist/ajv/express/etc. and crashed on import in Claude Desktop.
build-mcpb.mjs stages dist/ + manifest into a clean temp dir, runs a
non-workspace `npm install --omit=dev --omit=optional` (the new
DOMMatrix polyfill makes @napi-rs/canvas's ~130MB of native binaries
unnecessary), syncs manifest.version to package.json, then packs.
Result: 12.3MB / 38.8MB unpacked, full MCP handshake + tools/list pass.
Also rename display_name "PDF (By Anthropic)" → "pdf-viewer" — spaces
in display_name break MCP App UI rendering for MCPBs in Claude Desktop.
CI now smoke-tests the extracted bundle starts (`dist/index.js --stdio`
prints "Ready") so a deps-less bundle can't ship again.
* fix(pdf-server): list interact in MCPB manifest tools (was stale since #491)
56 lines
1.9 KiB
JavaScript
56 lines
1.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Build a self-contained .mcpb bundle for pdf-server.
|
|
*
|
|
* `mcpb pack` zips whatever is on disk; in this monorepo all runtime deps
|
|
* are hoisted to the root node_modules, so packing in-place produces a
|
|
* bundle with no pdfjs-dist/ajv/etc. that crashes in Claude Desktop.
|
|
*
|
|
* This script stages dist/ + manifest into a clean temp dir, runs a fresh
|
|
* non-workspace `npm install --omit=dev --omit=optional` (the polyfill in
|
|
* dist/pdfjs-polyfill.js makes @napi-rs/canvas's ~130MB of native binaries
|
|
* unnecessary), syncs the manifest version to package.json, then packs.
|
|
*/
|
|
|
|
import {
|
|
cpSync,
|
|
rmSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
writeFileSync,
|
|
} from "node:fs";
|
|
import { execSync } from "node:child_process";
|
|
import { fileURLToPath } from "node:url";
|
|
import path from "node:path";
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const stage = path.join(here, ".mcpb-stage");
|
|
const out = path.join(here, "pdf-server.mcpb");
|
|
|
|
const pkg = JSON.parse(readFileSync(path.join(here, "package.json"), "utf8"));
|
|
const manifest = JSON.parse(
|
|
readFileSync(path.join(here, "manifest.json"), "utf8"),
|
|
);
|
|
manifest.version = pkg.version;
|
|
|
|
rmSync(stage, { recursive: true, force: true });
|
|
mkdirSync(stage);
|
|
|
|
for (const f of ["dist", "icon.png", "README.md", ".mcpbignore"]) {
|
|
cpSync(path.join(here, f), path.join(stage, f), { recursive: true });
|
|
}
|
|
writeFileSync(
|
|
path.join(stage, "manifest.json"),
|
|
JSON.stringify(manifest, null, 2),
|
|
);
|
|
writeFileSync(path.join(stage, "package.json"), JSON.stringify(pkg, null, 2));
|
|
|
|
const run = (cmd) => execSync(cmd, { cwd: stage, stdio: "inherit" });
|
|
run(
|
|
"npm install --omit=dev --omit=optional --no-audit --no-fund --no-package-lock " +
|
|
"--registry=https://registry.npmjs.org/",
|
|
);
|
|
run(`npx -y @anthropic-ai/mcpb pack . ${JSON.stringify(out)}`);
|
|
|
|
rmSync(stage, { recursive: true, force: true });
|
|
console.log(`\n✅ ${path.relative(process.cwd(), out)}`);
|