Skip to content

feat: rebuild mcpb packaging as a self-contained bundle, publish on release - #3099

Open
enesgules wants to merge 4 commits into
masterfrom
feat/mcpb-bundle
Open

feat: rebuild mcpb packaging as a self-contained bundle, publish on release#3099
enesgules wants to merge 4 commits into
masterfrom
feat/mcpb-bundle

Conversation

@enesgules

Copy link
Copy Markdown
Collaborator

Follow-up to #3097.

Problem

The context7.mcpb bundle has been broken since 2.0.2:

  • The pack script relied on pnpm install --prod producing a bundleable node_modules, but pnpm uses symlinks, so no dependencies ever made it into the archive — the packed server could not start.
  • No CI built or uploaded the bundle; the manifest was stuck at 2.1.0 with wrong tool names (Resolve Context7 Library ID instead of resolve-library-id) and no way for users to configure an API key.
  • A stale built binary was committed to the repo.

Changes

  • Self-contained bundle: esbuild bundles the server into one index.mjs (960 KB packed, 3 runtime files) — no node_modules, no .mcpbignore, no install/reinstall dance. package.json ships in the archive root so the runtime SERVER_VERSION read resolves.
  • Manifest: real tool names, current version (CI injects it each release), user_config.api_key (sensitive, optional) wired to CONTEXT7_API_KEY.
  • CI: new publish-mcpb job builds the bundle, smoke-tests the packed artifact (extract + MCP initialize over stdio), and uploads it to the GitHub release whenever @upstash/context7-mcp is published. The registry publish job now waits for it and attaches the mcpb package to server.json with its download URL + sha256 (skips with a warning if the asset is missing, e.g. manual dispatch for an old version).
  • Untracked the built .mcpb binary; *.mcpb is gitignored.

Testing

  • mcpb validate passes; packed bundle extracted outside the repo answers initialize and tools/list with both tools over stdio.

https://claude.ai/code/session_013RG7wpXqUKZYsRzv7zyv6L

…elease

- Bundle the server with esbuild into a single self-contained file; the old
  pack relied on pnpm's symlinked node_modules, which never made it into the
  archive, so bundles since 2.0.2 were broken/stale
- Ship package.json in the archive so the runtime version read resolves
- Fix manifest: real tool names (resolve-library-id, query-docs), current
  version, and user_config so Desktop users can enter CONTEXT7_API_KEY
- Build, smoke-test, and upload context7.mcpb to the GitHub release on every
  @upstash/context7-mcp publish; registry publish then attaches it to
  server.json with its sha256
- Stop tracking the built .mcpb binary

Claude-Session: https://claude.ai/code/session_013RG7wpXqUKZYsRzv7zyv6L
Without a default, hosts leave the literal ${user_config.api_key}
placeholder in CONTEXT7_API_KEY when the user provides no key
(mcpb replaceVariables only substitutes known variables), and the
server would send that garbage value as its API key. An empty-string
default resolves to an empty env var, which the server treats as
no key.

Claude-Session: https://claude.ai/code/session_013RG7wpXqUKZYsRzv7zyv6L
The MCP Registry validates mcpb URLs against the pattern
/owner/repo/releases/download/tag/filename where the tag cannot
contain '/'. Changesets tags (@upstash/context7-mcp@x.y.z) do, and
Go's url.Parse decodes %2F back to '/', so encoding cannot help.
The bundle now ships on a dedicated mcpb-vX.Y.Z release.

Claude-Session: https://claude.ai/code/session_013RG7wpXqUKZYsRzv7zyv6L
Registry versions are immutable; a manual re-run for an already
published version should not retry three times and fail red.

Claude-Session: https://claude.ai/code/session_013RG7wpXqUKZYsRzv7zyv6L
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant