.claude/skills.nouse/python-mcp-server/SKILL.md
Instructions for building Model Context Protocol (MCP) servers using the Python SDK. Provides patterns, best practices, and code examples for FastMCP, tools, resources, prompts, and transports.
npx skillsauth add taewook486/real-estate-mcp python-mcp-serverInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
uv init mcp-server-demo and uv add "mcp[cli]"mcp.server.fastmcp: from mcp.server.fastmcp import FastMCP@mcp.tool(), @mcp.resource(), and @mcp.prompt() decorators for registrationmcp.run() or mcp.run(transport="stdio")mcp.run(transport="streamable-http") or mount to Starlette/FastAPIContext parameter in tools/resources to access MCP capabilities: ctx: Contextawait ctx.debug(), await ctx.info(), await ctx.warning(), await ctx.error()await ctx.report_progress(progress, total, message)await ctx.elicit(message, schema)await ctx.session.create_message(messages, max_tokens)Icon(src="path", mimeType="image/png") for server, tools, resources, promptsImage class for automatic image handling: return Image(data=bytes, format="png")@mcp.resource("greeting://{name}")ctx.request_context.lifespan_contextstateless_http=True in FastMCP initializationjson_response=Trueuv run mcp dev server.py (Inspector) or uv run mcp install server.py (Claude Desktop)Mount("/path", mcp.streamable_http_app())Mcp-Session-Id headerfrom mcp.server.fastmcp import FastMCP
mcp = FastMCP("My Server")
@mcp.tool()
def calculate(a: int, b: int, op: str) -> int:
"""Perform calculation"""
if op == "add":
return a + b
return a - b
if __name__ == "__main__":
mcp.run() # stdio by default
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("My HTTP Server")
@mcp.tool()
def hello(name: str = "World") -> str:
"""Greet someone"""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run(transport="streamable-http")
from pydantic import BaseModel, Field
class WeatherData(BaseModel):
temperature: float = Field(description="Temperature in Celsius")
condition: str
humidity: float
@mcp.tool()
def get_weather(city: str) -> WeatherData:
"""Get weather for a city"""
return WeatherData(
temperature=22.5,
condition="sunny",
humidity=65.0
)
@mcp.resource("users://{user_id}")
def get_user(user_id: str) -> str:
"""Get user profile data"""
return f"User {user_id} profile data"
from mcp.server.fastmcp import Context
from mcp.server.session import ServerSession
@mcp.tool()
async def process_data(
data: str,
ctx: Context[ServerSession, None]
) -> str:
"""Process data with logging"""
await ctx.info(f"Processing: {data}")
await ctx.report_progress(0.5, 1.0, "Halfway done")
return f"Processed: {data}"
from mcp.server.fastmcp import Context
from mcp.server.session import ServerSession
from mcp.types import SamplingMessage, TextContent
@mcp.tool()
async def summarize(
text: str,
ctx: Context[ServerSession, None]
) -> str:
"""Summarize text using LLM"""
result = await ctx.session.create_message(
messages=[SamplingMessage(
role="user",
content=TextContent(type="text", text=f"Summarize: {text}")
)],
max_tokens=100
)
return result.content.text if result.content.type == "text" else ""
from contextlib import asynccontextmanager
from dataclasses import dataclass
from mcp.server.fastmcp import FastMCP, Context
@dataclass
class AppContext:
db: Database
@asynccontextmanager
async def app_lifespan(server: FastMCP):
db = await Database.connect()
try:
yield AppContext(db=db)
finally:
await db.disconnect()
mcp = FastMCP("My App", lifespan=app_lifespan)
@mcp.tool()
def query(sql: str, ctx: Context) -> str:
"""Query database"""
db = ctx.request_context.lifespan_context.db
return db.execute(sql)
from mcp.server.fastmcp.prompts import base
@mcp.prompt(title="Code Review")
def review_code(code: str) -> list[base.Message]:
"""Create code review prompt"""
return [
base.UserMessage("Review this code:"),
base.UserMessage(code),
base.AssistantMessage("I'll review the code for you.")
]
@mcp.tool()
async def risky_operation(input: str) -> str:
"""Operation that might fail"""
try:
result = await perform_operation(input)
return f"Success: {result}"
except Exception as e:
return f"Error: {str(e)}"
testing
--- name: worklog description: Update worklog files by moving tasks between todo/doing/done states. Use when recording task progress, starting new work, or marking tasks complete. Requires explicit arguments: worklog [done|doing|todo] [description]. --- # Worklog Update task state in worklog files. Requires explicit arguments. ## Worklog Files - `localdocs/worklog.todo.md` — backlog - `localdocs/worklog.doing.md` — in progress - `localdocs/worklog.done.md` — completed (grouped by date, appen
development
Test-Driven Development workflow. Use for ALL code changes - features, bug fixes, refactoring. TDD is non-negotiable.
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
development
Refactoring assessment and patterns. Use after tests pass (GREEN phase) to assess improvement opportunities.