| name | add-mcp-tool |
| description | Use when adding a new MCP tool to the property MCP server (mcp_server/server.py). Provides the exact pattern with a copy-paste template. |
Add an MCP Tool
Add a new tool to mcp_server/server.py following the established FastMCP pattern.
Step 1: Add the Tool Function
Add to mcp_server/server.py. The docstring becomes the tool description for AI hosts.
@mcp.tool()
async def new_tool(
required_param: str,
optional_param: Optional[str] = None,
limit: int = 50,
) -> ToolResult:
"""One-line description of what this tool does.
Args:
required_param: UK postcode (e.g. "SW1A 1AA")
optional_param: Optional filter description
limit: Maximum results (default 50)
"""
from property_core import SomeService
result = await anyio.to_thread.run_sync(
partial(
SomeService().method,
param=required_param,
limit=limit,
)
)
data = result.model_dump(mode="json")
summary = f"Found {result.count} items for {required_param}"
return ToolResult(content=_content(summary, data), structured_content=data)
Key Rules
- Lazy imports —
from property_core import X inside the function body, never at module top level
- Async wrapping — use
anyio.to_thread.run_sync(partial(...)) for sync property_core calls. For already-async functions, just await them directly.
- ToolResult construction:
content = human-readable summary + slimmed JSON (via _content() helper)
structured_content = full data dict for programmatic consumers
- Configuration-gated tools — if the data source needs credentials, check
is_configured() and return early with an explanatory message if not configured. See property_epc() for the pattern.
Helpers Available
_slim(obj) — strips raw, images, floorplans from dicts recursively
_content(summary, data) — builds content string: summary + "\n\n" + slimmed JSON
Checklist