1# mcp 2 3MCP (Model Context Protocol) lets you build tools that LLMs can use. fastmcp makes this straightforward. 4 5## what MCP is 6 7MCP servers expose: 8- **tools** - functions LLMs can call (actions, side effects) 9- **resources** - read-only data (like GET endpoints) 10- **prompts** - reusable message templates 11 12clients (like Claude) discover and call these over stdio or HTTP. 13 14## basic server 15 16```python 17from fastmcp import FastMCP 18 19mcp = FastMCP("my-server") 20 21@mcp.tool 22def add(a: int, b: int) -> int: 23 """Add two numbers.""" 24 return a + b 25 26@mcp.resource("config://version") 27def get_version() -> str: 28 return "1.0.0" 29 30if __name__ == "__main__": 31 mcp.run() 32``` 33 34fastmcp generates JSON schemas from type hints and docstrings automatically. 35 36## running 37 38```bash 39# stdio (default, for local tools) 40python server.py 41 42# http (for deployment) 43fastmcp run server.py --transport http --port 8000 44``` 45 46## tools vs resources 47 48**tools** do things: 49```python 50@mcp.tool 51async def create_post(text: str) -> dict: 52 """Create a new post.""" 53 return await api.create(text) 54``` 55 56**resources** read things: 57```python 58@mcp.resource("posts://{post_id}") 59async def get_post(post_id: str) -> dict: 60 """Get a post by ID.""" 61 return await api.get(post_id) 62``` 63 64## context 65 66access MCP capabilities within tools: 67 68```python 69from fastmcp import FastMCP, Context 70 71mcp = FastMCP("server") 72 73@mcp.tool 74async def process(uri: str, ctx: Context) -> str: 75 await ctx.info(f"Processing {uri}...") 76 data = await ctx.read_resource(uri) 77 await ctx.report_progress(50, 100) 78 return data 79``` 80 81## middleware 82 83add authentication or other cross-cutting concerns: 84 85```python 86from fastmcp import FastMCP 87from fastmcp.server.middleware import Middleware 88 89class AuthMiddleware(Middleware): 90 async def on_call_tool(self, context, call_next): 91 # extract auth from headers, set context state 92 return await call_next(context) 93 94mcp = FastMCP("server") 95mcp.add_middleware(AuthMiddleware()) 96``` 97 98## decorator patterns 99 100add parameters dynamically (from pdsx): 101 102```python 103import inspect 104from functools import wraps 105 106def filterable(fn): 107 """Add a _filter parameter for JMESPath filtering.""" 108 @wraps(fn) 109 async def wrapper(*args, _filter: str | None = None, **kwargs): 110 result = await fn(*args, **kwargs) 111 if _filter: 112 import jmespath 113 return jmespath.search(_filter, result) 114 return result 115 116 # modify signature to include new param 117 sig = inspect.signature(fn) 118 params = list(sig.parameters.values()) 119 params.append(inspect.Parameter( 120 "_filter", 121 inspect.Parameter.KEYWORD_ONLY, 122 default=None, 123 annotation=str | None, 124 )) 125 wrapper.__signature__ = sig.replace(parameters=params) 126 return wrapper 127 128@mcp.tool 129@filterable 130async def list_records(collection: str) -> list[dict]: 131 ... 132``` 133 134## response size protection 135 136LLMs have context limits. protect against flooding: 137 138```python 139MAX_RESPONSE_CHARS = 30000 140 141def truncate_response(records: list) -> list: 142 import json 143 serialized = json.dumps(records) 144 if len(serialized) <= MAX_RESPONSE_CHARS: 145 return records 146 # truncate and add message about using _filter 147 ... 148``` 149 150## claude code plugins 151 152structure for Claude Code integration: 153 154``` 155.claude-plugin/ 156├── plugin.json # plugin definition 157└── marketplace.json # marketplace metadata 158 159skills/ 160└── domain/ 161 └── SKILL.md # contextual guidance 162``` 163 164**plugin.json**: 165```json 166{ 167 "name": "myserver", 168 "description": "what it does", 169 "mcpServers": "./.mcp.json" 170} 171``` 172 173skills are markdown files loaded as context when relevant to the task. 174 175## entry points 176 177expose both CLI and MCP server: 178 179```toml 180[project.scripts] 181mytool = "mytool.cli:main" 182mytool-mcp = "mytool.mcp:main" 183``` 184 185sources: 186- [fastmcp](https://github.com/jlowin/fastmcp) 187- [pdsx](https://github.com/zzstoatzz/pdsx) 188- [prefect-mcp-server-demo](https://github.com/zzstoatzz/prefect-mcp-server-demo) 189- [gofastmcp.com](https://gofastmcp.com)