mcp-python
SKILL.md
MCP Servers in Python
Create and extend MCP servers in Python with FastMCP and the official MCP Python SDK. Based on MCP Build a server and MCP Best Practices.
When to Use
- Building or extending MCP servers in Python
- Adding tools, resources, or prompts
- Debugging MCP server connection or tool discovery
- Choosing transport (stdio vs streamable HTTP)
- Configuring clients (Claude Desktop, Cursor) to run the server
Core Concepts
- Tools: Functions callable by the LLM (with user approval). Have explicit input/output and side-effect disclosure.
- Resources: Readable data (files, API responses) the client fetches for context. URI-based.
- Prompts: Pre-written templates for specific tasks; reduce prompt drift.
- Discovery: Clients enumerate tools/resources/prompts and get schemas at connect time.
- Transports: stdio for local, per-user processes; streamable HTTP for remote, shared services.
FastMCP Quick Reference
Python 3.10+, MCP Python SDK 1.2.0+. Use uv add "mcp[cli]" or uv add fastmcp (or project may use fastmcp package).
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# ... fetch and return string
return result
@mcp.resource("config://{key}")
def get_config(key: str) -> str:
"""Get config value by key."""
return config_store.get(key, "")
@mcp.prompt()
def plan_task(goal: str, steps: int = 5) -> str:
"""Generate a step-by-step plan. Args: goal, steps (default 5)."""
return f"Plan for: {goal} in {steps} steps."
def main():
mcp.run(transport="stdio")
if __name__ == "__main__":
main()
- Tool schemas: FastMCP infers names, types, and descriptions from type hints and docstrings (Args/Returns).
- Run:
mcp.run(transport="stdio")for stdio; use streamable HTTP for remote deployment.
STDIO Critical Rule
For STDIO-based servers, never write to stdout. JSON-RPC uses stdout; any print or stdout write corrupts messages and breaks the server.
- Bad:
print("Processing"),sys.stdout.write(...) - Good:
import loggingandlogging.info(...)(logging writes to stderr by default), or log to a file.
For HTTP-based servers, stdout logging is fine.
Best Practices (Short)
- Single responsibility: One clear domain and auth boundary per server.
- Bounded toolsets: Focused tools with specific contracts; avoid kitchen-sink servers.
- Contracts first: Strict input/output schemas, explicit side effects, documented errors.
- Stateless by default: No hidden in-memory state; use external stores if needed.
- Least privilege: Precise tools; gate high-impact or destructive actions behind approval.
- Additive change: Version tool schemas; prefer additive evolution; deprecate with notice.
Scaffolding a New Server
uvx create-mcp-server
# Follow prompts; then:
cd <generated-project>
uv sync --dev --all-extras
uv run <server-module>
Client Config (stdio)
Example for Claude Desktop or Cursor MCP (stdio, using uv):
{
"mcpServers": {
"my-server": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/project", "run", "server.py"]
}
}
}
Use absolute path to the project directory. On Windows use forward slashes or escaped backslashes in JSON.
References
Weekly Installs
1
Repository
antoinebou12/uml-mcpGitHub Stars
72
First Seen
9 days ago
Security Audits
Installed on
zencoder1
amp1
cline1
openclaw1
opencode1
cursor1