Build

What Claude actually sees

Claude never sees your code. It sees a name, a description and a schema, then the result. With the Python SDK, each one comes straight from your code.

server.pypython
from mcp.server import MCPServerfrom mcp.server.mcpserver.exceptions import ToolError mcp = MCPServer("weather") @mcp.tool()async def get_weather(    city: str, units: str = "metric") -> str:    """Current weather for a city, today only."""    data = await fetch_weather(city, units)    if data is None:        raise ToolError(f"Unknown city: {city}")    return f"{data.temp}° and {data.summary}" if __name__ == "__main__":    mcp.run()  # stdio by default
what Claude sees (tools/list)json
{  "name": "get_weather",  "description": "Current weather for a city, today only.",  "inputSchema": {    "type": "object",    "properties": {      "city": { "type": "string" },      "units": { "type": "string", "default": "metric" }    },    "required": ["city"]  }}
  • Function namename
  • Docstringdescription, read like a prompt
  • Type hints + defaultsinputSchema
  • Return valuethe tool result
  • ToolErroran error Claude can read and fix

On stdio, stdout is the protocol channel

A stray print() corrupts the message stream. Log to stderr instead.

20 / 28