Skip to content

docforge

docforge

Summary

Renderer-agnostic Python documentation compiler that converts Python docstrings into structured documentation for both humans (MkDocs) and machines (MCP / AI agents).

doc-forge statically analyzes source code, builds a semantic model of modules, classes, functions, and attributes, and renders that model into documentation outputs without executing user code.


Installation

Install using pip:

pip install doc-forge

CLI usage

Generate an MkDocs site from a Python package:

doc-forge build --mkdocs --module my_package

Generate MCP JSON documentation:

doc-forge build --mcp --module my_package

Generate MkDocs site and MCP JSON documentation:

doc-forge build --mcp --mkdocs --module my_package

Serve MkDocs locally:

doc-forge serve --mkdocs --module my_package

Serve MCP locally:

doc-forge serve --mcp --module my_package

Core concepts

Loader

Extracts symbols, signatures, and docstrings using static analysis.

Semantic model

Structured, renderer-agnostic representation of the API.

Renderer

Converts the semantic model into output formats such as MkDocs or MCP JSON.

Symbol

Any documentable object

  • module
  • class
  • function
  • method
  • property
  • attribute

Architecture

doc-forge follows a compiler architecture:

Front-end:

Static analysis of modules, classes, functions, type hints, and docstrings.

Middle-end:

Builds a semantic model describing symbols and relationships.

Back-end:

Renders documentation using interchangeable renderers.

This architecture ensures deterministic documentation generation.


Rendering pipeline

Typical flow:

1
2
3
4
5
6
7
8
9
Python package
    |
Loader (static analysis)
    |
Semantic model
    |
Renderer
    |
MkDocs site or MCP JSON

Google-Styled Doc-Forge Convention (GSDFC)

GSDFC defines how docstrings must be written so they render correctly in MkDocs and remain machine-parsable by doc-forge and AI tooling.

  • Docstrings are the single source of truth.
  • doc-forge compiles docstrings but does not generate documentation content.
  • Documentation follows the Python import hierarchy.
  • Every public symbol should have a complete and accurate docstring.

General rules

  • 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.
  • Write summaries in imperative form.
  • Sections are separated by ---

Notes subsection grouping

Group related information using labeled subsections.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Notes:
    **Guarantees:**

        - deterministic behavior

    **Lifecycle:**

        - created during initialization
        - reused across executions

    **Thread safety:**

        - safe for concurrent reads

Example formatting

  • Use indentation for examples.
  • Indent section contents using four spaces.
  • Use code blocks for example code.
Example

Single example:

1
2
3
4
5
6
Example:

    ```python
    foo = Foo("example")
    process(foo, multiplier=2)
    ```

Multiple examples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Example:
    Create foo:

        ```python
        foo = Foo("example")
        ```

    Run engine:

        ```python
        engine = BarEngine([foo])
        engine.run()
        ```

Avoid fenced code blocks inside structured sections.


Separator rules

Use horizontal separators only at docstring root level to separate sections:

---

Allowed locations:

  • package docstrings
  • module docstrings
  • major documentation sections

Do not use separators inside code sections.


Package docstrings

Package docstrings act as the documentation home page.

Recommended sections:

1
2
3
4
5
6
7
8
9
# Summary
# Installation
# Quick start
# CLI usage
# Core concepts
# Architecture
# Rendering pipeline
# Examples
# Notes
Example

Package Doc String:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
'''
# Summary

Foo-bar processing framework.

Provides tools for defining Foo objects and executing Bar pipelines.

---

# Installation

```bash
pip install foo-bar
```

---

# Quick start

```python
from foobar import Foo, BarEngine

foo = Foo("example")
engine = BarEngine([foo])

result = engine.run()
```

---
'''

Module docstrings

Module docstrings describe a subsystem.

Recommended sections:

1
2
3
# Summary
# Examples
# Notes
Example

Module Doc String:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'''
# Summary

Foo execution subsystem.

Provides utilities for executing Foo objects through Bar stages.

---

Example:

    ```python
    from foobar.engine import BarEngine
    from foobar.foo import Foo

    foo = Foo("example")

    engine = BarEngine([foo])
    engine.run()
    ```

---
'''

Class docstrings

Class docstrings define object responsibility, lifecycle, and attributes.

Recommended sections:

1
2
3
4
Attributes:
Notes:
Example:
Raises:
Example

Simple Foo:

class Foo:
    '''
    Represents a unit of work.

    Attributes:
        name (str):
            Identifier of the foo instance.

        value (int):
            Numeric value associated with foo.

    Notes:
        Guarantees:

            - instances are immutable after creation

        Lifecycle:

            - create instance
            - pass to processing engine

    Example:
        Create and inspect a Foo:

            ```python
            foo = Foo("example", value=42)
            print(foo.name)
            ```
    '''

Complex Bar:

class BarEngine:
    '''
    Executes Foo objects through Bar stages.

    Attributes:
        foos (tuple[Foo, ...]):
            Foo instances managed by the engine.

    Notes:
        Guarantees:

            - deterministic execution order

    Example:
        Run engine:

            ```python
            foo1 = Foo("a")
            foo2 = Foo("b")

            engine = BarEngine([foo1, foo2])
            engine.run()
            ```
    '''

Function and method docstrings

Function docstrings define API contracts.

Recommended sections:

1
2
3
4
5
6
Args:
Returns:
Raises:
Yields:
Notes:
Example:
Example

Simple process method:

def process(foo: Foo, multiplier: int) -> int:
    '''
    Process a Foo instance.

    Args:
        foo (Foo):
            Foo instance to process.

        multiplier (int):
            Value used to scale foo.

    Returns:
        int:
            Processed result.

    Raises:
        ValueError:
            If multiplier is negative.

    Notes:
        Guarantees:

            - foo is not modified

    Example:
        Process foo:

            ```python
            foo = Foo("example", value=10)

            result = process(foo, multiplier=2)
            print(result)
            ```
    '''

Multiple Examples:

def combine(foo_a: Foo, foo_b: Foo) -> Foo:
    '''
    Combine two Foo instances.

    Args:
        foo_a (Foo):
            First foo.

        foo_b (Foo):
            Second foo.

    Returns:
        Foo:
            Combined foo.

    Example:
        Basic usage:

            ```python
            foo1 = Foo("a")
            foo2 = Foo("b")

            combined = combine(foo1, foo2)
            ```

        Pipeline usage:

            ```python
            engine = BarEngine([foo1, foo2])
            engine.run()
            ```
    '''

Property docstrings

Properties must document return values.

Example

Property Doc String:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
```python
@property
def foos(self) -> tuple[Foo, ...]:
    '''
    Return contained Foo instances.

    Returns:
        tuple[Foo, ...]:
            Stored foo objects.

    Example:
        ```python
        container = FooContainer()

        foos = container.foos
        ```
    '''
```

Attribute documentation

Document attributes in class docstrings using Attributes:.

Example

Attribute Doc String:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
```python
'''
Represents a processing stage.

Attributes:
    id (str):
        Unique identifier.

    enabled (bool):
        Whether the stage is active.
'''
```

Parsing guarantees

GSDFC ensures doc-forge can deterministically extract:

  • symbol kind (module, class, function, property, attribute)
  • symbol name
  • parameters
  • return values
  • attributes
  • examples
  • structured Notes subsections

This enables:

  • reliable MkDocs rendering
  • deterministic MCP export
  • accurate AI semantic interpretation

Notes
  • doc-forge never executes analyzed modules.
  • Documentation is generated entirely through static analysis.

Classes

GriffeLoader

GriffeLoader()

Load Python modules using Griffe and convert them into doc-forge models.

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.

Initialize the Griffe-backed loader.

Creates an internal Griffe loader instance with dedicated collections for modules and source lines.

Functions
load_module
load_module(path: str) -> Module

Load and convert a single Python module.

The module is introspected using Griffe and then transformed into a doc-forge Module model.

Parameters:

Name Type Description Default
path str

Dotted import path of the module.

required

Returns:

Name Type Description
Module Module

A populated Module instance.

load_project
load_project(module_paths: List[str], project_name: Optional[str] = None, skip_import_errors: bool = None) -> Project

Load multiple modules and assemble them into a Project model.

Each module path is introspected and converted into a Module instance. All modules are then aggregated into a single Project object.

Parameters:

Name Type Description Default
module_paths List[str]

List of dotted module import paths to load.

required
project_name str

Optional override for the project name. Defaults to the top-level name of the first module.

None
skip_import_errors bool

If True, modules that fail to load will be skipped instead of raising an error.

None

Returns:

Name Type Description
Project Project

A populated Project instance containing the loaded modules.

Raises:

Type Description
ValueError

If no module paths are provided.

ImportError

If a module fails to load and skip_import_errors is False.

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).

Functions
generate_sources
generate_sources(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.

Parameters:

Name Type Description Default
project Project

Documentation project model to render.

required
out_dir Path

Directory where MCP resources will be written.

required

MkDocsRenderer

Renderer that produces Markdown documentation for MkDocs.

Generated pages use mkdocstrings directives to reference Python modules, allowing MkDocs to render API documentation dynamically.

Functions
generate_readme
generate_readme(project: Project, docs_dir: Path, module_is_source: bool | None = None) -> None

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.

Parameters:

Name Type Description Default
project Project

Project model containing documentation metadata.

required
docs_dir Path

Directory containing generated documentation sources.

required
module_is_source bool

Whether the module is treated as the project source root.

None
generate_sources
generate_sources(project: Project, out_dir: Path, module_is_source: bool | None = None) -> None

Generate Markdown documentation files for a project.

This method renders a documentation structure from the provided project model and writes the resulting Markdown files to the specified output directory.

Parameters:

Name Type Description Default
project Project

Project model containing modules to document.

required
out_dir Path

Directory where generated Markdown files will be written.

required
module_is_source bool

If True, treat the specified module as the documentation root rather than nesting it inside a folder.

None

Functions

discover_module_paths

discover_module_paths(module_name: str, project_root: Path | None = None) -> List[str]

Discover Python modules within a package directory.

The function scans the filesystem for .py files inside the specified package and converts them into dotted module import paths.

Discovery rules:

  • Directories containing __init__.py are treated as packages.
  • Each .py file is treated as a module.
  • Results are returned as dotted import paths.

Parameters:

Name Type Description Default
module_name str

Top-level package name to discover modules from.

required
project_root Path

Root directory used to resolve module paths. If not provided, the current working directory is used.

None

Returns:

Type Description
List[str]

List[str]: A sorted list of unique dotted module import paths.

Raises:

Type Description
FileNotFoundError

If the specified package directory does not exist.