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.
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 checkmanifest.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
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.0The 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.