feat: unify docs portal and MCP servers into one config-driven service
- add config.yml as single source of truth for collected repos/categories - add collect.py CLI to pull lib/api/wiki site builds and mcp bundles from source repos and regenerate nginx.conf + _index/index.html - port mcp runtime (main.py/core.py/config.py): nginx + health + FastMCP servers started from config.yml - docker: python:3.13-slim + nginx, expose 8000-8006 + 9000 (html portal) - drone: publish html (6007:9000) and MCP ports 8000-8006 - move mongo-ops docs to wiki/, add auth-server (api) and hexa (lib) - refresh lib site builds (lib/ prefix) and collect mcp bundles
This commit is contained in:
68
config.py
Normal file
68
config.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MCPBundle:
|
||||
root: Path
|
||||
name: str
|
||||
port: int
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RepoDoc:
|
||||
name: str
|
||||
description: str | None
|
||||
lib: str | None
|
||||
api: str | None
|
||||
wiki: str | None
|
||||
mcp_bundle: str | None # source-relative path in the repo (collect use)
|
||||
mcp_server: str | None # MCP server / namespace name
|
||||
mcp_port: int | None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ServiceConfig:
|
||||
name: str
|
||||
html_port: int
|
||||
health_port: int
|
||||
repos: tuple[RepoDoc, ...]
|
||||
|
||||
@property
|
||||
def mcp_servers(self) -> dict[str, MCPBundle]:
|
||||
"""Return only repos that expose an MCP server."""
|
||||
return {
|
||||
r.name: MCPBundle(root=Path("mcp") / r.name, name=r.mcp_server, port=r.mcp_port)
|
||||
for r in self.repos
|
||||
if r.mcp_port is not None
|
||||
}
|
||||
|
||||
|
||||
def load_config(path: Path | str = "config.yml") -> ServiceConfig:
|
||||
p = Path(path)
|
||||
data = yaml.safe_load(p.read_text(encoding="utf-8"))
|
||||
service = data.get("service") or {}
|
||||
repos: list[RepoDoc] = []
|
||||
for entry in data.get("repos", []):
|
||||
docs = entry.get("docs") or {}
|
||||
mcp = docs.get("mcp")
|
||||
repos.append(RepoDoc(
|
||||
name=entry["name"],
|
||||
description=entry.get("description"),
|
||||
lib=docs.get("lib"),
|
||||
api=docs.get("api"),
|
||||
wiki=docs.get("wiki"),
|
||||
mcp_bundle=mcp["bundle"] if mcp else None,
|
||||
mcp_server=mcp["server"] if mcp else None,
|
||||
mcp_port=mcp["port"] if mcp else None,
|
||||
))
|
||||
return ServiceConfig(
|
||||
name=service.get("name", "aetos-docs"),
|
||||
html_port=service.get("html_port", 9000),
|
||||
health_port=service.get("health_port", 8000),
|
||||
repos=tuple(repos),
|
||||
)
|
||||
Reference in New Issue
Block a user