Skip to content

Commit 860d12d

Browse files
anvansterclaude
andauthored
fix(release): correct npm package metadata and gate publishing on engine assets (#18)
* fix(release): correct npm metadata and gate publishing on engine assets npm rewrote four `bin` paths and `repository.url` on every publish and reported the bin entries as "invalid and removed". The entries in fact survived - 0.19.0 and 0.19.1 both carry all of theirs on the registry - but the warning was indistinguishable from a real failure and cost a publish that was aborted on the assumption it had broken something. Store the forms npm normalizes to, so a clean publish is silent and any future warning means something. package-npm.sh treated a package.json/server.json version mismatch as a warning, printed into the middle of npm pack output where it scrolls past. The two files are published to two different registries under one version, and republishing that version cannot correct a disagreement between them, so this now aborts instead. The package ships no engine: every install fetches one from the release tagged with the engine's version. Publishing ahead of those assets makes a package that installs cleanly and then has nothing to run, so the assets are probed before packing rather than trusted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rVbt7rENTwXkdHt3Bpgb5 * no-mistakes(review): harden npm packaging version and engine-asset gates * no-mistakes(document): clarify package-npm.sh engine-asset gate in header comment --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 284c8e5 commit 860d12d

2 files changed

Lines changed: 86 additions & 11 deletions

File tree

mcp-package/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"license": "Apache-2.0",
88
"repository": {
99
"type": "git",
10-
"url": "https://github.com/codegraph-ai/CodeGraph"
10+
"url": "git+https://github.com/codegraph-ai/CodeGraph.git"
1111
},
1212
"keywords": [
1313
"mcp",
@@ -20,10 +20,10 @@
2020
"copilot"
2121
],
2222
"bin": {
23-
"codegraph-mcp": "./bin/codegraph-mcp.js",
24-
"codegraph-daemon": "./bin/codegraph-daemon.js",
25-
"codegraph-mcp-install-hooks": "./bin/install-hooks.js",
26-
"codegraph-mcp-fetch-engine": "./bin/fetch-engine-cli.js"
23+
"codegraph-mcp": "bin/codegraph-mcp.js",
24+
"codegraph-daemon": "bin/codegraph-daemon.js",
25+
"codegraph-mcp-install-hooks": "bin/install-hooks.js",
26+
"codegraph-mcp-fetch-engine": "bin/fetch-engine-cli.js"
2727
},
2828
"files": [
2929
"bin/",

scripts/package-npm.sh

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
# Package the npm MCP server distribution.
66
# Run from the repo root after all platform binaries are built.
77
#
8-
# Usage:
98
# The engine is not bundled: it is fetched from the GitHub release at install
109
# time by bin/postinstall.js. Publish the release assets first with
11-
# ./scripts/publish-release-assets.sh, or installs of this version will fail to
12-
# find an engine.
10+
# ./scripts/publish-release-assets.sh - this script refuses to pack until every
11+
# asset for the pinned engine version is on the release, because an install
12+
# without them succeeds and then has nothing to run.
1313
#
1414
# Usage:
1515
# ./scripts/package-npm.sh # pack only
@@ -54,15 +54,90 @@ fi
5454
echo " ✓ package tests pass"
5555

5656
# Step 3: Verify version consistency
57+
#
58+
# server.json carries the release version twice: once at the top level, and once
59+
# inside the npm entry of `packages`, which is the field the MCP Registry
60+
# resolves the tarball from. Nothing synchronises the three numbers - they are
61+
# hand-edited - so all of them are compared, not just the top-level one. A
62+
# release that bumped package.json and server.json but missed the nested version
63+
# would register a new server entry pointing at the previous tarball, and the
64+
# Registry would accept it because that older tarball exists and carries the
65+
# right mcpName.
5766
PKG_VERSION=$(node -e "console.log(require('$PKG_DIR/package.json').version)")
5867
SERVER_VERSION=$(node -e "console.log(require('$PKG_DIR/server.json').version)")
68+
SERVER_NPM_VERSION=$(node -e "
69+
const npm = (require('$PKG_DIR/server.json').packages || [])
70+
.find((p) => p.registryType === 'npm');
71+
console.log(npm ? npm.version : '<no npm package entry>');
72+
")
5973
echo ""
60-
echo "package.json version: $PKG_VERSION"
61-
echo "server.json version: $SERVER_VERSION"
74+
echo "package.json version: $PKG_VERSION"
75+
echo "server.json version: $SERVER_VERSION"
76+
echo "server.json npm package: $SERVER_NPM_VERSION"
6277

78+
# A mismatch here is fatal rather than a warning. The two files are published to
79+
# two different registries under one version, and a warning scrolls past in the
80+
# npm pack output - leaving npmjs.com and the MCP Registry disagreeing about what
81+
# this release is, which cannot be corrected by republishing the same version.
6382
if [ "$PKG_VERSION" != "$SERVER_VERSION" ]; then
64-
echo "WARNING: version mismatch between package.json and server.json"
83+
echo "ERROR: version mismatch between package.json ($PKG_VERSION) and server.json ($SERVER_VERSION)" >&2
84+
exit 1
85+
fi
86+
if [ "$PKG_VERSION" != "$SERVER_NPM_VERSION" ]; then
87+
echo "ERROR: version mismatch between package.json ($PKG_VERSION) and the npm entry in server.json ($SERVER_NPM_VERSION)" >&2
88+
echo " The MCP Registry resolves the tarball from packages[].version, so this would" >&2
89+
echo " publish a $PKG_VERSION server entry pointing at the $SERVER_NPM_VERSION tarball." >&2
90+
exit 1
91+
fi
92+
93+
# The npm package contains no engine; every install fetches one from the release
94+
# tagged with the engine version pinned in bin/fetch-engine.js, which is
95+
# deliberately not this package's version (see the ENGINE_VERSION comment there:
96+
# a client-only patch release must not start asking for a tag nobody published).
97+
# Publishing before those assets exist produces a package that installs cleanly
98+
# and then has nothing to run.
99+
#
100+
# Every asset is probed, not just one. publish-release-assets.sh uploads the
101+
# whole staging directory in a single `gh release upload`, so a network drop or
102+
# a rate limit part-way through leaves the release with some platforms attached
103+
# and others missing - and a one-platform probe would wave that through, giving
104+
# users on the missing platforms exactly the empty install this gate exists to
105+
# prevent. The list mirrors BINARIES + WINDOWS_SIDECAR there, which is the same
106+
# set bin/fetch-engine.js resolves against.
107+
ENGINE_VERSION=$(node -e "console.log(require('$PKG_DIR/bin/fetch-engine').ENGINE_VERSION)")
108+
ENGINE_ASSETS=(
109+
"codegraph-server-darwin-arm64"
110+
"codegraph-server-darwin-x64"
111+
"codegraph-server-linux-x64"
112+
"codegraph-server-win32-x64.exe"
113+
"onnxruntime.dll"
114+
)
115+
RELEASE_BASE="https://github.com/codegraph-ai/CodeGraph/releases/download/v${ENGINE_VERSION}"
116+
117+
echo ""
118+
echo "engine version: $ENGINE_VERSION (fetched at install time)"
119+
echo "Checking published engine assets for v${ENGINE_VERSION}..."
120+
missing_assets=0
121+
for asset in "${ENGINE_ASSETS[@]}"; do
122+
# A binary and its checksum are separate assets and the client needs both, so
123+
# both are probed. The binaries are requested one byte at a time - presence is
124+
# the question here, and downloading ~120 MB to answer it is not worth it.
125+
if ! curl -fsSL -o /dev/null -r 0-0 "$RELEASE_BASE/$asset" \
126+
|| ! curl -fsSL -o /dev/null "$RELEASE_BASE/$asset.sha256"; then
127+
printf ' ✗ %s\n' "$asset"
128+
missing_assets=1
129+
else
130+
printf ' ✓ %s\n' "$asset"
131+
fi
132+
done
133+
134+
if [ "$missing_assets" -ne 0 ]; then
135+
echo "ERROR: the release v${ENGINE_VERSION} is missing engine assets (binary or .sha256)." >&2
136+
echo " Run ./scripts/publish-release-assets.sh --publish first, or installs on those" >&2
137+
echo " platforms will find no engine." >&2
138+
exit 1
65139
fi
140+
echo " ✓ every engine asset is published for v${ENGINE_VERSION}"
66141

67142
# Step 4: Pack
68143
echo ""

0 commit comments

Comments
 (0)