MCP Factory
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
> *The test count is verifiable below (python -m pytest tests/ → **348 passed, 8 skipped**) and enforced in CI by scripts/check_readme_counts.py, which fails the build if this README's counts drift from the live suite.*
60-Second Quickstart
**From PyPI (registry users):**
**From a git checkout (contributors):** see the python hub_server.py ... examples throughout this README — hub_server.py at the repo root is a backward-compat wrapper around the same mcp_factory.cli module the console script runs, so behavior is identical either way.
**The manifest-driven engine behind the MCP Integration Sprint.** Write one mcp.yaml for a bot repo and the factory generates the server stub and the ~/.claude.json entry; run the hub and it serves every bot's tools through a single MCP endpoint.
The SDK wrapper is the easy part. What makes an MCP server safe to put in front of a real internal tool — **scoped auth/env, fail-soft error handling, validated manifests, a collision-safe registry, and a real test suite** — is the engineering this engine is built around. That same production layer is hand-built per engagement; the factory scaffolds it, it doesn't fake it.
Browse before you reply
This repo is public **so you can verify the discipline instead of taking my word for it.** Every claim below maps to a file you can open:
| Claim | Where it lives | What to look for |
|---|---|---|
| **Validated, env-scoped manifests** | mcp_factory/manifest.py | strict from_dict validation (raises on missing/invalid fields); the env_required / env model that scopes which secrets a server may see |
| **Fail-soft subprocess proxying** | mcp_factory/runtime/subprocess_adapter.py | typed SubprocessError, lazy start, JSON-RPC error surfacing, timeout/OSError-guarded teardown + atexit cleanup — a dead bot returns a clean error, it doesn't crash the hub |
| **Collision-safe, manifest-driven registry** | mcp_factory/runtime/registry.py · registry.json | CollisionError on duplicate . names; the registry is built from manifests, not hand-maintained |
| **Tested on a clean checkout** | tests/ | **348 passed, 8 skipped, 0 failed** (Python 3.12); the 8 skips are real integration tests or lint checks that no-op when the thing they need is absent |
> **Honesty rails:** 348 is the real, reproducible count on a clean checkout — the same number the public CI run produces and gates on. mcp-factory generates the *scaffold* and runs the hub — it does not "generate the production server" or carry any client/CI claims. The hardened production layer (per-tool auth boundaries, the full failure set, two-axis version-pinning) is built per engagement on top of this engine. That applies to both Python scaffold styles below — see "Two Python styles" for exactly what the fastmcp variant does and doesn't add on top of that baseline.
Quick Start
Factory mode (generate config from one manifest)
Output always goes to ~/.claude.json.factory-test by default — **never** to the live ~/.claude.json. Copy entries manually after review.
Scan mode (batch-register all bots)
--scan discovers all projects/*/mcp.yaml files, validates each, and diffs them against the current ~/.claude.json. Default root is C:\path\to\projects. With --apply, a timestamped backup is created at ~/.claude.json.scan-backup- before writing.
**Skip logic:** manifests whose name already exists in ~/.claude.json are skipped unless --force is passed. This prevents accidentally overwriting manually-crafted entries.
Serve mode (runtime hub — single MCP for all bots)
The hub scans all mcp.yaml manifests under each --scan-root at startup, then exposes every bot's tools under the . namespace (e.g., fleet-health.fleet_status, my-bot.run_scan). Tools are proxied to per-bot subprocess MCP servers with lazy startup.
**Hub meta-tool:** _hub.list_bots returns the registered bots and their subprocess status.
Hub is pre-registered in ~/.claude.json as mcp-factory-hub (see scripts/register_hub.py).
Node.js template