Return Structured Data from MCP Tools

Whenever a tool's result will feed another tool or decision, structured output is more reliable than prose.

from pydantic import BaseModel

class DeployResult(BaseModel):
    deployment_id: str
    status: str
    url: str | None = None

@mcp.tool()
async def deploy(service: str) -> DeployResult:
    """Deploy a service to staging."""
    data = await deployment_service.deploy(service)
    return DeployResult(**data)

Why structured output helps

Do not over-return

Return the fields needed for the next decision, not an entire internal database row or third-party payload.