migration

This commit is contained in:
John Lancaster
2026-08-07 20:07:21 -05:00
parent 2a2700b78c
commit 5b6d5aaec4
70 changed files with 1182 additions and 3633 deletions
+53 -158
View File
@@ -2,199 +2,94 @@
icon: lucide/server
---
# Static Docs Hosting Pattern
# Runtime And Static Docs Layout
## Purpose
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.
The project serves native MCP content and a pre-built documentation site from one FastAPI process. Markdown is authored once under `docs/`; runtime providers and Zensical consume that same packaged tree for different purposes.
This design intentionally avoids runtime docs rendering and avoids a separate docs hosting service.
It also treats Markdown as the single source of truth for both MCP resources and published docs.
## Completed-State Layout
## Repository Layout
```mermaid
---
config:
treeView:
rowIndent: 40
rowIndent: 32
lineThickness: 2
themeVariables:
treeView:
labelColor: '#FFFFFF'
lineColor: '#FFFFFF'
---
treeView-beta
"project-root"
"pyproject.toml"
"uv.lock"
"zensical.toml"
"docs"
"index.md"
"<project-docs>.md"
"contracts"
"index.md"
"<contract-pages>.md"
"mcp_layout.md"
"prompts"
"<prompt-id>"
"PROMPT.md"
"references"
"skills"
"<skill-id>"
"SKILL.md"
"references"
"<reference>.md"
"prompts/<prompt-id>/PROMPT.md"
"skills/<skill-id>/SKILL.md"
"skills/<skill-id>/<supporting-files>"
"<general-pages>.md"
"site"
"static build output"
"src"
"personal_mcp"
"__init__.py"
"main.py"
"mcp.py"
"catalog"
"<catalog-modules>.py"
"registry"
"<registry-modules>.py"
"web"
"<web-modules>.py"
"skills"
"<skills-modules>.py"
"src/personal_mcp"
"mcp.py"
"prompts/components/*.py"
"prompts/content.py"
"prompts/provider.py"
"registry/"
"skills/provider.py"
"web/"
```
Notes:
Ownership rules:
1. docs contains both project-authored pages and the canonical skill Markdown tree.
2. site contains static build output only.
3. docs/skills contains canonical skill Markdown and reference Markdown.
4. docs/prompts contains canonical prompt Markdown used for prompt catalog and document surfaces.
5. MCP resources and docs site read from the same Markdown sources.
1. `docs/skills/` is owned exclusively by `SkillsDirectoryProvider` at runtime.
2. `docs/prompts/` owns prompt prose; Python components own prompt metadata and argument schemas.
3. The docs registry owns only general Markdown resources and explicitly excludes skills.
4. `site/` is generated output.
5. The deleted custom `catalog/` package is not part of the runtime.
## Runtime Composition
The runtime process serves two surfaces:
1. MCP protocol surface from FastMCP
2. Static docs surface from FastAPI static mount
```mermaid
flowchart TD
A[Packaged Skill Directory] --> B[SkillsDirectoryProvider]
C[Packaged Prompts and Docs] --> D[Validated Registry]
B --> E[FastMCP Server]
D --> E
E --> F[MCP Transport]
E --> G[FastAPI Application]
G --> H[Static Mount /docs]
H --> I[Zensical Site Output]
A[Packaged Skills] --> B[SkillsDirectoryProvider]
C[Prompt Components] --> D[FileSystemProvider]
E[Packaged Markdown] --> F[Docs Registry]
B --> G[FastMCP]
D --> G
F --> G
G --> H[MCP Transport]
H --> K[FastAPI Application]
L[Pre-built site] --> M[Static /docs Mount]
K --> M
```
Runtime guarantees:
1. The skills provider and prompt/docs registry initialize before resource exposure.
2. Duplicate resource and template registration fails startup (`on_duplicate="error"`).
3. Skill resources come directly from `SkillsDirectoryProvider` directory discovery.
4. Legacy per-skill Python servers, custom skill catalogs, and metadata sidecars are not part of the runtime.
1. Providers are installed before serving requests.
2. Production provider discovery uses `reload=False`.
3. Duplicate components fail according to FastMCP's configured duplicate policy.
4. Skills and prompts use native FastMCP component surfaces.
5. General docs path parsing rejects traversal, backslashes, non-Markdown paths, and the skill namespace.
## Build and Publish Flow
## Build And Publish Flow
The docs flow is pre-build only.
1. Author Markdown under `docs/` and typed prompts under `src/personal_mcp/prompts/components/`.
2. Run `uv run zensical build` to produce `site/`.
3. Build the wheel, which packages the authored docs under `personal_mcp/docs/`.
4. Start the app and serve MCP plus the static site.
1. Read authored docs pages and skill markdown sources.
2. Build static site with Zensical into site.
3. Start app and serve site directory as static files.
No runtime Markdown-to-HTML conversion occurs.
No runtime markdown conversion is required.
## Machine-Facing Mapping
## Content Merge Pattern
1. `docs/skills/<skill-id>/SKILL.md` maps to `skill://<skill-id>/SKILL.md`.
2. Skill supporting files map to `skill://<skill-id>/<path>`.
3. Typed prompt components map to native MCP prompt names.
4. General `docs/<path>.md` maps to `resource://docs/{path*}`.
The published docs site always contains both:
The server publishes no tool projections of resources or prompts.
1. Project-authored docs pages
2. Skill Markdown content from docs/skills/*/SKILL.md and references
## Public Surface Policy
This ensures the public docs reflect architectural guidance and the exact Markdown served by MCP.
Canonical provider and protocol surfaces are the only public interfaces.
## Markdown-to-Resource Mapping
## Static Mount Expectations
MCP resources map directly to canonical Markdown documents.
Example mapping model:
1. docs/skills/<skill-id>/SKILL.md -> skill://<skill-id>/SKILL.md
2. docs/skills/<skill-id>/<path> -> skill://<skill-id>/<path>
3. docs/<path>.md -> resource://docs/{path*}
Catalog discovery resources are:
1. resource://catalog/prompts_index
2. resource://catalog/prompts_index{?q,tag,cursor,limit}
3. resource://catalog/prompts/{prompt_id}
Resource registration details:
1. `skill://<skill-id>/SKILL.md` resolves to each skill's main instructions.
2. `skill://<skill-id>/_manifest` lists every skill file with size and SHA256 hash.
3. Per-skill wildcard templates resolve validated supporting-file paths.
4. `resource://docs/{path*}` resolves normalized Markdown paths under `docs/`.
When clients cannot attach MCP resources directly, `ResourcesAsTools` exposes generic `list_resources` and `read_resource` tools over the same provider resources.
## URI Compatibility Policy
1. Canonical URIs are the only supported URIs in this runtime.
2. No backward-compatibility aliases or dual registration paths are maintained.
3. Contract changes should update clients to canonical URIs directly.
## Why This Pattern
### Operational Simplicity
One application process serves both protocol and static docs surfaces.
### Deterministic Docs
Published docs are immutable static assets for a given build.
### Documentation Fidelity
The docs site and MCP resources resolve from the same Markdown sources.
### Maintainer Experience
Authors continue to work in markdown while resource contracts remain machine-consumable.
## FastAPI Static Mount Expectations
The FastAPI app is expected to:
1. Mount static directory containing Zensical output.
2. Serve index and asset files from that directory.
3. Keep docs route stable across releases.
Recommended route conventions:
1. /docs for static site root
2. /docs/* for static assets and page routes
## Update Lifecycle
For each documentation update:
1. Edit authored docs and skill markdown content.
2. Rebuild static site.
3. Restart runtime if needed.
This keeps docs publication explicit and predictable.
## Example Source Material
Existing reference docs remain valid content inputs in this pattern:
1. docs/skills/pytesting/references/pytest-docs.md
2. docs/skills/python-logging/references/python-logging-docs.md
3. docs/skills/python-logging/references/json-file-logging.md
4. docs/skills/fastapi-uv-docker/references/fastapi-best-practices.md
These are source documents, not deployment artifacts.
The FastAPI app mounts the Zensical output, serves index and asset files, and returns a clear unavailable response when the static output is absent. The site directory is immutable for a given build and remains separate from packaged authored Markdown.