feat: add standards wiki, MCP registry, and app template
This commit is contained in:
103
tools/build_standards.py
Normal file
103
tools/build_standards.py
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python
|
||||
"""Build the hand-authored "standards" MCP bundle from the wiki markdown.
|
||||
|
||||
This converter reads `standards_src/wiki/*.md` and writes the MCP bundle shape
|
||||
that doc-forge's `MCPRenderer` emits, so the shared `MCPServer` can serve it:
|
||||
|
||||
mcp/standards/index.json
|
||||
mcp/standards/nav.json
|
||||
mcp/standards/modules/<module>.json
|
||||
|
||||
No doc-forge code is involved; the bundle is authored here so the spec and the
|
||||
machine-readable resources never drift.
|
||||
|
||||
Usage:
|
||||
python tools/build_standards.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
SRC = ROOT / "standards_src" / "wiki"
|
||||
OUT = ROOT / "mcp" / "standards"
|
||||
MODULES = OUT / "modules"
|
||||
|
||||
NUM_PREFIX = re.compile(r"^\d+[_-]?")
|
||||
|
||||
|
||||
def module_name(stem: str) -> str:
|
||||
"""Map a markdown filename to a module name (strip the NN_ prefix)."""
|
||||
return NUM_PREFIX.sub("", stem) or stem
|
||||
|
||||
|
||||
def read_title(path: Path) -> str:
|
||||
"""Return the first markdown H1 title, or a prettified fallback."""
|
||||
for line in path.read_text(encoding="utf-8").splitlines():
|
||||
if line.startswith("# "):
|
||||
return line[2:].strip()
|
||||
return module_name(path.stem).replace("_", " ").title()
|
||||
|
||||
|
||||
def write_module(name: str, body: str) -> None:
|
||||
payload = {
|
||||
"module": name,
|
||||
"content": {
|
||||
"path": name,
|
||||
"docstring": body.strip() + "\n",
|
||||
"objects": {},
|
||||
},
|
||||
}
|
||||
(MODULES / f"{name}.json").write_text(
|
||||
json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
|
||||
|
||||
def build() -> int:
|
||||
if not SRC.is_dir():
|
||||
raise SystemExit(f"wiki source not found: {SRC}")
|
||||
|
||||
MODULES.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
home = SRC / "index.md"
|
||||
if home.exists():
|
||||
write_module("index", home.read_text(encoding="utf-8"))
|
||||
nav = [{"module": "index", "resource": "docs://modules/index", "title": "Home"}]
|
||||
else:
|
||||
nav = []
|
||||
|
||||
for path in sorted(SRC.glob("*.md")):
|
||||
if path.name == "index.md":
|
||||
continue
|
||||
name = module_name(path.stem)
|
||||
write_module(name, path.read_text(encoding="utf-8"))
|
||||
nav.append({"module": name, "resource": f"docs://modules/{name}", "title": read_title(path)})
|
||||
|
||||
(OUT / "nav.json").write_text(
|
||||
json.dumps(nav, indent=2, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
(OUT / "index.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"project": "standards",
|
||||
"type": "standards",
|
||||
"modules_count": len(nav),
|
||||
"source": "hand-authored",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return len(nav)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
count = build()
|
||||
print(f"[OK] wrote {count} modules to {OUT.relative_to(ROOT)}/")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user