Building Your Own MCP Server for AI
Build Your First Tool
Register a callable MCP tool, understand the JSON schema the model sees, and return a result it can use.
A tool is a function the model may call. You pick the name, the arguments, and the return value. The SDK turns type hints into a JSON Schema the host advertises.
Names and descriptions are the UI
The model never sees your Python source. It sees name, description, and inputSchema. A tool named do_stuff with an empty docstring will be ignored or misused. Write the docstring as if the reader is the model: what it does, when to call it, what not to assume.
A tool with arguments
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("greeter")
@mcp.tool()
def greet(name: str, excited: bool = False) -> str:
'''Return a short greeting. Use excited=True for an exclamation mark.'''
mark = "!" if excited else "."
return f"Hello, {name}{mark}"
if __name__ == "__main__":
mcp.run()Required argument: name (string). Optional: excited (boolean, default false). The host will refuse a call that omits name if the schema marks it required — which MCPServer does for parameters without defaults.
What the model sees
Conceptually the advertised tool looks like this (exact JSON varies by SDK version):
{
"name": "greet",
"description": "Return a short greeting. Use excited=True for an exclamation mark.",
"inputSchema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"excited": { "type": "boolean", "default": false }
},
"required": ["name"]
}
}Keep return values boring and structured enough to quote. A one-line string is fine here. In Parameters and Structured Results you will return JSON objects and errors the model can act on.
Check it
- Run
mcp dev server.pyand invokegreetwithnameset. - Omit
nameand confirm the inspector (or host) reports a validation error — that is the schema working. - Change the docstring and reload. The new description should appear in the tool list.