Skip to content

Latest commit

 

History

History

mcpb

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

MCP Bundle (Claude Desktop extension)

Everything needed to package this server as an MCP Bundle (.mcpb) for Claude Desktop lives in this folder, so the project root stays a plain Python project. The one exception is .mcpbignore, which sits at the project root where the MCPB CLI looks for it (like .gitignore).

File Purpose
manifest.json The MCPB manifest. It uses the uv runtime: Claude Desktop runs uv run --directory <install dir> --frozen --no-dev src/stdio.py and installs the locked dependencies itself, so nothing is vendored.
build.py Builds dist/serpapi-mcp-<version>.mcpb: rebuilds the engine schemas, lays out the bundle, packs it with the MCPB CLI, verifies the archive and smoke-tests it over stdio.
../.mcpbignore Trims the git-tracked files down to what the server needs at runtime; tests, CI, deployment files and this folder stay out.

The stdio entry point is src/stdio.py; it belongs to the server (any local MCP host can launch it), not to the packaging. The manifest tests live in tests/test_mcpb.py.

Build

Run from the project root. Node.js is needed for the MCPB CLI (via npx), and the default build needs network access to regenerate the engine schemas.

uv run mcpb/build.py                       # dist/serpapi-mcp-<version>.mcpb
uv run mcpb/build.py --no-rebuild-engines  # bundle engines/ from the working tree
uv run mcpb/build.py --no-smoke            # skip the install-and-start check

Bundle layout

manifest.json has to sit at the root of the packed directory, so the build copies it there next to the git-tracked files (.mcpbignore is already at the project root, so it is staged like any other tracked file):

serpapi-mcp-<version>.mcpb
├── manifest.json        <- mcpb/manifest.json
├── pyproject.toml, uv.lock, .python-version, LICENSE, README.md
├── src/                 <- git-tracked files minus .mcpbignore (git add anything new that must ship)
└── engines/             <- regenerated from the SerpApi Playground at build time

Releasing

From the repository root, run the version helper to update pyproject.toml, server.json, mcpb/manifest.json and uv.lock together. It accepts stable X.Y.Z versions. Review and commit the changes, then push a matching tag:

uv run --no-sync scripts/bump_version.py 2.0.0
# Review and commit the changes before tagging.
git tag v2.0.0 && git push origin v2.0.0

The release workflow runs the test suite, then builds the bundle, creates the GitHub release if it does not exist yet and attaches the .mcpb to it; the same workflow also deploys the hosted server and publishes server.json to the MCP Registry, so a tag is the only thing that ships or builds anything. Pull requests only run the manifest and stdio entry point tests in tests/test_mcpb.py; build locally with uv run mcpb/build.py to check a bundle before tagging.