diff --git a/manage_docs.py b/manage_docs.py index a177dad..81c072c 100644 --- a/manage_docs.py +++ b/manage_docs.py @@ -25,9 +25,8 @@ Optional flags: --package-root NAME Root Python package name (default: mail_intake) """ -import argparse -import json import re +import argparse from pathlib import Path from typing import Iterable @@ -139,64 +138,6 @@ def extract_modules(md_file: Path) -> list[str]: return MKDOCSTRINGS_DIRECTIVE.findall(content) -def cmd_build_mcp(args: argparse.Namespace) -> None: - docs_root = args.docs_dir - mcp_root = args.mcp_dir - - modules_dir = mcp_root / "modules" - modules_dir.mkdir(parents=True, exist_ok=True) - - nav = [] - modules = [] - - for md in iter_markdown_files(docs_root): - rel = md.relative_to(docs_root) - - module_refs = extract_modules(md) - if not module_refs: - continue - - nav.append({ - "page": str(rel), - "modules": module_refs, - }) - - for module in module_refs: - module_entry = { - "module": module, - "doc_page": str(rel), - } - modules.append(module_entry) - - out = modules_dir / f"{module}.json" - out.parent.mkdir(parents=True, exist_ok=True) - out.write_text( - json.dumps(module_entry, indent=2), - encoding="utf-8", - ) - - mcp_root.mkdir(parents=True, exist_ok=True) - - (mcp_root / "nav.json").write_text( - json.dumps(nav, indent=2), - encoding="utf-8", - ) - - (mcp_root / "index.json").write_text( - json.dumps( - { - "project": "Aetoskia Mail Intake", - "type": "docs-only", - "modules_count": len(modules), - }, - indent=2, - ), - encoding="utf-8", - ) - - print(f"MCP artifacts written to: {mcp_root}") - - # ------------------------- # CLI # ------------------------- @@ -220,13 +161,6 @@ def main() -> None: help="Root Python package name", ) - parser.add_argument( - "--mcp-dir", - type=Path, - default=DEFAULT_MCP_DIR, - help="Output directory for MCP artifacts", - ) - subparsers = parser.add_subparsers(dest="command", required=True) subparsers.add_parser( @@ -244,13 +178,6 @@ def main() -> None: help="Serve the MkDocs site locally", ).set_defaults(func=cmd_serve) - subparsers.add_parser( - "build_mcp", - help="Generate MCP artifacts (docs-only)", - ).set_defaults( - func=cmd_build_mcp - ) - args = parser.parse_args() args.func(args) diff --git a/mcp_server.py b/mcp_server.py index 9d76160..2961060 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -2,28 +2,31 @@ from pathlib import Path import json from mcp.server.fastmcp import FastMCP -MCP_ROOT = Path(__file__).resolve().parent / "mcp" +MCP_ROOT = Path("mcp") mcp = FastMCP("aetoskia-mail-intake-docs") +def read_json(path: Path): + if not path.exists(): + return {"error": "not_found", "path": str(path)} + return json.loads(path.read_text()) @mcp.resource("docs://index") def index(): - return json.loads((MCP_ROOT / "index.json").read_text()) - + return read_json(MCP_ROOT / "index.json") @mcp.resource("docs://nav") def nav(): - return json.loads((MCP_ROOT / "nav.json").read_text()) + return read_json(MCP_ROOT / "nav.json") - -@mcp.resource("docs://module/{module}") +@mcp.resource("docs://{module}") def module(module: str): - path = MCP_ROOT / "modules" / f"{module}.json" - if not path.exists(): - raise FileNotFoundError(module) - return json.loads(path.read_text()) + return read_json(MCP_ROOT / "modules" / f"{module}.json") +@mcp.tool() +def ping() -> str: + return "Pong! (fake tool executed)" if __name__ == "__main__": - mcp.run() + # FastMCP owns the HTTP server + mcp.run(transport="streamable-http") diff --git a/requirements.txt b/requirements.txt index 51d0b66..21f6f67 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,10 @@ google-api-python-client==2.187.0 google-auth-oauthlib==1.2.3 types-beautifulsoup4 mcp==1.25.0 +mcp-inspector==0.1.0 +fastapi +uvicorn +fastmcp # Test Packages pytest==7.4.0 @@ -14,5 +18,5 @@ mkdocs==1.6.1 mkdocs-material==9.6.23 neoteroi-mkdocs==1.1.3 pymdown-extensions==10.16.1 -mkdocstrings==1.0.0 +mkdocstrings[python]==1.0.1 mkdocstrings-python==2.0.1