Files
prompts/src/personal_mcp/mcp.py
T

74 lines
2.4 KiB
Python

from __future__ import annotations
from fastmcp import FastMCP
from fastmcp.server.transforms import PromptsAsTools
from fastmcp.server.transforms import ResourcesAsTools
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; tool-only agents can discover and render them with
list_prompts and get_prompt. 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)
# Bridges tool-only clients that cannot browse native resources or prompts directly.
mcp.add_transform(ResourcesAsTools(mcp))
mcp.add_transform(PromptsAsTools(mcp))
return mcp
if __name__ == "__main__":
run_stdio()