@neopress/mcp 1.1.3 → 1.2.0
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.
- package/dist/bin.cjs +44868 -54875
- package/dist/http-bin.cjs +46512 -56800
- package/dist/index.d.ts +883 -52
- package/dist/index.js +25930 -56832
- package/integrations/claude-desktop/manifest.json +1 -1
- package/package.json +8 -5
- package/scripts/check-dist-contract.mjs +91 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neopress/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Neopress MCP server for first-party AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"scripts",
|
|
22
22
|
"README.md"
|
|
23
23
|
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=24"
|
|
26
|
+
},
|
|
24
27
|
"publishConfig": {
|
|
25
28
|
"access": "public"
|
|
26
29
|
},
|
|
@@ -29,14 +32,14 @@
|
|
|
29
32
|
"zod": "^4.1.12"
|
|
30
33
|
},
|
|
31
34
|
"devDependencies": {
|
|
32
|
-
"@types/node": "^
|
|
33
|
-
"
|
|
34
|
-
"typescript": "
|
|
35
|
+
"@types/node": "^24",
|
|
36
|
+
"tsdown": "^0.22.14",
|
|
37
|
+
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
35
38
|
"vitest": "^4.1.5",
|
|
36
39
|
"@neopress/sdk": "0.4.0"
|
|
37
40
|
},
|
|
38
41
|
"scripts": {
|
|
39
|
-
"build": "
|
|
42
|
+
"build": "tsdown && node ./scripts/check-dist-contract.mjs",
|
|
40
43
|
"mcpb:stage": "node ./scripts/prepare-mcpb-package.mjs",
|
|
41
44
|
"start:http": "node ./dist/http-bin.cjs",
|
|
42
45
|
"lint": "tsc --noEmit",
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Build-path gate for the published artifact. See packages/cli/scripts/check-dist-contract.mjs
|
|
3
|
+
// for the rationale; the file-set invariant matters more here because
|
|
4
|
+
// prepare-mcpb-package.mjs copies dist/bin.cjs alone into the Claude Desktop bundle,
|
|
5
|
+
// so a shared chunk would produce an extension that breaks at runtime.
|
|
6
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
|
|
9
|
+
const packageRoot = path.resolve(import.meta.dirname, '..');
|
|
10
|
+
const distDir = path.join(packageRoot, 'dist');
|
|
11
|
+
const packageJson = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
12
|
+
|
|
13
|
+
const expectedFiles = ['bin.cjs', 'http-bin.cjs', 'index.d.ts', 'index.js'];
|
|
14
|
+
const allowedBareImports = new Set(Object.keys(packageJson.dependencies ?? {}));
|
|
15
|
+
// See the cli script: tsdown inlines a leaked third-party type instead of leaving a
|
|
16
|
+
// dangling import, turning a loud failure into silent bloat. Current output is ~26KB.
|
|
17
|
+
const maxDeclarationBytes = 120_000;
|
|
18
|
+
|
|
19
|
+
const errors = [];
|
|
20
|
+
|
|
21
|
+
const actualFiles = readdirSync(distDir).sort();
|
|
22
|
+
const unexpected = actualFiles.filter((f) => !expectedFiles.includes(f));
|
|
23
|
+
const missing = expectedFiles.filter((f) => !actualFiles.includes(f));
|
|
24
|
+
if (unexpected.length > 0) {
|
|
25
|
+
errors.push(
|
|
26
|
+
`dist has unexpected files: ${unexpected.join(', ')}\n` +
|
|
27
|
+
` Likely code splitting — give each entry its own config object in tsdown.config.ts.\n` +
|
|
28
|
+
` dist/bin.cjs must stay self-contained: prepare-mcpb-package.mjs ships it alone.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (missing.length > 0) {
|
|
32
|
+
errors.push(`dist is missing: ${missing.join(', ')}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Every emitted bundle must have the workspace packages inlined. tsdown reports an
|
|
36
|
+
// unresolved import (a missing packages/sdk/dist, say) as a *warning* and still exits 0,
|
|
37
|
+
// which would publish a binary carrying a bare require("@neopress/sdk") that no consumer
|
|
38
|
+
// can resolve. Checking the .d.ts alone does not see this.
|
|
39
|
+
for (const file of actualFiles.filter((f) => /\.(cjs|js|mjs)$/.test(f))) {
|
|
40
|
+
const bundle = readFileSync(path.join(distDir, file), 'utf8');
|
|
41
|
+
const leaked = [
|
|
42
|
+
...new Set(
|
|
43
|
+
[...bundle.matchAll(/(?:require\(|from\s*)["'](@neopress\/[^"']+)["']/g)].map((m) => m[1])
|
|
44
|
+
),
|
|
45
|
+
];
|
|
46
|
+
if (leaked.length > 0) {
|
|
47
|
+
errors.push(
|
|
48
|
+
`dist/${file} still imports workspace packages at runtime: ${leaked.join(', ')}\n` +
|
|
49
|
+
` They must be bundled. A missing dependency build leaves these unresolved and\n` +
|
|
50
|
+
` tsdown only warns — build the workspace deps first (turbo handles this via ^build).`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const declarations = actualFiles.includes('index.d.ts')
|
|
56
|
+
? readFileSync(path.join(distDir, 'index.d.ts'), 'utf8')
|
|
57
|
+
: '';
|
|
58
|
+
if (declarations.length > maxDeclarationBytes) {
|
|
59
|
+
errors.push(
|
|
60
|
+
`dist/index.d.ts is ${Math.round(declarations.length / 1000)}KB, over the ${Math.round(maxDeclarationBytes / 1000)}KB ceiling\n` +
|
|
61
|
+
` A third-party type tree was probably inlined. Narrow the public surface\n` +
|
|
62
|
+
` (@internal + stripInternal) rather than raising this number.`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const specifiers = [
|
|
66
|
+
...[...declarations.matchAll(/\bfrom\s*["']([^"']+)["']/g)].map((m) => m[1]),
|
|
67
|
+
// `typeof import("x")` is what TS emits when a type leaks through an inferred
|
|
68
|
+
// signature — the `from` form above never matches it.
|
|
69
|
+
...[...declarations.matchAll(/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g)].map((m) => m[1]),
|
|
70
|
+
];
|
|
71
|
+
const unresolvable = [...new Set(specifiers)].filter((specifier) => {
|
|
72
|
+
if (specifier.startsWith('node:')) return false;
|
|
73
|
+
const packageName = specifier.startsWith('@')
|
|
74
|
+
? specifier.split('/').slice(0, 2).join('/')
|
|
75
|
+
: specifier.split('/')[0];
|
|
76
|
+
return !allowedBareImports.has(packageName);
|
|
77
|
+
});
|
|
78
|
+
if (unresolvable.length > 0) {
|
|
79
|
+
errors.push(
|
|
80
|
+
`dist/index.d.ts imports that consumers cannot resolve: ${unresolvable.join(', ')}\n` +
|
|
81
|
+
` Allowed: node: builtins and this package's own dependencies.\n` +
|
|
82
|
+
` Relative imports mean a type was not inlined; bare ones mean an undeclared dependency leaked.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (errors.length > 0) {
|
|
87
|
+
console.error(`[check-dist-contract] ${packageJson.name} failed:\n\n${errors.join('\n\n')}\n`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log(`[check-dist-contract] ${packageJson.name} ok — ${actualFiles.length} files, no unresolvable type imports`);
|