Files
doc-forge/docforge/renderers/mcp_renderer.py
Vishesh 'ironeagle' Bangotra 582b6809a0 docs: bring docforge docstrings and wiki to GSDFC standard
- fix GSDFC spec contradictions in __init__ docstring (parenthesized types, fenced-block rule) and sync generated README
- rewrite docstrings across loaders, models, nav, servers, renderers, cli; sync .pyi stubs
- add pydoclint (google style) gate to dev extras and pyproject config
- fix mcp nav resources doc:// -> docs://
- refresh docs/lib and docs/mcp, drop stale docforge/ duplicate group
- update wiki pages and add GSDFC + MCP guides under 05_development
2026-09-12 13:12:51 +05:30

160 lines
4.2 KiB
Python

"""
# 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"docs://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)