docs
This commit is contained in:
@@ -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/<skill_id>/overview
|
||||||
|
2. resource://skills/<skill_id>/rules
|
||||||
|
3. resource://skills/<skill_id>/checklist
|
||||||
|
4. resource://skills/<skill_id>/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.
|
||||||
@@ -3,3 +3,8 @@ icon: lucide/rocket
|
|||||||
---
|
---
|
||||||
|
|
||||||
# Get started
|
# Get started
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- [Resource-First Pattern Module Architecture](./architecture.md)
|
||||||
|
- [Static Docs Hosting Pattern](./mcp_layout.md)
|
||||||
|
|||||||
+102
-360
@@ -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
|
## Purpose
|
||||||
* `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
|
|
||||||
|
|
||||||
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
|
```text
|
||||||
personal-mcp/
|
project-root/
|
||||||
│
|
|
|
||||||
├── pyproject.toml
|
|- pyproject.toml
|
||||||
├── uv.lock
|
|- uv.lock
|
||||||
├── README.md
|
|- zensical.toml
|
||||||
│
|
|
|
||||||
├── Dockerfile
|
|- docs/
|
||||||
├── .dockerignore
|
| |- index.md
|
||||||
│
|
| |- architecture.md
|
||||||
├── src/
|
| |- mcp_layout.md
|
||||||
│ └── personal_mcp/
|
| |- generated/
|
||||||
│
|
| |- patterns/
|
||||||
│ ├── __init__.py
|
| |- index.md
|
||||||
│ │
|
| |- pytest-scaffolding.md
|
||||||
│ ├── main.py
|
| |- python-logging-dictconfig.md
|
||||||
│ │ # Creates the root MCP server
|
| |- fastapi-uv-docker.md
|
||||||
│ │ # Mounts all skills
|
|
|
||||||
│ │
|
|- site/
|
||||||
│ ├── settings.py
|
| |- ... static files built by zensical ...
|
||||||
│ │ # Pydantic settings
|
|
|
||||||
│ │
|
|- src/
|
||||||
│ ├── graph/
|
|- personal_mcp/
|
||||||
│ │ ├── __init__.py
|
|- main.py
|
||||||
│ │ └── capability_graph.py
|
|- web/
|
||||||
│ │
|
| |- app.py
|
||||||
│ ├── catalog/
|
| |- docs_mount.py
|
||||||
│ │ ├── __init__.py
|
|- catalog/
|
||||||
│ │ ├── resources.py
|
| |- server.py
|
||||||
│ │ └── tools.py
|
|- skills/
|
||||||
│ │
|
|- pytest_scaffolding/
|
||||||
│ └── skills/
|
|- python_logging_dictconfig/
|
||||||
│
|
|- fastapi_uv_docker/
|
||||||
│ ├── __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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
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
|
The runtime process serves two surfaces:
|
||||||
from fastmcp import FastMCP
|
|
||||||
|
|
||||||
from personal_mcp.catalog.server import catalog_server
|
1. MCP protocol surface from FastMCP
|
||||||
from personal_mcp.skills.nixos.server import nixos_server
|
2. Static docs surface from FastAPI static mount
|
||||||
from personal_mcp.skills.homelab.server import homelab_server
|
|
||||||
|
|
||||||
mcp = FastMCP("Personal MCP")
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
mcp.mount(catalog_server, namespace="catalog")
|
A[FastMCP Root Server] --> B[MCP Transport]
|
||||||
mcp.mount(nixos_server, namespace="nixos")
|
A --> C[FastAPI Application]
|
||||||
mcp.mount(homelab_server, namespace="homelab")
|
C --> D[Static Mount /docs]
|
||||||
|
D --> E[Zensical site output directory]
|
||||||
if __name__ == "__main__":
|
|
||||||
mcp.run()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
## Content Merge Pattern
|
||||||
# skills/nixos/metadata.yaml
|
|
||||||
|
|
||||||
id: nixos
|
The published docs site always contains both:
|
||||||
|
|
||||||
name: NixOS Administration
|
1. Project-authored docs pages
|
||||||
|
2. Resource-derived pattern pages
|
||||||
|
|
||||||
description: |
|
This ensures the public docs reflect both architectural guidance and live pattern knowledge.
|
||||||
Tools and guidance for managing NixOS systems.
|
|
||||||
|
|
||||||
tags:
|
## Resource-to-Docs Mapping
|
||||||
- nix
|
|
||||||
- linux
|
|
||||||
- systemd
|
|
||||||
|
|
||||||
capabilities:
|
Pattern resources map directly to docs sections.
|
||||||
- package_management
|
|
||||||
- service_debugging
|
|
||||||
- flakes
|
|
||||||
|
|
||||||
depends_on:
|
Example mapping model:
|
||||||
- certificates
|
|
||||||
```
|
|
||||||
|
|
||||||
The catalog layer reads these files.
|
1. resource://skills/<id>/overview -> docs/generated/patterns/<id>.md section Overview
|
||||||
|
2. resource://skills/<id>/rules -> docs/generated/patterns/<id>.md section Rules
|
||||||
|
3. resource://skills/<id>/checklist -> docs/generated/patterns/<id>.md section Checklist
|
||||||
|
4. resource://skills/<id>/references -> docs/generated/patterns/<id>.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
|
One application process serves both protocol and static docs surfaces.
|
||||||
# skills/nixos/server.py
|
|
||||||
|
|
||||||
from fastmcp import FastMCP
|
### Deterministic Docs
|
||||||
|
|
||||||
nixos_server = FastMCP(
|
Published docs are immutable static assets for a given build.
|
||||||
"NixOS"
|
|
||||||
)
|
|
||||||
|
|
||||||
from .tools.rebuild import *
|
### Documentation Fidelity
|
||||||
from .resources.overview import *
|
|
||||||
from .prompts.expert import *
|
|
||||||
```
|
|
||||||
|
|
||||||
The pattern is:
|
Resource-derived pages align docs with the exact methodology contracts exposed to agents.
|
||||||
|
|
||||||
```text
|
### Maintainer Experience
|
||||||
One skill
|
|
||||||
=
|
|
||||||
One FastMCP server
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
Recommended route conventions:
|
||||||
# resources/overview.py
|
|
||||||
|
|
||||||
from .server import nixos_server
|
1. /docs for static site root
|
||||||
|
2. /docs/* for static assets and page routes
|
||||||
|
|
||||||
|
## Update Lifecycle
|
||||||
|
|
||||||
@nixos_server.resource(
|
For each documentation update:
|
||||||
"resource://skills/nixos"
|
|
||||||
)
|
|
||||||
def nixos_skill_description():
|
|
||||||
return """
|
|
||||||
NixOS administration skill.
|
|
||||||
|
|
||||||
Provides:
|
1. Edit authored markdown and resource content.
|
||||||
- flake troubleshooting
|
2. Regenerate docs markdown from resources.
|
||||||
- package search
|
3. Rebuild static site.
|
||||||
- service diagnostics
|
4. Restart runtime if needed.
|
||||||
- generation management
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
1. ../skills/pytest-scaffolding/references/pytest-docs.md
|
||||||
# prompts/expert.py
|
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
|
These are source documents, not deployment artifacts.
|
||||||
|
|
||||||
|
|
||||||
@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"
|
|
||||||
|
|||||||
Reference in New Issue
Block a user