Build, package, install, and validate MCP servers (Matrix Hub–compatible).
Project description
🔧 mcp-builder
Build, package, install, and validate MCP servers locally — with Matrix Hub–compatible bundles and install plans.
✨ What is it?
mcp-builder turns a source repo (Python/Node today) into a verifiable bundle:
- Detects language + transport (SSE / STDIO)
- Scaffolds
runner.json+mcp.server.json - Packages to a normalized zip + SHA-256
- Emits a Matrix Hub–compatible install plan
- Installs locally to
~/.matrix/runners/<alias>/<version>/ - Probes startup (smoke test), with optional port/env overrides
It’s designed to scale: convention-over-configuration, typed validation, and CI-friendly.
🚀 Quickstart
Requires Python 3.11+. For Node servers, install Node 18+.
# 0) Install the CLI
pip install mcp-builder
# 1) Detect
mcp-builder detect ./fixtures/hello-python-sse
# 2) Scaffold metadata (if missing)
mcp-builder init ./fixtures/hello-python-sse --transport sse --name hello --version 0.1.0
# 3) Build metadata (zip creation handled by pipeline/package step)
mcp-builder build ./fixtures/hello-python-sse --out ./dist
# 4) Package to zip (+sha256) using the packaging API in your pipeline
# ... dist/bundle.zip and dist/bundle.zip.sha256
# 5) Emit an install plan for Matrix Hub
mcp-builder plan ./dist/bundle.zip --name hello --transport SSE --out ./dist/hello.plan.json
# 6) Install locally (with a smoke probe)
mcp-builder install ./dist/bundle.zip --as hello-sse --port 8023 --env LOG_LEVEL=debug
# 7) Run on demand
mcp-builder run ~/.matrix/runners/hello-sse/0.1.0 --port 8023
Handy flags
--port N— setsPORTduring probe/run (SSE)--env KEY=VAL— repeatable env for probe/run--no-probe— skip the post-install smoke test--prefer docker|zip|git— future multi-surface preference
🧰 CLI overview
| Command | What it does |
|---|---|
detect |
Detects language/transport/entry; prints JSON |
init |
Scaffolds runner.json + mcp.server.json |
build |
Produces metadata & file list for packaging |
plan |
Emits a Matrix Hub–compatible install plan from a bundle |
install |
Installs a bundle/dir into ~/.matrix/runners/<alias>/<version>/ |
run |
Smoke-runs a bundle/dir; supports --port and --env KEY=VAL |
verify |
Verifies a bundle against a SHA-256 (sha256:<hex> or raw hex) |
🧪 Tests & examples
- Fixtures:
fixtures/hello-python-sse/— a minimal SSE server - Unit tests: detectors, validator, zip safety
- Integration tests: build → plan shape → install zip
Run everything:
make venv
. .venv/bin/activate
make test # lint + unit + integration
make docs-serve # local docs at http://127.0.0.1:8001
🧱 Architecture (P0–P3)
- Detect:
mcp_builder/detect/*→DetectReport(lang, transport, entrypoints, …) - Buildpacks:
buildpacks/python.py,buildpacks/node.py→ runner + manifest + files - Package:
package/zip.py→bundle.zip+.sha256 - Validate:
schema/*.json,validator.py(permissive, tightened later) - Plan:
planner.py→install planJSON - Install:
installer/install.py(zip/dir), safe extraction, lock metadata - Run/Probe:
conformance/runner.py(smoke),conformance/testspec.py(basic tests) - Integrity:
signing/checks.py(sha256 now; cosign later)
🧭 When to use MCP (and when not to)
Best fits: exposing executable capabilities (tools) to AI apps — DB queries, filesystem ops, API calls, workflows. Also fits: read-only resources (files/URLs/DB rows) & reusable prompts/templates. Use MCP when: you need standardized integration, security/permissioning, model-agnostic interop, and observability across clients. Don’t use MCP when: a simple HTTP API/Webhook suffices and model-facing semantics aren’t needed.
🧑🎨 Designing great MCP servers
Core principles
- Single responsibility (one auth domain, cohesive feature set)
- Statelessness (replayable; horizontally scalable)
- Explicit contracts (strict JSON Schemas, min/max/enum/pattern)
- Least privilege (read-only default, granular permissions)
- Idempotency & safety (confirm destructive ops)
- Observability first (structured logs, metrics, traces, request IDs)
- Failure-tolerant (timeouts, retries, circuit breakers, cancellation)
Transports
- STDIO: simplest for local dev/trusted envs
- HTTP (SSE): default for browsers/remote clients; supports streaming & CORS
- WebSocket: bidirectional, if you control both ends
Security checklist
- Read-only default; explicit write gates
- FS/egress allowlists; sanitize URIs
- AuthN/AuthZ (scopes, rotation), secrets redaction
- Quotas & rate limits; audit logs
Observability & reliability
- Metrics: latency, error rate, concurrency, bytes in/out
- Logs: structured JSON with correlation/request IDs
- Tracing: spans across external calls
- Resilience: timeouts, backoff, health/liveness probes
🧪 Testing strategy
- Unit: schema validation, input validators, error mappers
- Integration: spin up server;
tools/list, resource reads, tool calls - Protocol: MCP flows (listing, calling, streaming, cancellation)
- Performance: load hot paths; watch tail latencies
- Model-compat: exercise across multiple model clients
🧯 Troubleshooting
-
Editable install fails with
TypeError: Field project.dependencies must be an array→ Inpyproject.toml,project.dependenciesmust be an array of strings, not a TOML table. -
Zip extraction blocked → The installer protects against zip-slip, absolute paths, and huge members. Rebuild your bundle with normalized relative paths only.
-
Probe timeout → Increase
--timeout, set a deterministic--port, or run with--no-probein CI and test separately.
🛣️ Roadmap
- P4: Docker surface (
docker-image-ref.txtthen actual buildx flow) - P4: Schema tightening (
additionalProperties: falsewhere safe) - P5: Node SSE detection & build; Go/Rust buildpacks
- Supply chain: SBOM, SLSA provenance, cosign signatures
- Conformance: full handshake + tool call contract tests
- Multi-surface plans: zip / PyPI / npm / Docker / client configs
🧪 Industrialized blueprint (for many servers & surfaces)
Guiding principles
- Convention over config
- One source → many surfaces (zip, PyPI/npm, Docker, OS packages, client configs)
- Reproducible & verifiable (pinned toolchains, SBOM, provenance, signatures)
- Gated releases (conformance/security/perf)
Canonical mcp.server.json (embed in every bundle)
{
"schemaVersion": "1.0",
"name": "hello-mcp",
"version": "0.2.0",
"transports": [
{"type": "stdio", "command": ["python","-m","hello_mcp.server_stdio"]},
{"type": "sse", "url": "http://127.0.0.1:8000/messages/", "health": "/healthz"}
],
"tools": ["hello"],
"limits": {"maxInputKB":128,"maxOutputKB":256,"timeoutMs":15000},
"security": {
"readOnlyDefault": true,
"fsAllowlist": ["${PROJECT_ROOT}/data/**"],
"egressAllowlist": ["api.github.com:443"]
},
"build": {"lang":"python","runner":"uv","lockfiles":["uv.lock"]},
"digest": {"algo":"sha256","value":"<filled by CI>"}
}
Multi-surface outputs from one build
- Zip (+
mcp.server.json,runner.json, SHA-256, signature, SBOM, provenance) - PyPI/npm (console-script/bin →
uvx/npxinstalls) - Docker (SSE preferred, non-root, healthcheck)
- Client configs (VS Code / Claude Desktop snippets)
- OS packages (brew/scoop/winget) – optional
Conformance & security gates (practical minimum)
- Protocol: list/call/cancel/stream
- Schemas: strict JSON Schema validation
- Security: read-only default + allowlists
- Perf smoke: concurrent calls within p95 budgets
- Logging: JSON logs include tool, durationMs, status, requestId
🛠 Development
# Create a local environment and install dev/docs extras
make venv
. .venv/bin/activate
# Quality gates & tests
make lint
make fmt
make unit
make integration
make test
# Docs
make docs-serve # live
make docs-build # static site in ./site
# Package for PyPI
make build
📜 License
Licensed under the Apache 2.0 License — see LICENSE.
🙋 FAQ
Is this only for Python? No. Python is first-class today; Node stdio is included; more languages (Go/Rust) are planned via buildpacks.
Is it safe to install arbitrary zips? We verify SHA-256, block zip-slip/absolute paths, and will add signatures (cosign) + provenance in upcoming releases.
How do I make my server “Matrix Hub ready”?
Include runner.json + canonical mcp.server.json, keep tools’ schemas strict, and ensure read-only defaults + allowlists. Use mcp-builder plan to emit an install plan with digests.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_builder-0.1.0.tar.gz.
File metadata
- Download URL: mcp_builder-0.1.0.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19995a94a996f54f31a9d930655b64eeaa3cc7c277ab26430c4c73b96b39fc66
|
|
| MD5 |
e800b7d66258ddeb799bec63d3413953
|
|
| BLAKE2b-256 |
01628430b7fe89fbcc799c2981e3995e44ae8aac3bfd10b1c6bc9dd09b8535c4
|
Provenance
The following attestation bundles were made for mcp_builder-0.1.0.tar.gz:
Publisher:
release.yml on ruslanmv/mcp-builder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_builder-0.1.0.tar.gz -
Subject digest:
19995a94a996f54f31a9d930655b64eeaa3cc7c277ab26430c4c73b96b39fc66 - Sigstore transparency entry: 400075249
- Sigstore integration time:
-
Permalink:
ruslanmv/mcp-builder@db31e15dbb2ec6f6c8cee14b08a2209960ca4264 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ruslanmv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@db31e15dbb2ec6f6c8cee14b08a2209960ca4264 -
Trigger Event:
release
-
Statement type:
File details
Details for the file mcp_builder-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_builder-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77072d03433f8fca3b3cd4f49c6dd95cb2c94775a2b3dcb7d59c4c86e6e6a608
|
|
| MD5 |
4fd0f08ef6f87a2fde355df853d2ea03
|
|
| BLAKE2b-256 |
df24d775629ea795d96f8e87d34a5defd762489e8a61b9f9378c84f76758cc34
|
Provenance
The following attestation bundles were made for mcp_builder-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ruslanmv/mcp-builder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_builder-0.1.0-py3-none-any.whl -
Subject digest:
77072d03433f8fca3b3cd4f49c6dd95cb2c94775a2b3dcb7d59c4c86e6e6a608 - Sigstore transparency entry: 400075292
- Sigstore integration time:
-
Permalink:
ruslanmv/mcp-builder@db31e15dbb2ec6f6c8cee14b08a2209960ca4264 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ruslanmv
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@db31e15dbb2ec6f6c8cee14b08a2209960ca4264 -
Trigger Event:
release
-
Statement type: