""" # Summary MCP renderer implementation. This module defines the `MCPRenderer` class, which generates documentation resources compatible with the Model Context Protocol (MCP). """ import json from pathlib import Path from docforge.models import DocObject, Module, Project class MCPRenderer: """ Renderer that generates MCP-compatible documentation resources. This renderer converts doc-forge project models into structured JSON resources suitable for consumption by systems implementing the Model Context Protocol (MCP). """ name = "mcp" def generate_sources(self, project: Project, out_dir: Path) -> None: """ Generate MCP documentation resources for a project. The renderer serializes each module into a JSON resource and produces supporting metadata files such as `nav.json` and `index.json`. Args: project (Project): Documentation project model to render. out_dir (Path): Directory where MCP resources will be written. """ modules_dir = out_dir / "modules" modules_dir.mkdir(parents=True, exist_ok=True) nav: list[dict[str, str]] = [] for module in project.get_all_modules(): self._write_module(module, modules_dir) nav.append( { "module": module.path, "resource": f"doc://modules/{module.path}", } ) # Write nav.json (out_dir / "nav.json").write_text( self._json(nav), encoding="utf-8", ) # Write index.json index = { "project": project.name, "type": "docforge-model", "modules_count": len(nav), "source": "docforge", } (out_dir / "index.json").write_text( self._json(index), encoding="utf-8", ) def _write_module(self, module: Module, modules_dir: Path) -> None: """ Serialize a module into an MCP resource file. Args: module (Module): Module instance to serialize. modules_dir (Path): Directory where module JSON files are stored. """ payload = { "module": module.path, "content": self._render_module(module), } out = modules_dir / f"{module.path}.json" out.parent.mkdir(parents=True, exist_ok=True) out.write_text(self._json(payload), encoding="utf-8") def _render_module(self, module: Module) -> dict: """ Convert a Module model into MCP-compatible structured data. Args: module (Module): Module instance to convert. Returns: Dict: Dictionary representing the module and its documented objects. """ data: dict = { "path": module.path, "docstring": module.docstring, "objects": {}, } for obj in module.get_all_objects(): data["objects"][obj.name] = self._render_object(obj) return data def _render_object(self, obj: DocObject) -> dict: """ Recursively convert a DocObject into structured MCP data. Args: obj (DocObject): Documentation object to convert. Returns: Dict: Dictionary describing the object and any nested members. """ data: dict = { "name": obj.name, "kind": obj.kind, "path": obj.path, "signature": obj.signature, "docstring": obj.docstring, } members = list(obj.get_all_members()) if members: data["members"] = { member.name: self._render_object(member) for member in members } return data @staticmethod def _json(data: dict) -> str: """ Serialize data to formatted JSON. Args: data (Dict): Dictionary to serialize. Returns: str: JSON string formatted with indentation and UTF-8 compatibility. """ return json.dumps(data, indent=2, ensure_ascii=False)