""" # 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 typing import Dict, List from docforge.models import Project, Module, DocObject 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)