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
This commit is contained in:
2026-09-12 13:12:51 +05:30
parent 8c6c46caf2
commit 582b6809a0
82 changed files with 1467 additions and 703 deletions

View File

@@ -41,6 +41,18 @@ doc-forge build --mcp --module my_package
doc-forge build --mcp --mkdocs --module my_package
```
## Include a hand-written wiki in the MkDocs site:
```bash
doc-forge build --wiki --mkdocs --module my_package
```
## Build wiki pages only (no module required):
```bash
doc-forge build --wiki --site-name my_package
```
## Serve MkDocs locally:
```bash
@@ -129,7 +141,9 @@ GSDFC defines how docstrings must be written so they render correctly in MkDocs
- Use **Markdown headings** at package and module level.
- Use **Google-style structured sections** at class, function, and method level.
- Use type hints in signatures instead of duplicating types in prose.
- Use type hints in signatures.
- Use parenthesized types in prose entries (`name (Type):`) that match the
signature types. This keeps docstrings self-contained and machine-parseable.
- Write summaries in imperative form.
- Sections are separated by `---`
@@ -189,7 +203,10 @@ Example:
engine.run()
```
Avoid fenced code blocks inside structured sections.
Avoid fenced code blocks inside argument descriptions and other prose lines.
Inside `Example:` sections, fenced `python` code blocks are allowed and must be
indented four spaces, matching the examples below.
---

View File

@@ -35,7 +35,8 @@ def load_openapi_spec(spec_path: Path) -> dict:
Load and validate an OpenAPI specification from a JSON file.
Args:
spec_path: Path to the OpenAPI JSON specification file.
spec_path (Path):
Path to the OpenAPI JSON specification file.
Returns:
dict:
@@ -68,7 +69,8 @@ def derive_metadata(spec: dict) -> OpenAPIMetadata:
Derive MkDocs site metadata from an OpenAPI spec ``info`` block.
Args:
spec: Parsed OpenAPI specification.
spec (dict):
Parsed OpenAPI specification.
Returns:
OpenAPIMetadata:
@@ -97,8 +99,10 @@ def generate_api_sources(spec: dict, docs_dir: Path) -> None:
an ``index.md`` embedding the swagger UI is generated alongside it.
Args:
spec: Parsed OpenAPI specification.
docs_dir: Directory (for example ``docs/api``) where the swagger
spec (dict):
Parsed OpenAPI specification.
docs_dir (Path):
Directory (for example ``docs/api``) where the swagger
sources are written.
"""
docs_dir.mkdir(parents=True, exist_ok=True)

View File

@@ -4,6 +4,15 @@
Command definitions for the doc-forge CLI.
Provides the CLI structure using Click, including build, serve, and tree commands.
---
Notes:
- The `build` command validates requested modes before generating anything.
- `--mkdocs`, `--api`, and `--wiki` share a single MkDocs build; `--mcp`
generates a machine-readable bundle independently.
---
"""
from pathlib import Path
@@ -12,6 +21,7 @@ import click
from docforge.cli import api_utils, mcp_utils, mkdocs_utils
from docforge.loaders import GriffeLoader
from docforge.models import DocObject
@click.group()
@@ -99,9 +109,9 @@ def build(
"""
Build documentation artifacts.
This command performs the full documentation build pipeline:
style of the selected platform, generates renderer-specific
documentation sources, and optionally builds the final output.
This command runs the full documentation pipeline: it loads Python
modules, generates renderer-specific documentation sources, and
optionally builds or serves the final output.
Depending on the selected options, the build can target:
@@ -110,6 +120,12 @@ def build(
- Hand-written wiki pages included in the MkDocs site
- MCP structured documentation resources
Notes:
- At least one of `--mcp`, `--mkdocs`, `--wiki`, or `--api` must be
provided.
- `--mkdocs`, `--api`, and `--wiki` are combined into a single MkDocs
build, while `--mcp` emits a machine-readable bundle.
Args:
mcp (bool):
Enable MCP documentation generation.
@@ -126,16 +142,16 @@ def build(
module_is_source (bool):
Treat the specified module directory as the project root.
module (Optional[str]):
module (str | None):
Python module import path to document.
openapi_spec (Optional[Path]):
openapi_spec (Path | None):
Path to the OpenAPI JSON specification used for API docs.
project_name (Optional[str]):
project_name (str | None):
Optional override for the project name.
site_name (Optional[str]):
site_name (str | None):
Display name for the MkDocs site.
docs_dir (Path):
@@ -147,7 +163,7 @@ def build(
nav_file (Path):
Path to the navigation specification file.
template (Optional[Path]):
template (Path | None):
Optional custom MkDocs configuration template.
mkdocs_yml (Path):
@@ -282,7 +298,7 @@ def serve(
mkdocs (bool):
Serve the MkDocs development site.
module (Optional[str]):
module (str | None):
Python module import path to serve via MCP.
mkdocs_yml (Path):
@@ -333,7 +349,7 @@ def tree(
module (str):
Python module import path to introspect.
project_name (Optional[str]):
project_name (str | None):
Optional name to display as the project root.
"""
loader = GriffeLoader()
@@ -347,7 +363,7 @@ def tree(
_print_object(obj, indent="│ ")
def _print_object(obj, indent: str) -> None:
def _print_object(obj: DocObject, indent: str) -> None:
"""
Recursively print a documentation object and its members.
@@ -355,7 +371,7 @@ def _print_object(obj, indent: str) -> None:
and prints each object with indentation to represent hierarchy.
Args:
obj:
obj (DocObject):
Documentation object to print.
indent (str):

View File

@@ -1,8 +1,9 @@
from pathlib import Path
from typing import Any
from click.core import Group
from docforge.models import DocObject
cli: Group
def build(
@@ -33,4 +34,4 @@ def tree(
module: str,
project_name: str | None,
) -> None: ...
def _print_object(obj: Any, indent: str) -> None: ...
def _print_object(obj: DocObject, indent: str) -> None: ...

View File

@@ -2,6 +2,16 @@
# Summary
Utilities for working with MCP in the doc-forge CLI.
---
Notes:
- `generate_resources` produces the bundle consumed by `MCPServer`:
`index.json`, `nav.json`, and per-module resources under `modules/`.
- Resource URIs use the `docs://` scheme: `docs://index`, `docs://nav`,
and `docs://modules/{module}`.
---
"""
from pathlib import Path
@@ -26,7 +36,7 @@ def generate_resources(module: str, project_name: str | None, out_dir: Path) ->
Python module import path used as the entry point for
documentation generation.
project_name (Optional[str]):
project_name (str | None):
Optional override for the project name used in generated
documentation metadata.

View File

@@ -2,6 +2,15 @@
# Summary
Utilities for working with MkDocs in the doc-forge CLI.
---
Notes:
- A single generated `mkdocs.yml` serves lib, api, and wiki content with
merged navigation. Wiki navigation, when enabled, precedes every other
group and its `index.md` becomes the site `Home`.
---
"""
import os
@@ -44,14 +53,14 @@ def generate_sources(
docs_dir (Path):
Directory where the generated Markdown files will be written.
project_name (Optional[str]):
project_name (str | None):
Optional override for the project name used in documentation metadata.
module_is_source (Optional[bool]):
module_is_source (bool | None):
If True, treat the specified module directory as the project root
rather than a nested module.
readme_dir (Optional[Path]):
readme_dir (Path | None):
Directory where the generated README.md should be written. If not
provided, defaults to the parent of ``docs_dir``.
"""
@@ -105,7 +114,7 @@ def generate_config(
nav_file (Path):
Path to the `docforge.nav.yml` navigation specification.
template (Optional[Path]):
template (Path | None):
Optional path to a fully custom MkDocs configuration template.
If not provided, built-in templates are merged; the provided
template replaces the built-in templates entirely.
@@ -116,19 +125,19 @@ def generate_config(
site_name (str):
Display name for the generated documentation site.
modes (Optional[Iterable[str]]):
modes (Iterable[str] | None):
Documentation modes to enable. Each mode contributes its own
built-in template fragment (for example ``lib``, ``api``, or
``wiki``), merged on top of the shared ``mkdocs.common.yml``
template.
site_description (Optional[str]):
site_description (str | None):
Optional site description written into the configuration.
site_author (Optional[str]):
site_author (str | None):
Optional site author written into the configuration.
wiki_dir (Optional[Path]):
wiki_dir (Path | None):
Optional path to a hand-written wiki directory (for example
``docs/wiki``). When provided, the site navigation is derived
from the wiki file structure and placed before the navigation
@@ -186,13 +195,13 @@ def _load_template(
When a custom template path is provided, it is used as-is. Otherwise the
shared ``mkdocs.common.yml`` template is deep-merged with the fragments
contributed by each enabled mode (``lib`` or ``api``).
contributed by each enabled mode (``lib``, ``api``, or ``wiki``).
Args:
template (Optional[Path]):
template (Path | None):
Optional fully custom template that replaces the built-ins.
modes (Optional[Iterable[str]]):
modes (Iterable[str] | None):
Documentation modes whose template fragments should be merged.
Returns:
@@ -237,7 +246,8 @@ def _item_name(item: object) -> str:
first key. This is used to deduplicate plugin and extension lists.
Args:
item: List entry, either a string or a single-key mapping.
item (object):
List entry, either a string or a single-key mapping.
Returns:
str:
@@ -253,8 +263,10 @@ def _merge_list(base: list, added: list) -> list:
Merge two lists, preserving order and dropping duplicates by name.
Args:
base: Existing list entries.
added: Entries to append when not already present.
base (list):
Existing list entries.
added (list):
Entries to append when not already present.
Returns:
list:
@@ -279,8 +291,10 @@ def _deep_merge(base: dict, part: dict) -> dict:
the fragment override the base.
Args:
base: Configuration being built up.
part: Template fragment to merge into the base.
base (dict):
Configuration being built up.
part (dict):
Template fragment to merge into the base.
Returns:
dict:

View File

@@ -6,6 +6,14 @@ Utilities for loading and introspecting Python modules using Griffe.
This module provides the `GriffeLoader` class and helper utilities used to
discover Python modules, introspect their structure, and convert the results
into doc-forge documentation models.
---
Notes:
- All analysis is static; analyzed modules are never executed.
- Private members (names starting with `_`) are skipped during conversion.
---
"""
import logging
@@ -46,12 +54,12 @@ def discover_module_paths(
module_name (str):
Top-level package name to discover modules from.
project_root (Path, optional):
project_root (Path | None):
Root directory used to resolve module paths. If not provided, the
current working directory is used.
Returns:
List[str]:
list[str]:
A sorted list of unique dotted module import paths.
Raises:
@@ -88,6 +96,10 @@ class GriffeLoader:
This loader uses the Griffe introspection engine to analyze Python source
code and transform the extracted information into `Project`, `Module`,
and `DocObject` instances used by doc-forge.
Attributes:
_loader (_GriffeLoader):
Internal Griffe loader with dedicated module and line collections.
"""
def __init__(self) -> None:
@@ -106,7 +118,7 @@ class GriffeLoader:
self,
module_paths: list[str],
project_name: str | None = None,
skip_import_errors: bool = None,
skip_import_errors: bool | None = None,
) -> Project:
"""
Load multiple modules and assemble them into a Project model.
@@ -116,14 +128,14 @@ class GriffeLoader:
object.
Args:
module_paths (List[str]):
module_paths (list[str]):
List of dotted module import paths to load.
project_name (str, optional):
project_name (str | None):
Optional override for the project name. Defaults to the top-level
name of the first module.
skip_import_errors (bool, optional):
skip_import_errors (bool | None):
If True, modules that fail to load will be skipped instead of raising an error.
Returns:
@@ -172,6 +184,21 @@ class GriffeLoader:
Returns:
Module:
A populated `Module` instance.
Raises:
ImportError:
If the module cannot be loaded by Griffe.
KeyError:
If the loaded module is missing from the module collection.
Example:
Load a single module:
```python
loader = GriffeLoader()
module = loader.load_module("mypackage.submodule")
```
"""
self._loader.load(path)
griffe_module = self._loader.modules_collection[path]
@@ -260,7 +287,7 @@ class GriffeLoader:
Griffe object to inspect.
Returns:
Optional[str]:
str | None:
The raw docstring text if available, otherwise `None`.
"""
try:
@@ -277,7 +304,7 @@ class GriffeLoader:
Griffe object to inspect.
Returns:
Optional[str]:
str | None:
String representation of the object's signature if available, otherwise `None`.
"""
try:

View File

@@ -11,6 +11,7 @@ class GriffeLoader:
"""Griffe-based introspection loaders.
This is the only supported introspection backend in doc-forge.
Converts Griffe results into `Project`, `Module`, and `DocObject` models.
"""
def __init__(self) -> None: ...
@@ -18,7 +19,7 @@ class GriffeLoader:
self,
module_paths: list[str],
project_name: str | None = ...,
skip_import_errors: bool = ...,
skip_import_errors: bool | None = ...,
) -> Project:
"""Load a documentation project from Python modules."""

View File

@@ -7,6 +7,13 @@ This module defines the `Module` class used in the doc-forge documentation
model. A `Module` acts as a container for top-level documented objects
(classes, functions, variables, and other members) discovered during
introspection.
---
Notes:
- Only public members are stored; private names are filtered by the loader.
---
"""
from collections.abc import Iterable
@@ -26,10 +33,10 @@ class Module:
path (str):
Dotted import path of the module.
docstring (Optional[str]):
docstring (str | None):
Module-level documentation string, if present.
members (Dict[str, DocObject]):
members (dict[str, DocObject]):
Mapping of object names to their corresponding `DocObject` representations.
"""
@@ -45,7 +52,7 @@ class Module:
path (str):
Dotted import path identifying the module.
docstring (Optional[str]):
docstring (str | None):
Module-level documentation text, if available.
"""
self.path = path

View File

@@ -7,6 +7,14 @@ This module defines the `DocObject` class, the fundamental recursive unit of
the doc-forge documentation model. Each `DocObject` represents a Python
entity such as a class, function, method, or attribute, and may contain nested
members that form a hierarchical documentation structure.
---
Notes:
- `DocObject` instances form a tree mirroring the Python import hierarchy.
- Objects are renderer-agnostic and may be consumed by any renderer.
---
"""
from collections.abc import Iterable
@@ -30,13 +38,13 @@ class DocObject:
path (str):
Fully qualified dotted path to the object.
signature (Optional[str]):
signature (str | None):
Callable signature if the object represents a callable.
docstring (Optional[str]):
docstring (str | None):
Raw docstring text extracted from the source code.
members (Dict[str, DocObject]):
members (dict[str, DocObject]):
Mapping of member names to child `DocObject` instances.
"""
@@ -61,10 +69,10 @@ class DocObject:
path (str):
Fully qualified dotted path of the object.
signature (Optional[str]):
signature (str | None):
Callable signature if applicable.
docstring (Optional[str]):
docstring (str | None):
Documentation string associated with the object.
"""
self.name = name
@@ -82,7 +90,8 @@ class DocObject:
nested objects to their parent containers.
Args:
obj: Documentation object to add as a member.
obj (DocObject):
Documentation object to add as a member.
"""
self.members[obj.name] = obj

View File

@@ -6,6 +6,14 @@ Documentation model representing a project.
This module defines the `Project` class, the top-level container used by
doc-forge to represent a documented codebase. A `Project` aggregates multiple
modules and provides access to them through a unified interface.
---
Notes:
- Modules are keyed by their dotted import path.
- Objects are renderer-agnostic; the same model feeds every renderer.
---
"""
from collections.abc import Iterable
@@ -24,7 +32,7 @@ class Project:
name (str):
Name of the project.
modules (Dict[str, Module]):
modules (dict[str, Module]):
Mapping of module paths to `Module` instances.
"""
@@ -35,6 +43,14 @@ class Project:
Args:
name (str):
Name used to identify the documentation project.
Example:
Create a project and register a module:
```python
project = Project("mypackage")
project.add_module(module)
```
"""
self.name = name
self.modules: dict[str, Module] = {}

View File

@@ -4,6 +4,14 @@ MkDocs navigation emitter.
This module provides the ``MkDocsNavEmitter`` class, which converts a
``ResolvedNav`` instance into the navigation structure required by the
MkDocs ``nav`` configuration.
---
Notes:
- The emitted structure is a list of dictionaries, one per top-level nav
entry, matching the MkDocs ``nav`` YAML format.
---
"""
from pathlib import Path
@@ -25,13 +33,15 @@ class MkDocsNavEmitter:
Generate a navigation structure for ``mkdocs.yml``.
Args:
nav: Resolved navigation data describing documentation groups
nav (ResolvedNav):
Resolved navigation data describing documentation groups
and their associated Markdown files.
Returns:
A list of dictionaries representing the MkDocs navigation layout.
Each dictionary maps a navigation label to a page or a list of
pages.
list[dict[str, Any]]:
A list of dictionaries representing the MkDocs navigation layout.
Each dictionary maps a navigation label to a page or a list of
pages.
"""
result: list[dict[str, Any]] = []
@@ -59,11 +69,14 @@ class MkDocsNavEmitter:
resulting path is relative to the documentation root.
Args:
path: Filesystem path to convert.
docs_root: Root directory of the documentation sources.
path (Path):
Filesystem path to convert.
docs_root (Path | None):
Root directory of the documentation sources.
Returns:
POSIX-style path relative to the documentation root.
str:
POSIX-style path relative to the documentation root.
"""
if docs_root and path.is_absolute():
try:

View File

@@ -3,6 +3,14 @@ Navigation resolution utilities.
This module resolves a ``NavSpec`` against the filesystem by expanding glob
patterns and validating that referenced documentation files exist.
---
Notes:
- Glob resolution is recursive and returns paths in sorted order.
- Unmatched patterns raise ``FileNotFoundError`` to fail fast on typos.
---
"""
import glob
@@ -35,9 +43,12 @@ class ResolvedNav:
Initialize a ResolvedNav instance.
Args:
home: Relative path to the home page within the documentation root.
groups: Mapping of group titles to resolved documentation file paths.
docs_root: Root directory of the documentation source files.
home (str | None):
Relative path to the home page within the documentation root.
groups (dict[str, list[Path]]):
Mapping of group titles to resolved documentation file paths.
docs_root (Path | None):
Root directory of the documentation source files.
"""
self.home = home
self.groups = groups
@@ -47,8 +58,10 @@ class ResolvedNav:
"""
Iterate over all files referenced by the navigation structure.
Returns:
An iterable of ``Path`` objects representing documentation files.
Yields:
Path:
A documentation file referenced by the navigation, including
the home page when defined.
Raises:
RuntimeError: If the home page is defined but the documentation
@@ -74,11 +87,14 @@ def resolve_nav(
that referenced documentation files exist within the documentation root.
Args:
spec: Navigation specification describing documentation layout.
docs_root: Root directory containing documentation Markdown files.
spec (NavSpec):
Navigation specification describing documentation layout.
docs_root (Path):
Root directory containing documentation Markdown files.
Returns:
A ``ResolvedNav`` instance containing validated navigation paths.
ResolvedNav:
A `ResolvedNav` instance containing validated navigation paths.
Raises:
FileNotFoundError: If the documentation root does not exist or a
@@ -92,10 +108,12 @@ def resolve_nav(
Resolve a glob pattern relative to the documentation root.
Args:
pattern: Glob pattern used to match documentation files.
pattern (str):
Glob pattern used to match documentation files.
Returns:
A sorted list of matching ``Path`` objects.
list[Path]:
A sorted list of matching `Path` objects.
Raises:
FileNotFoundError: If the pattern does not match any files.

View File

@@ -4,8 +4,19 @@ Navigation specification model.
This module defines the ``NavSpec`` class, which represents the navigation
structure defined by the user in the doc-forge navigation specification
(typically ``docforge.nav.yml``).
---
Notes:
- The spec file supports an optional ``icon`` mapping for MkDocs theme
customization.
- All file references in ``groups`` are relative to the documentation root.
---
"""
from __future__ import annotations
from pathlib import Path
import yaml
@@ -38,10 +49,13 @@ class NavSpec:
Initialize a NavSpec instance.
Args:
home: Relative path to the home document.
groups: Mapping of group names to lists of path patterns
home (str | None):
Relative path to the home document.
groups (dict[str, list[str]]):
Mapping of group names to lists of path patterns
(glob expressions).
icon: Optional mapping of theme icon entries applied to the
icon (dict[str, str] | None):
Optional mapping of theme icon entries applied to the
generated MkDocs configuration.
"""
self.home = home
@@ -49,15 +63,17 @@ class NavSpec:
self.icon = icon
@classmethod
def load(cls, path: Path) -> "NavSpec":
def load(cls, path: Path) -> NavSpec:
"""
Load a navigation specification from a YAML file.
Args:
path: Filesystem path to the navigation specification file.
path (Path):
Filesystem path to the navigation specification file.
Returns:
A ``NavSpec`` instance representing the parsed configuration.
NavSpec:
A ``NavSpec`` instance representing the parsed configuration.
Raises:
FileNotFoundError: If the specified file does not exist.
@@ -105,8 +121,9 @@ class NavSpec:
Return all path patterns referenced by the specification.
Returns:
A list containing the home document (if defined) and all
group pattern entries.
list[str]:
A list containing the home document (if defined) and all
group pattern entries.
"""
patterns: list[str] = []
@@ -127,10 +144,12 @@ def load_nav_spec(path: Path) -> NavSpec:
corresponding ``NavSpec`` instance.
Args:
path: Path to the navigation specification file.
path (Path):
Path to the navigation specification file.
Returns:
A ``NavSpec`` instance representing the parsed specification.
NavSpec:
A ``NavSpec`` instance representing the parsed specification.
Raises:
FileNotFoundError: If the specification file does not exist.

View File

@@ -20,6 +20,7 @@ modified by doc-forge; only the navigation layout is inferred.
"""
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
@@ -46,7 +47,7 @@ def build_wiki_nav(wiki_dir: Path) -> list[dict[str, Any]]:
Path to the hand-written wiki directory, for example ``docs/wiki``.
Returns:
List[Dict[str, Any]]:
list[dict[str, Any]]:
Navigation entries compatible with the MkDocs ``nav`` configuration.
The list is empty if the wiki contains no Markdown files.
@@ -75,7 +76,10 @@ def build_wiki_nav(wiki_dir: Path) -> list[dict[str, Any]]:
return nav
def _render_entries(base_dir: Path, rel) -> list[dict[str, Any]]:
def _render_entries(
base_dir: Path,
rel: Callable[[Path], str],
) -> list[dict[str, Any]]:
"""
Render navigation entries for the children of a wiki directory.
@@ -87,11 +91,11 @@ def _render_entries(base_dir: Path, rel) -> list[dict[str, Any]]:
base_dir (Path):
Directory whose children are rendered.
rel:
rel (Callable[[Path], str]):
Callable converting a wiki file path into a docs-relative path.
Returns:
List[Dict[str, Any]]:
list[dict[str, Any]]:
Navigation entries for ``base_dir`` in natural sort order.
"""
children = sorted(
@@ -152,7 +156,7 @@ def _natural_key(name: str) -> list[object]:
Filename or directory name to key.
Returns:
List[object]:
list[object]:
Mixed list of lowercased strings and integers used for sorting.
"""
return [

View File

@@ -1,3 +1,4 @@
from collections.abc import Callable
from pathlib import Path
from typing import Any
@@ -5,11 +6,36 @@ def build_wiki_nav(wiki_dir: Path) -> list[dict[str, Any]]:
"""
Derive an MkDocs navigation block from a wiki directory.
Args:
wiki_dir (Path):
Path to the hand-written wiki directory.
Returns:
Wiki navigation entries compatible with the MkDocs
`nav` configuration.
list[dict[str, Any]]:
Wiki navigation entries compatible with the MkDocs `nav`
configuration.
Raises:
FileNotFoundError: if the wiki directory does not exist
FileNotFoundError:
If the wiki directory does not exist.
"""
...
def _render_entries(
base_dir: Path,
rel: Callable[[Path], str],
) -> list[dict[str, Any]]:
"""
Render navigation entries for the children of a wiki directory.
Args:
base_dir (Path):
Directory whose children are rendered.
rel (Callable[[Path], str]):
Callable converting a wiki file path into a docs-relative path.
Returns:
list[dict[str, Any]]:
Navigation entries for `base_dir` in natural sort order.
"""
...

View File

@@ -49,7 +49,7 @@ class MCPRenderer:
nav.append(
{
"module": module.path,
"resource": f"doc://modules/{module.path}",
"resource": f"docs://modules/{module.path}",
}
)
@@ -101,7 +101,7 @@ class MCPRenderer:
Module instance to convert.
Returns:
Dict:
dict:
Dictionary representing the module and its documented objects.
"""
data: dict = {
@@ -124,7 +124,7 @@ class MCPRenderer:
Documentation object to convert.
Returns:
Dict:
dict:
Dictionary describing the object and any nested members.
"""
data: dict = {
@@ -149,7 +149,7 @@ class MCPRenderer:
Serialize data to formatted JSON.
Args:
data (Dict):
data (dict):
Dictionary to serialize.
Returns:

View File

@@ -54,7 +54,7 @@ class MkDocsRenderer:
out_dir (Path):
Directory where generated Markdown files will be written.
module_is_source (bool, optional):
module_is_source (bool | None):
If True, treat the specified module as the documentation root
rather than nesting it inside a folder.
"""
@@ -87,11 +87,10 @@ class MkDocsRenderer:
"""
Generate a `README.md` file from the root module docstring.
Behavior:
- If `module_is_source` is True, `README.md` is written to the project
root directory.
- If False, README generation is currently not implemented.
Notes:
- If `module_is_source` is True, `README.md` is written to the
project root directory.
- If False, README generation is currently not implemented.
Args:
project (Project):
@@ -100,10 +99,10 @@ class MkDocsRenderer:
docs_dir (Path):
Directory containing generated documentation sources.
module_is_source (Optional[bool]):
module_is_source (bool | None):
Whether the module is treated as the project source root.
readme_dir (Optional[Path]):
readme_dir (Path | None):
Directory where the generated README.md should be written.
Defaults to the parent of `docs_dir`.
"""
@@ -157,7 +156,7 @@ class MkDocsRenderer:
Project model to inspect.
Returns:
Optional[Module]:
Module | None:
The root `Module` if found, otherwise `None`.
"""
for module in project.get_all_modules():
@@ -189,7 +188,7 @@ class MkDocsRenderer:
out_dir (Path):
Base directory for generated documentation files.
module_is_source (bool, optional):
module_is_source (bool | None):
Whether the module acts as the documentation root directory.
"""

View File

@@ -5,6 +5,16 @@ MCP server implementation.
This module defines the `MCPServer` class, which serves pre-generated
documentation bundles through the Model Context Protocol (MCP).
---
Notes:
- The served bundle is generated offline by `MCPRenderer`.
- Missing resources are reported as structured error dictionaries rather
than raising exceptions.
- The server exposes read-only resources and a single health-check tool.
---
"""
from __future__ import annotations
@@ -22,6 +32,14 @@ class MCPServer:
The server exposes documentation resources and diagnostic tools through
MCP endpoints backed by JSON files generated by the MCP renderer.
Attributes:
mcp_root (Path):
Directory containing the generated MCP documentation bundle.
app (FastMCP):
Underlying FastMCP application instance that registers resources
and tools.
"""
def __init__(self, mcp_root: Path, name: str) -> None:

View File

@@ -4,7 +4,10 @@ from typing import Any, Literal
from mcp.server.fastmcp import FastMCP
class MCPServer:
"""MCP server for serving documentation."""
"""MCP server serving a pre-generated documentation bundle.
Exposes read-only documentation resources and a health-check tool.
"""
mcp_root: Path
app: FastMCP