From c915c1846d695c9f5ad4baf4289483c76ce1afa6 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Thu, 18 Jun 2026 20:01:47 -0500 Subject: [PATCH] docs --- docs/architecture.md | 172 ++++++++++++++++ docs/index.md | 5 + docs/mcp_layout.md | 462 ++++++++++--------------------------------- 3 files changed, 279 insertions(+), 360 deletions(-) create mode 100644 docs/architecture.md diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..0e8844f --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,172 @@ +--- +icon: lucide/library +--- + +# Resource-First Pattern Module Architecture + +## Overview + +The platform is implemented as a resource-first MCP system with an integrated static documentation surface. The same methodology content powers both MCP resources and the published docs site. + +The system is complete in four layers: + +1. Pattern modules expose methodology as MCP resources. +2. Catalog resources provide normalized discovery. +3. A docs export step materializes resource content into markdown. +4. Zensical builds a static site that is served by the FastAPI app in the FastMCP runtime process. + +This architecture keeps authored content human-friendly while preserving machine-stable contracts. + +## Intent + +The architecture is designed to satisfy three long-term requirements: + +1. Methodology must be editable as markdown by humans. +2. Agents must consume stable, discoverable resource contracts. +3. Public documentation must be pre-built static output served from the application runtime without a separate docs service. + +## System Model + +### Pattern Modules + +Each module encapsulates one methodology domain and publishes resource families: + +1. overview +2. rules +3. checklist +4. references + +Tools are intentionally narrow and optional. They exist only for deterministic export-like behavior. + +### Catalog Module + +The catalog is the canonical discovery layer and publishes normalized records for all modules. + +Typical catalog resources: + +1. resource://catalog/patterns +2. resource://catalog/patterns_by_id +3. resource://catalog/skills_index +4. resource://catalog/skills_details + +### Content Sources + +Content is authored in markdown and managed as long-form reference material. Resource handlers load authored content and expose it through stable resource URIs. + +### Static Docs Surface + +Static docs are generated from two merged content streams: + +1. Project-authored docs pages +2. Generated pages derived from MCP resources + +The merged docs tree is built by Zensical into static files and served by the FastAPI app. + +## Data Flow + +```mermaid +flowchart TD + A[Authored Markdown] --> C[Resource Handlers] + B[Pattern Metadata] --> D[Catalog Resources] + C --> E[Docs Export Step] + D --> E + E --> F[Generated Docs Markdown] + F --> G[Zensical Static Build] + G --> H[FastAPI Static Mount] + H --> I[Served Docs Site] +``` + +## Contracts + +### Metadata Contract + +Each pattern module declares: + +1. id +2. name +3. version +4. description +5. tags +6. capabilities +7. depends_on + +### URI Contract + +Module resource URIs are stable and follow: + +1. resource://skills//overview +2. resource://skills//rules +3. resource://skills//checklist +4. resource://skills//references + +Catalog resource URIs are stable and discovery-focused. + +### Versioning Rule + +Published URIs are immutable. Behavioral or schema changes are versioned in metadata and documented through additive migration notes. + +## Static Hosting Pattern + +The docs site is pre-built and served by the same FastAPI runtime process used by the MCP app. + +Runtime behavior: + +1. App starts. +2. FastAPI mounts the static docs output directory. +3. Requests to docs paths are served as static assets. + +This provides a single deployment artifact with no runtime markdown rendering dependency. + +## Advantages + +### Single Source of Truth + +Methodology is authored once and reused in both MCP resources and docs pages. + +### High-Fidelity Agent Context + +Resources expose explicit, attachable context for accurate implementation behavior. + +### Operational Simplicity + +A single app process serves MCP and docs surfaces. + +### Long-Term Maintainability + +Markdown remains easy to review, while contracts remain stable for clients. + +### Client Independence + +Clients can use Ask, Edit, or Agent modes without requiring server-owned prompt orchestration. + +## Authoring and Publishing Lifecycle + +1. Update markdown reference content. +2. Update metadata if capability surface changes. +3. Run resource export to generated docs markdown. +4. Build static docs with Zensical. +5. Serve built output through FastAPI static mount. + +## Scope and Non-Goals + +In-scope: + +1. Resource-first methodology delivery +2. Catalog-based discovery +3. Pre-built static docs hosting in app runtime + +Out-of-scope: + +1. Prompt-first orchestration as the primary interface +2. Large tool inventories duplicating static guidance +3. Separate dynamic docs service at runtime + +## Example Content Inputs + +Existing markdown reference sets are valid examples of authored source material for this architecture: + +1. ../skills/pytest-scaffolding/references/pytest-docs.md +2. ../skills/python-logging-dictconfig/references/python-logging-docs.md +3. ../skills/fastapi-uv-docker/references/fastapi-best-practices.md + +These inputs are treated as content sources, while resource URIs and catalog payloads remain the machine-facing contracts. diff --git a/docs/index.md b/docs/index.md index d79e3d8..7d75c90 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,3 +3,8 @@ icon: lucide/rocket --- # Get started + +## Architecture + +- [Resource-First Pattern Module Architecture](./architecture.md) +- [Static Docs Hosting Pattern](./mcp_layout.md) diff --git a/docs/mcp_layout.md b/docs/mcp_layout.md index 2b7fe03..606c2b7 100644 --- a/docs/mcp_layout.md +++ b/docs/mcp_layout.md @@ -1,408 +1,150 @@ -For a modern Python project in 2026, I would treat the MCP server exactly like any other deployable service: +# Static Docs Hosting Pattern -* `src/` layout -* `uv` for dependency management -* skill modules as importable Python packages -* FastMCP composition via `mount()` -* Docker image built from the root package -* resources/prompts kept close to the skill that owns them -* avoid giant decorator files with hundreds of tools +## Purpose -FastMCP's mounting/composition model is specifically intended for this sort of modular organization. ([FastMCP][1]) +This document describes the completed layout and runtime pattern used to host a pre-built static documentation site from the same FastAPI app process that runs the FastMCP server. -I'd structure it something like: +This design intentionally avoids runtime docs rendering and avoids a separate docs hosting service. + +## Completed-State Layout ```text -personal-mcp/ -│ -├── pyproject.toml -├── uv.lock -├── README.md -│ -├── Dockerfile -├── .dockerignore -│ -├── src/ -│ └── personal_mcp/ -│ -│ ├── __init__.py -│ │ -│ ├── main.py -│ │ # Creates the root MCP server -│ │ # Mounts all skills -│ │ -│ ├── settings.py -│ │ # Pydantic settings -│ │ -│ ├── graph/ -│ │ ├── __init__.py -│ │ └── capability_graph.py -│ │ -│ ├── catalog/ -│ │ ├── __init__.py -│ │ ├── resources.py -│ │ └── tools.py -│ │ -│ └── skills/ -│ -│ ├── __init__.py -│ │ -│ ├── nixos/ -│ │ -│ │ ├── __init__.py -│ │ ├── server.py -│ │ │ -│ │ ├── tools/ -│ │ │ └── rebuild.py -│ │ │ -│ │ ├── prompts/ -│ │ │ └── expert.py -│ │ │ -│ │ ├── resources/ -│ │ │ ├── overview.py -│ │ │ └── troubleshooting.py -│ │ │ -│ │ └── metadata.yaml -│ │ -│ ├── homelab/ -│ │ -│ │ ├── __init__.py -│ │ ├── server.py -│ │ ├── tools/ -│ │ ├── prompts/ -│ │ ├── resources/ -│ │ └── metadata.yaml -│ │ -│ └── knowledge_base/ -│ ├── __init__.py -│ ├── server.py -│ ├── tools/ -│ ├── prompts/ -│ ├── resources/ -│ └── metadata.yaml -│ -└── tests/ - ├── test_catalog.py - ├── test_nixos.py - └── test_homelab.py +project-root/ +| +|- pyproject.toml +|- uv.lock +|- zensical.toml +| +|- docs/ +| |- index.md +| |- architecture.md +| |- mcp_layout.md +| |- generated/ +| |- patterns/ +| |- index.md +| |- pytest-scaffolding.md +| |- python-logging-dictconfig.md +| |- fastapi-uv-docker.md +| +|- site/ +| |- ... static files built by zensical ... +| +|- src/ + |- personal_mcp/ + |- main.py + |- web/ + | |- app.py + | |- docs_mount.py + |- catalog/ + | |- server.py + |- skills/ + |- pytest_scaffolding/ + |- python_logging_dictconfig/ + |- fastapi_uv_docker/ ``` ---- +Notes: -## main.py +1. docs contains authored pages and generated markdown pages. +2. site contains static build output only. +3. MCP resources and docs generation share the same content contract. -This is intentionally boring. +## Runtime Composition -```python -from fastmcp import FastMCP +The runtime process serves two surfaces: -from personal_mcp.catalog.server import catalog_server -from personal_mcp.skills.nixos.server import nixos_server -from personal_mcp.skills.homelab.server import homelab_server +1. MCP protocol surface from FastMCP +2. Static docs surface from FastAPI static mount -mcp = FastMCP("Personal MCP") - -mcp.mount(catalog_server, namespace="catalog") -mcp.mount(nixos_server, namespace="nixos") -mcp.mount(homelab_server, namespace="homelab") - -if __name__ == "__main__": - mcp.run() +```mermaid +flowchart TD + A[FastMCP Root Server] --> B[MCP Transport] + A --> C[FastAPI Application] + C --> D[Static Mount /docs] + D --> E[Zensical site output directory] ``` -FastMCP namespaces resources, prompts, and tools automatically when mounted. ([FastMCP][2]) +## Build and Publish Flow ---- +The docs flow is pre-build only. -## Skill Metadata +1. Read module resources and catalog metadata. +2. Generate docs markdown pages into docs/generated. +3. Build static site with Zensical into site. +4. Start app and serve site directory as static files. -Every skill gets metadata. +No runtime markdown conversion is required. -```yaml -# skills/nixos/metadata.yaml +## Content Merge Pattern -id: nixos +The published docs site always contains both: -name: NixOS Administration +1. Project-authored docs pages +2. Resource-derived pattern pages -description: | - Tools and guidance for managing NixOS systems. +This ensures the public docs reflect both architectural guidance and live pattern knowledge. -tags: - - nix - - linux - - systemd +## Resource-to-Docs Mapping -capabilities: - - package_management - - service_debugging - - flakes +Pattern resources map directly to docs sections. -depends_on: - - certificates -``` +Example mapping model: -The catalog layer reads these files. +1. resource://skills//overview -> docs/generated/patterns/.md section Overview +2. resource://skills//rules -> docs/generated/patterns/.md section Rules +3. resource://skills//checklist -> docs/generated/patterns/.md section Checklist +4. resource://skills//references -> docs/generated/patterns/.md section References ---- +Catalog resources generate index pages and navigation pages. -## Skill Server +## Why This Pattern -Each skill owns its own MCP instance. +### Operational Simplicity -```python -# skills/nixos/server.py +One application process serves both protocol and static docs surfaces. -from fastmcp import FastMCP +### Deterministic Docs -nixos_server = FastMCP( - "NixOS" -) +Published docs are immutable static assets for a given build. -from .tools.rebuild import * -from .resources.overview import * -from .prompts.expert import * -``` +### Documentation Fidelity -The pattern is: +Resource-derived pages align docs with the exact methodology contracts exposed to agents. -```text -One skill -= -One FastMCP server -``` +### Maintainer Experience -This keeps ownership obvious. +Authors continue to work in markdown while resource contracts remain machine-consumable. ---- +## FastAPI Static Mount Expectations -## Skill Resource +The FastAPI app is expected to: -Resources are your discovery layer. +1. Mount static directory containing Zensical output. +2. Serve index and asset files from that directory. +3. Keep docs route stable across releases. -```python -# resources/overview.py +Recommended route conventions: -from .server import nixos_server +1. /docs for static site root +2. /docs/* for static assets and page routes +## Update Lifecycle -@nixos_server.resource( - "resource://skills/nixos" -) -def nixos_skill_description(): - return """ - NixOS administration skill. +For each documentation update: - Provides: - - flake troubleshooting - - package search - - service diagnostics - - generation management - """ -``` +1. Edit authored markdown and resource content. +2. Regenerate docs markdown from resources. +3. Rebuild static site. +4. Restart runtime if needed. -Resources are exactly what MCP intends for exposing contextual information and data to clients. ([fastmcp.mintlify.app][3]) +This keeps docs publication explicit and predictable. ---- +## Example Source Material -## Skill Prompt +Existing reference docs remain valid content inputs in this pattern: -```python -# prompts/expert.py +1. ../skills/pytest-scaffolding/references/pytest-docs.md +2. ../skills/python-logging-dictconfig/references/python-logging-docs.md +3. ../skills/fastapi-uv-docker/references/fastapi-best-practices.md -from .server import nixos_server - - -@nixos_server.prompt -def nixos_expert(): - return """ - Act as an expert NixOS administrator. - - Prefer: - - flakes - - declarative configuration - - modern systemd patterns - - Avoid: - - imperative package management - """ -``` - ---- - -## Skill Tool - -```python -# tools/rebuild.py - -from .server import nixos_server - - -@nixos_server.tool -def explain_rebuild(): - """ - Explain a nixos-rebuild failure. - """ - - return { - "workflow": [ - "Inspect journal", - "Check evaluation errors", - "Verify inputs", - "Retry build" - ] - } -``` - ---- - -## Catalog Layer - -The catalog should be its own server. - -Not a skill. - -Its job is discovery. - -```python -catalog/ -├── server.py -├── tools.py -└── resources.py -``` - -Example: - -```python -# catalog/tools.py - -@catalog_server.tool -def list_skills(): - - return [ - "nixos", - "homelab", - "knowledge_base" - ] -``` - -```python -@catalog_server.tool -def describe_skill( - name: str -): - ... -``` - ---- - -## Capability Graph - -This is where NetworkX belongs. - -```python -# graph/capability_graph.py - -import networkx as nx - -graph = nx.DiGraph() - -graph.add_edge( - "homelab", - "certificates", - relation="depends_on" -) - -graph.add_edge( - "nixos", - "homelab", - relation="manages" -) -``` - -Expose it as: - -```python -resource://skills/graph -resource://skills/nixos/dependencies -``` - -Now agents can discover related capabilities without hardcoding them. - ---- - -## pyproject.toml - -Minimal UV setup: - -```toml -[project] -name = "personal-mcp" -version = "0.1.0" - -dependencies = [ - "fastmcp", - "networkx", - "pydantic-settings", - "pyyaml", -] - -[project.scripts] -personal-mcp = "personal_mcp.main:mcp" -``` - ---- - -## Docker - -```dockerfile -FROM python:3.13-slim - -WORKDIR /app - -COPY pyproject.toml uv.lock ./ - -RUN pip install uv -RUN uv sync --frozen - -COPY src ./src - -CMD ["uv", "run", "python", "-m", "personal_mcp.main"] -``` - ---- - -If I were building this for long-term growth, I'd make one additional change: treat every skill as a Python package with a common interface: - -```python -class Skill: - id: str - metadata: SkillMetadata - - def create_server(self) -> FastMCP: - ... -``` - -Then `main.py` simply discovers skills dynamically: - -```python -for skill in discover_skills(): - mcp.mount( - skill.create_server(), - namespace=skill.id, - ) -``` - -At that point adding a new skill becomes: - -```text -mkdir skills/new_skill -drop in metadata.yaml -implement Skill -``` - -and the server automatically exposes it. That's the closest thing to a plugin architecture while still remaining very Pythonic and Docker-friendly. - -[1]: https://fastmcp.wiki/en/servers/composition?utm_source=chatgpt.com "Server Composition - FastMCP" -[2]: https://gofastmcp.com/servers/composition?utm_source=chatgpt.com "Composing Servers - FastMCP" -[3]: https://fastmcp.mintlify.app/servers/resources?utm_source=chatgpt.com "Resources & Templates - FastMCP" +These are source documents, not deployment artifacts.