Files
prompts/src/personal_mcp/mcp.py
T
2026-08-29 20:10:30 -05:00

67 lines
2.1 KiB
Python

from __future__ import annotations
from fastmcp import FastMCP
from mcp_types import Icon
from .prompts.provider import prompt_lifespan
from .registry.load import get_docs_registry
from .registry.load import read_docs_markdown_path
from .skills import skill_lifespan
_SERVER_INSTRUCTIONS = """Personal development guidance exposed as native MCP resources and prompts.
Use prompts for parameterized workflows. For task-specific guidance, browse native skill resources,
select one skill://<name>/SKILL.md resource, and read its manifest only when supporting detail is needed.
"""
_SERVER_ICON = Icon(
src=(
"data:image/svg+xml;base64,"
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+"
"PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iOCIgZmlsbD0iIzE2N0Q4RCIvPjxwYXRoIGQ9"
"Ik0xOCAxNmgyMGw4IDh2MjRIMTh6IiBmaWxsPSJub25lIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lk"
"dGg9IjQiLz48cGF0aCBkPSJNMzggMTZ2MTBoOE0yNSAzM2gxNE0yNSA0MGgxNCIgZmlsbD0ibm9uZSIg"
"c3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI0Ii8+PC9zdmc+"
),
mime_type="image/svg+xml",
sizes=["64x64"],
)
def run_stdio() -> None:
"""Create the MCP server and expose it over stdio"""
create_mcp().run()
def create_mcp() -> FastMCP:
mcp = FastMCP(
"personal-mcp",
instructions=_SERVER_INSTRUCTIONS,
icons=[_SERVER_ICON],
on_duplicate="error",
lifespan=skill_lifespan | prompt_lifespan,
)
registry = get_docs_registry()
@mcp.resource(
"resource://docs/{path*}",
name="docs_markdown",
title="Documentation Markdown",
description="Read a packaged documentation page by its path relative to the docs root.",
mime_type="text/markdown",
tags={"docs"},
annotations={
"readOnlyHint": True,
"idempotentHint": True,
"openWorldHint": False,
},
)
def docs_markdown(path: str) -> dict[str, str]:
return read_docs_markdown_path(registry, path)
return mcp
if __name__ == "__main__":
run_stdio()