zensical docs skill

This commit is contained in:
John Lancaster
2026-06-19 00:24:08 -05:00
parent 07475f972f
commit 36abea5940
11 changed files with 164 additions and 44 deletions
+11 -36
View File
@@ -4,7 +4,7 @@ from typing import Any
import yaml
from fastmcp import FastMCP
from personal_mcp.skills.document_loader import load_skill_document
from personal_mcp.skills.document_loader import load_skill_document_from_metadata
catalog_server = FastMCP("catalog")
@@ -59,6 +59,10 @@ def _matches_query(pattern: dict[str, Any], query: str) -> bool:
if not lowered:
return True
query_terms = [term for term in lowered.replace("-", " ").split() if term]
if not query_terms:
return True
haystack = " ".join(
[
str(pattern.get("id", "")),
@@ -68,7 +72,7 @@ def _matches_query(pattern: dict[str, Any], query: str) -> bool:
" ".join(str(tag) for tag in pattern.get("tags", [])),
]
).lower()
return lowered in haystack
return all(term in haystack for term in query_terms)
def _matches_tags(pattern: dict[str, Any], tags: list[str] | None) -> bool:
@@ -83,34 +87,6 @@ def _matches_tags(pattern: dict[str, Any], tags: list[str] | None) -> bool:
return all(tag in pattern_tags for tag in requested)
def _resolve_skill_slug(*, skill_id: str, namespace: str, metadata: dict[str, Any]) -> str:
candidates: list[str] = []
slug = metadata.get("slug")
if isinstance(slug, str) and slug.strip():
candidates.append(slug.strip())
candidates.extend(
[
skill_id,
namespace.replace("_", "-"),
namespace,
]
)
seen: set[str] = set()
for candidate in candidates:
if candidate in seen:
continue
seen.add(candidate)
try:
load_skill_document(skill_id=skill_id, skill_slug=candidate)
return candidate
except FileNotFoundError:
continue
return skill_id
@catalog_server.resource("resource://catalog/skills_index")
def skills_index() -> dict[str, Any]:
"""Return a compact discovery index for all available pattern modules."""
@@ -184,14 +160,13 @@ def get_skill_document_by_id(skill_id: str) -> dict[str, Any]:
if pattern_id != skill_id:
continue
skill_slug = _resolve_skill_slug(
skill_id=skill_id,
namespace=namespace,
metadata=metadata,
)
return {
"found": True,
"document": load_skill_document(skill_id=skill_id, skill_slug=skill_slug),
"document": load_skill_document_from_metadata(
skill_id=skill_id,
namespace=namespace,
metadata=metadata,
),
}
return {"found": False, "id": skill_id}
+2
View File
@@ -14,6 +14,7 @@ from personal_mcp.skills.pytest_scaffolding.server import pytest_scaffolding_ser
from personal_mcp.skills.python_logging_dictconfig.server import (
python_logging_dictconfig_server,
)
from personal_mcp.skills.zensical_docs.server import zensical_docs_server
mcp = FastMCP("personal-mcp")
@@ -28,3 +29,4 @@ mcp.mount(nicegui_ui_customization_server, namespace="nicegui_ui_customization")
mcp.mount(pytest_scaffolding_server, namespace="pytest_scaffolding")
mcp.mount(python_logging_dictconfig_server, namespace="python_logging_dictconfig")
mcp.mount(fastapi_uv_docker_server, namespace="fastapi_uv_docker")
mcp.mount(zensical_docs_server, namespace="zensical_docs")
@@ -1,10 +1,45 @@
from pathlib import Path
from typing import Any
def _repo_root() -> Path:
return Path(__file__).resolve().parents[3]
def resolve_skill_document_path(
*, skill_id: str, namespace: str, metadata: dict[str, Any]
) -> Path:
"""Resolve the canonical Markdown document path for a skill."""
document_path = metadata.get("document_path")
if isinstance(document_path, str) and document_path.strip():
return _repo_root() / document_path.strip()
candidates: list[str] = []
slug = metadata.get("slug")
if isinstance(slug, str) and slug.strip():
candidates.append(slug.strip())
candidates.extend(
[
skill_id,
namespace.replace("_", "-"),
namespace,
]
)
seen: set[str] = set()
for candidate in candidates:
if candidate in seen:
continue
seen.add(candidate)
candidate_path = _repo_root() / "docs" / "skills" / candidate / "SKILL.md"
if candidate_path.exists():
return candidate_path
return _repo_root() / "docs" / "skills" / skill_id / "SKILL.md"
def load_markdown_document(*, skill_id: str, document_path: Path) -> dict[str, str]:
"""Load an arbitrary Markdown document and expose it as a skill resource."""
if not document_path.exists():
@@ -25,3 +60,15 @@ def load_skill_document(*, skill_id: str, skill_slug: str) -> dict[str, str]:
"""Load the canonical skill markdown document for an MCP skill."""
document_path = _repo_root() / "docs" / "skills" / skill_slug / "SKILL.md"
return load_markdown_document(skill_id=skill_id, document_path=document_path)
def load_skill_document_from_metadata(
*, skill_id: str, namespace: str, metadata: dict[str, Any]
) -> dict[str, str]:
"""Load a skill document using metadata overrides when present."""
document_path = resolve_skill_document_path(
skill_id=skill_id,
namespace=namespace,
metadata=metadata,
)
return load_markdown_document(skill_id=skill_id, document_path=document_path)
@@ -7,6 +7,7 @@ tags:
- scaffolding
- skills
- mcp
document_path: docs/new_skill.md
capabilities:
- resource://skills/new-skill/document
depends_on: []
+8 -4
View File
@@ -1,17 +1,21 @@
from pathlib import Path
import yaml
from fastmcp import FastMCP
from personal_mcp.skills.document_loader import load_markdown_document
from personal_mcp.skills.document_loader import load_skill_document_from_metadata
new_skill_server = FastMCP("new-skill")
_METADATA_PATH = Path(__file__).with_name("metadata.yaml")
_METADATA = yaml.safe_load(_METADATA_PATH.read_text(encoding="utf-8")) or {}
@new_skill_server.resource("resource://skills/new-skill/document")
def skill_document() -> dict[str, str]:
"""Return the bootstrap guide used to scaffold new skills."""
document_path = Path(__file__).resolve().parents[4] / "docs" / "new_skill.md"
return load_markdown_document(
return load_skill_document_from_metadata(
skill_id="new-skill",
document_path=document_path,
namespace="new_skill",
metadata=_METADATA,
)
@@ -0,0 +1 @@
"""Zensical documentation authoring skill server."""
@@ -0,0 +1,16 @@
id: zensical-docs
name: Zensical Documentation Authoring
version: 1.0.0
description: Plan, write, and improve high-quality documentation with Zensical.
tags:
- zensical
- docs
- documentation
- information-architecture
- skills
- bootstrap
- discovery
- authoring
capabilities:
- resource://skills/zensical-docs/document
depends_on: []
@@ -0,0 +1,14 @@
from fastmcp import FastMCP
from personal_mcp.skills.document_loader import load_skill_document
zensical_docs_server = FastMCP("zensical-docs")
@zensical_docs_server.resource("resource://skills/zensical-docs/document")
def skill_document() -> dict[str, str]:
"""Return the canonical Markdown document for this skill."""
return load_skill_document(
skill_id="zensical-docs",
skill_slug="zensical-docs",
)