Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased — `pdfmux-mcp` (npm) no longer silently serves a stale pdfmux

### Fixed

- **The `npx -y pdfmux-mcp` wrapper accepted any already-importable `pdfmux`, even one below its own declared `PDFMUX_MIN_VERSION`.** Reported as "MCP server mode produces garbled Korean text while the CLI works correctly on the same PDF" (`NameetP/pdfmux#10`): the wrapper's `python3`/`python` can resolve to a different environment than the one backing the user's own `pdfmux` CLI binary, and the old check (`isPdfmuxInstalled`) only asked "does `import pdfmux` succeed," never "is it new enough." A stale install on that other environment runs silently instead of the version the wrapper advertises installing.
- **Fix:** `npm-wrapper/index.js`'s `getInstalledVersion()` + `versionAtLeast()` compare the resolved environment's actual `pdfmux.__version__` against `PDFMUX_MIN_VERSION` and reinstall/upgrade when it falls short, same as the already-correct "not installed at all" path.
- Not yet published to npm — `npm view pdfmux-mcp version` still serves `1.4.0` with this fix unreleased; publishing is a Tier-2 founder action, same gate as a PyPI release.

## Unreleased — table cells no longer depend on what pymupdf4llm did to PyMuPDF

### Fixed
Expand Down
37 changes: 31 additions & 6 deletions npm-wrapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,29 @@ function findPython() {
return null;
}

function isPdfmuxInstalled(python) {
function getInstalledVersion(python) {
try {
execSync(`${python} -c "import pdfmux; print(pdfmux.__version__)"`, {
return execSync(`${python} -c "import pdfmux; print(pdfmux.__version__)"`, {
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
});
return true;
}).trim();
} catch {
return false;
return null;
}
}

function versionAtLeast(version, minVersion) {
const parts = (v) => v.split(".").map((n) => parseInt(n, 10) || 0);
const a = parts(version);
const b = parts(minVersion);
for (let i = 0; i < Math.max(a.length, b.length); i++) {
const x = a[i] || 0;
const y = b[i] || 0;
if (x !== y) return x > y;
}
return true;
}

function installPdfmux(python) {
console.error("[pdfmux-mcp] Installing pdfmux...");
try {
Expand All @@ -66,7 +77,21 @@ function main() {
process.exit(1);
}

if (!isPdfmuxInstalled(python)) {
// Bug (reported as "pdfmux-mcp garbles Korean text, pdfmux CLI doesn't" —
// NameetP/pdfmux#10): this check used to only ask "is pdfmux importable at
// all," so a stale pdfmux already present on whatever `python3`/`python`
// this wrapper resolves to (which can be a different install than the
// user's own `pdfmux` CLI binary) was accepted silently, even below
// PDFMUX_MIN_VERSION. Two installs drifting apart is exactly the kind of
// silent inconsistency this product's extraction claims are supposed to
// rule out — it must not exist in its own install path.
const installedVersion = getInstalledVersion(python);
if (!installedVersion || !versionAtLeast(installedVersion, PDFMUX_MIN_VERSION)) {
if (installedVersion) {
console.error(
`[pdfmux-mcp] Installed pdfmux ${installedVersion} is older than the required ${PDFMUX_MIN_VERSION} — upgrading.`
);
}
if (!installPdfmux(python)) {
process.exit(1);
}
Expand Down
Loading