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
+62 -207
View File
@@ -6,249 +6,104 @@ icon: lucide/library
## 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 application combines a FastMCP server with a pre-built Zensical documentation site. Markdown under `docs/` is the single authored content tree, while native FastMCP providers own skill and prompt discovery.
An MCP server is a runtime that exposes machine-readable resources and tools through stable interfaces so AI clients can discover and consume context consistently. Here, the server's role is intentionally narrow: publish canonical methodology documents as resources, keep discovery predictable through a catalog layer, and serve the same source material as pre-built static documentation.
The runtime has four content paths:
The system is complete in three layers:
1. `SkillsDirectoryProvider` publishes native `skill://` resources from packaged skill directories.
2. `FileSystemProvider` discovers typed `@prompt` functions from packaged Python modules.
3. The general docs registry publishes non-skill Markdown through `resource://docs/{path*}`.
4. FastAPI serves the pre-built `site/` directory.
1. Canonical methodology is maintained in Markdown skill documents.
2. Catalog resources provide normalized discovery.
3. Zensical builds a static site from those same Markdown sources and the FastAPI app serves it in the FastMCP runtime process.
There is no custom skill catalog, prompt catalog, or prompt registry model.
Prompt documents under `docs/prompts/` are also indexed and exposed as first-class catalog and prompt surfaces.
## Source Ownership
This architecture is anchored by three contracts:
### Skills
1. Docs-first authored content contract under `docs/` with strict per-skill ownership.
2. Standard `SKILL.md` frontmatter consumed directly by FastMCP.
3. Native `skill://` resource URIs with break-and-replace policy for contract changes.
Detailed contract pages:
1. [Content Contract](./contracts/index.md#content-contract)
2. [Frontmatter Contract](./contracts/frontmatter.md)
3. [URI Contract](./contracts/uris.md)
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, with a minimal read-only catalog tool fallback for constrained clients.
3. Public documentation must be pre-built static output served from the application runtime without a separate docs service.
## System Model
### Pattern Modules
Each skill encapsulates one methodology domain in a docs-owned directory:
Each skill owns one directory:
1. `docs/skills/<skill-id>/SKILL.md`
2. `docs/skills/<skill-id>/references/...`
2. `docs/skills/<skill-id>/<supporting-path>`
The skill document and references are the authored source of truth; runtime code indexes and serves these files without becoming a second authored source.
`SkillsDirectoryProvider` publishes:
Each skill publishes three native resource families:
1. `skill://<name>/SKILL.md`
2. `skill://<name>/_manifest`
3. `skill://<name>/{path*}`
1. `skill://<name>/SKILL.md` for primary instructions
2. `skill://<name>/_manifest` for file discovery and integrity metadata
3. `skill://<name>/{path*}` for supporting files
The provider parses standard skill frontmatter and generates the manifest. The general docs registry excludes `skills/**`, so only the native provider owns this namespace.
The main resource returns canonical Markdown. The generated manifest lists real relative paths, sizes, and SHA256 hashes so clients can load supporting material selectively.
### Prompts
### Prompt Modules
Each prompt has two coordinated sources:
Prompt guidance can be authored in `docs/prompts/` using either canonical prompt directories (`docs/prompts/<prompt-id>/PROMPT.md`) or legacy markdown files during migration.
1. `src/personal_mcp/prompts/components/<module>.py` owns the typed signature and runtime metadata.
2. `docs/prompts/<prompt-id>/PROMPT.md` owns the canonical prompt prose.
Prompt modules publish two additive surfaces:
The component loads Markdown with `importlib.resources`. The renderer strips documentation frontmatter, requires exact placeholder-to-argument equality, and substitutes typed values. `FileSystemProvider(reload=False)` discovers the components during server construction.
1. prompt resources for catalog and document retrieval
2. MCP prompt objects for prompt-list/get-prompt style client workflows
FastMCP exposes prompts through native `prompts/list` and `prompts/get` operations.
This keeps authored markdown as source-of-truth while allowing clients to discover and invoke prompts directly.
### General Docs
### Catalog Module
The docs registry indexes packaged Markdown for `resource://docs/{path*}`. It rejects `skills/**` because skills are provider-owned. Prompt Markdown can remain visible as general documentation, but prompt invocation is owned by the native prompt provider.
The catalog publishes normalized records for prompts. Skills use FastMCP's native resource discovery and client utilities instead of a parallel catalog.
Typical catalog resources:
1. resource://catalog/prompts_index
2. resource://catalog/prompts_index{?q,tag,cursor,limit}
3. resource://catalog/prompts/{prompt_id}
Only canonical catalog resources are part of the runtime contract in this phase.
### Registry Loader
Importing the package does not read or parse documentation. The MCP server and FastAPI application factories initialize content when constructing a runnable server. The prompt/docs registry reads packaged resources through `importlib.resources.files(...)` and `Traversable` APIs; the native skills provider receives the packaged `personal_mcp/docs/skills` filesystem path.
Loader responsibilities:
1. Parse and validate prompt frontmatter.
2. Build the prompt catalog and MCP prompt objects.
3. Index authored Markdown for `resource://docs/{path*}`.
Skill loading is owned by `SkillsDirectoryProvider`, which scans the packaged skills directory and constructs native resources before the server starts serving requests.
The immutable registry is cached for the process lifetime. Each Uvicorn worker constructs and retains its own registry because worker processes do not share Python objects. Registry load failure is a server-factory startup error, not a package-import error or partial runtime warning.
### Content Sources
Content is authored in markdown under `docs/` and managed as long-form reference material. Skill documents and companion references now live under `docs/skills/`, while project-authored pages remain alongside them in the docs tree. Resource handlers expose the same authored documents through stable resource URIs.
The repository root `docs/` directory is the only authored source. The `src/personal_mcp/docs` path is a relative symlink to that directory for source-checkout and editable-install workflows; it is not a second content tree and packaging does not depend on traversing it.
For wheel builds, Hatchling's normal `src/personal_mcp` package traversal follows the relative `docs` symlink and archives its targets as regular files under `personal_mcp/docs/`. No `force-include` mapping is used because that would add the same archive paths twice. The prompt/docs registry uses [`importlib.resources.files`](https://docs.python.org/3/library/importlib.resources.html#importlib.resources.files), while `SkillsDirectoryProvider` scans the package-relative filesystem path. Neither path depends on the current working directory.
### Static Docs Surface
Static docs are built directly from two markdown source streams:
1. Project-authored docs pages
2. Skill and reference markdown pages
The merged docs tree is built by Zensical into static files and served by the FastAPI app.
Generated `site/` files are deployment assets for the human-facing static site. They are separate from the authored Markdown resources packaged under `personal_mcp/docs/`.
## Data Flow
## Runtime Composition
```mermaid
flowchart TD
A[Authored Skill Directories] --> B[SkillsDirectoryProvider]
B --> C[Native Skill Resources]
D[Authored Prompts and Docs] --> E[Prompt and Docs Registry]
E --> F[Prompt Catalog and Docs Resources]
A --> G[Zensical Static Build]
D --> G
G --> H[FastAPI Static Mount]
A[Packaged Skill Directories] --> B[SkillsDirectoryProvider]
C[Typed Prompt Components] --> D[FileSystemProvider]
E[Packaged Prompt Markdown] --> C
F[General Markdown] --> G[Docs Registry]
B --> H[FastMCP Server]
D --> H
G --> H
H --> K[MCP Transport]
L[Zensical Site Output] --> M[FastAPI Static Mount]
K --> M
```
## Contracts
Server construction is lazy with respect to package import. Each application process creates its providers and docs snapshot when the server factory runs. Production providers use `reload=False`; content changes require a process restart.
### Metadata Contract
## Packaging
Each skill declares standard frontmatter in `docs/skills/<skill-id>/SKILL.md`.
The repository root `docs/` directory is the only authored Markdown source. `src/personal_mcp/docs` is a relative symlink used by source checkouts and editable installs. Hatchling follows it and stores regular files beneath `personal_mcp/docs/` in the wheel.
For the full field-level contract, validation model, and FastMCP metadata mapping, see [Frontmatter Contract](./contracts/frontmatter.md).
Runtime reads are package-relative:
Required fields:
1. Prompt content and general docs use `importlib.resources` and `Traversable` APIs.
2. `SkillsDirectoryProvider` receives the packaged `personal_mcp/docs/skills` filesystem path.
3. No runtime content lookup depends on the current working directory.
1. name
2. description
## Public Contracts
The directory name is the provider identity and must match `name`. There is no skill catalog metadata or sidecar.
The machine-facing surfaces are:
### URI Contract
1. Native skill resources under `skill://<name>/...`.
2. Native MCP prompt list and get operations.
3. `resource://docs/{path*}` for general Markdown.
Canonical resource URIs are:
Canonical contracts are documented in:
For the full URI semantics, parameter validation rules, and compatibility policy, see [URI Contract](./contracts/uris.md).
1. [Prompt Contract](./contracts/prompt.md)
2. [Skill Contract](./contracts/skill_contract.md)
3. [Frontmatter Contract](./contracts/frontmatter.md)
4. [URI Contract](./contracts/uris.md)
1. skill://<skill_name>/SKILL.md
2. skill://<skill_name>/_manifest
3. skill://<skill_name>/<supporting_path>
4. resource://docs/{path*}
5. resource://catalog/prompts_index
6. resource://catalog/prompts_index{?q,tag,cursor,limit}
7. resource://catalog/prompts/{prompt_id}
8. resource://prompts/{prompt_id}/document
Only these canonical provider and protocol surfaces are registered.
Validation rules:
## Static Documentation
1. `skill_name` is the lowercase kebab-case skill directory name.
2. `supporting_path` is a provider-validated relative path within that skill.
3. Docs `path*` resolves only to normalized Markdown paths under `docs/`.
Zensical builds `docs/` into `site/` before deployment. FastAPI mounts that immutable output in the same process that hosts FastMCP. Generated `site/` files are deployment assets and are never an authored source.
### Resource Registration Contract
## Validation
Skill resources are registered by one `SkillsDirectoryProvider`; prompt and docs resources remain registered from the validated registry.
Changes are accepted only after:
Registration rules:
1. Use RFC6570 URI templates where appropriate.
2. Mark documentation resources as read-only and idempotent.
3. Set explicit mime types for resource responses.
4. Configure duplicate URI handling with `on_duplicate="error"` for startup safety.
This keeps runtime behavior deterministic and prevents accidental URI collisions.
### Versioning Rule
URIs are unversioned and canonical in this phase.
1. Breaking URI changes are handled as direct replacement.
2. No compatibility aliases or dual URI families are maintained.
## 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 the same canonical Markdown that humans author and review.
### 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 prompt-first orchestration. Prompt objects are available as an additive MCP surface, while resource retrieval remains the canonical source path. MCP affordances are still chat-surface-dependent: some clients or sessions expose resource attachment directly, while others make tool invocation the more reliable retrieval path.
## Authoring and Publishing Lifecycle
1. Update markdown reference content.
2. Keep skill `name` and directory identity aligned.
3. Build static docs with Zensical and run provider tests.
4. Package authored docs into `personal_mcp/docs/`.
5. Serve native MCP resources and the static docs mount.
## Scope and Non-Goals
In-scope:
1. Resource-first methodology delivery
2. Native FastMCP skill 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 across skill modules
3. Separate dynamic docs service at runtime
The prompt catalog remains an independent surface. Tool-only skill clients use generic resource tools rather than a skill-specific compatibility layer.
## Example Content Inputs
Existing markdown reference sets are valid examples of authored source material for this architecture:
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 inputs are treated as content sources, while native skill URIs and generated manifests form the machine-facing skill contract.
1. focused provider and protocol tests
2. Ruff and ty checks
3. a Zensical build
4. the full pytest suite
5. an installed-wheel smoke test when packaging or provider paths change