Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
Manifest-driven MCP server scaffolder and runtime hub for tool integrations.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요
{
"mcpServers": {
"factory": {
"command": "uvx",
"args": [
"jaimenbell-mcp-factory"
]
}
}
}터미널에서 이 명령어를 실행하세요
claude mcp add factory -- uvx jaimenbell-mcp-factory프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"factory": {
"command": "uvx",
"args": [
"jaimenbell-mcp-factory"
]
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"factory": {
"type": "stdio",
"command": "uvx",
"args": [
"jaimenbell-mcp-factory"
]
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 8일 점검
레지스트리 이름이 GitHub 계정 jaimenbell 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.1.3)은 3개월 전 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Python (uv)도 있어야 해요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, Thalovant MCP
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:↓ 주간 다운로드i★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Connect MCP clients to Thalovant control-plane and hub runtime APIs over stdio or Streamable HTTP.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
*The test count is verifiable below (
python -m pytest tests/→ 348 passed, 8 skipped) and enforced in CI byscripts/check_readme_counts.py, which fails the build if this README's counts drift from the live suite.*
From PyPI (registry users):
pip install jaimenbell-mcp-factory
mcp-factory-hub --serve
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.
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:
348is 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.
# Reference an existing MCP server (no code generated — just the config entry)
python hub_server.py --manifest examples/fleet_health.yaml
python hub_server.py --manifest my_bot/mcp.yaml --output-dir my_bot/
python hub_server.py --manifest my_bot/mcp.yaml --dry-run
python hub_server.py --manifest examples/fleet_health.yaml --verify ~/.claude.json
Output always goes to ~/.claude.json.factory-test by default — never to the live ~/.claude.json. Copy entries manually after review.
# Dry-run diff: show what would change in ~/.claude.json
python hub_server.py --scan C:\path\to\projects
python hub_server.py --scan C:\path\to\projects --apply
python hub_server.py --scan C:\path\to\projects --apply --force
--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.
# Run the hub as a live MCP server (stdio transport)
python hub_server.py --serve
python hub_server.py --serve \ --scan-root C:\path\to\projects \ --scan-root C:\path\to\Claude
python hub_server.py --register \ --scan-root C:\path\to\projects \ --scan-root C:\path\to\Claude
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).
Factory generates Node.js stubs when runtime.type: node is set in mcp.yaml:
runtime:
type: node command: "node" output: "path/to/server.js"
Generated stubs use @modelcontextprotocol/sdk with stdio transport and zod for argument validation. See examples/node_example.yaml for a working demo.
For runtime.type: python, the factory can scaffold either of two styles from the exact same manifest:
runtime:
type: python command: "python" style: raw # default — official mcp SDK, hand-rolled list_tools/call_tool
Both styles read the same tools: / env_required: fields and produce a server that speaks the same stdio JSON-RPC wire protocol — the runtime hub's SubprocessAdapter proxies either one without any adapter changes (see tests/test_fastmcp_template.py::TestFastmcpServeSmoke for a live generate-and-call test).
style: raw (python_server.py.j2) | style: fastmcp (python_fastmcp.j2) | |
|---|---|---|
| SDK | official mcp package, mcp.server.Server | fastmcp (pinned exact fastmcp==3.4.2 — 4.0.0b1 is a beta that breaks sampling/roots, do not float) |
| Tool registration | manual @server.list_tools() / @server.call_tool() dispatch | one @mcp.tool(...)-decorated function per tool |
| Arg schema | hand-built JSON Schema dict per arg | Annotated[type, Field(description=...)] on real Python parameters — FastMCP derives the JSON Schema, including required/optional, from the signature |
| Tool body | # TODO: implement stub | same stub, wrapped in try/except Exception — a runtime error in a filled-in implementation returns a structured {"status": "error", ...} instead of crashing the process |
env_required | not enforced at scaffold level | rendered into a _check_required_env() startup check that warns to stderr if a declared var is missing — a presence check, not credential validation |
Gaps, stated honestly: neither style implements per-tool authorization, rate limiting, or the "full failure set" the hub-level subprocess_adapter.py gives you for free (typed errors, lazy start, atexit cleanup) — that's still a per-engagement build on top of either scaffold. The fastmcp template's fail-soft wrapper and env-presence check are new, real code (read mcp_factory/templates/python_fastmcp.j2), not a marketing claim about auth — they were added because FastMCP's decorator model made them cheap to include cleanly; they have not (yet) been backported to the raw template, which is why the two styles differ slightly in what ships out of the box. If your engagement needs FastMCP-specific features beyond this (resources, prompts, HTTP/SSE transport, middleware-based auth), the generated file is a normal FastMCP app — extend it directly.
See examples/fastmcp_example.yaml for a working demo manifest.
name: my-bot # REQUIRED — unique MCP server name (key in claude.json)
description: > # REQUIRED — shown in Claude's tool descriptions What this bot does and when to use it.
runtime: # REQUIRED type: python # python | node | binary command: "C:\\Python314\\python.exe" # full path to interpreter script: "path/to/server.py" # existing server (skips scaffold generation) output: "path/to/out.py" # where to write generated scaffold (omit = auto) style: raw # python only: raw (default) | fastmcp — see "Two Python styles"
tools: # REQUIRED — list of MCP tools to expose
env_required: # env var names that must be set at runtime
env: # static env vars injected into claude.json entry MY_API_KEY: "" # leave value empty — fill in ~/.claude.json manually
tags: [trading, health] # for documentation / future routing priority: high # high | medium | low
runtime.script + existing file → factory references it, skips scaffoldruntime.script + missing file → validation error (use runtime.output for new scaffolds)runtime.output → explicit path for generated stub (absolute recommended)script nor output → error at config-write steptitle and annotationsBoth are optional and both are worth declaring.
title is the human display name, which lets name stay a programmatic identifier. Display precedence is title → annotations.title → name; the factory exposes only the top-level title so one manifest cannot declare two competing display names.
annotations matters more than it looks. The four hints have pessimistic defaults — destructiveHint and openWorldHint both default to true, readOnlyHint to false —
앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요