4.1 KiB
icon
| icon |
|---|
| lucide/library |
Architecture
Overview
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.
The runtime has four content paths:
SkillsDirectoryProviderpublishes nativeskill://resources from packaged skill directories.- A custom prompt provider loads declarative prompt definitions from packaged Markdown.
- The general docs registry publishes non-skill Markdown through
resource://docs/{path*}. - FastAPI serves the pre-built
site/directory.
There is no custom skill catalog, prompt catalog, or per-prompt Python module.
Source Ownership
Skills
Each skill owns one directory:
docs/skills/<skill-id>/SKILL.mddocs/skills/<skill-id>/<supporting-path>
SkillsDirectoryProvider publishes:
skill://<name>/SKILL.mdskill://<name>/_manifestskill://<name>/{path*}
The provider parses standard skill frontmatter and generates the manifest. The general docs registry excludes skills/**, so only the native provider owns this namespace.
Prompts
Each prompt has one source: docs/prompts/<prompt-id>/PROMPT.md. Its nested prompt frontmatter owns runtime metadata and argument declarations, while its body owns canonical prose.
The custom provider reads packaged Markdown with importlib.resources, validates metadata and exact placeholder-to-argument equality, and creates native FastMCP prompt objects. It rescans on each list and get request, so an editable deployment observes file additions, edits, and deletions without a restart.
FastMCP exposes prompts through native prompts/list and prompts/get operations.
General Docs
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.
Runtime Composition
flowchart TD
A[Packaged Skill Directories] --> B[SkillsDirectoryProvider]
C[Packaged Prompt Markdown] --> D[Markdown Prompt Provider]
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
Server construction is lazy with respect to package import. Each application process creates its providers and docs snapshot when the server factory runs. Skills use startup discovery, while prompts are reloaded when a client lists or gets prompts.
Packaging
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.
Runtime reads are package-relative:
- Prompt content and general docs use
importlib.resourcesandTraversableAPIs. SkillsDirectoryProviderreceives the packagedpersonal_mcp/docs/skillsfilesystem path.- No runtime content lookup depends on the current working directory.
Public Contracts
The machine-facing surfaces are:
- Native skill resources under
skill://<name>/.... - Native MCP prompt list and get operations.
resource://docs/{path*}for general Markdown.
Canonical contracts are documented in:
Only these canonical provider and protocol surfaces are registered.
Static Documentation
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.
Validation
Changes are accepted only after:
- focused provider and protocol tests
- Ruff and ty checks
- a Zensical build
- the full pytest suite
- an installed-wheel smoke test when packaging or provider paths change