Build More Tools
Table of Contents + β
In the previous chapter, our MCP server currently has only one tool:
Thatβs a good start, but a calculator should be able to do more than addition.
Letβs add three more tools:
By the end of this chapter, our MCP server will support the four basic arithmetic operations.
β 7.1 Add the Subtract Tool
Letβs start with subtraction.
Add this function to server.py:
@mcp.tool()def subtract(a: int, b: int) -> int: """Subtract the second number from the first number.""" return a - bThe tool takes two numbers:
aband returns:
a - bFor example:
subtract(20, 5)returns:
15Notice that the structure is very similar to our add() tool.
@mcp.tool()def subtract(a: int, b: int) -> int: """Subtract the second number from the first number.""" return a - bThe @mcp.tool() decorator exposes the function as an MCP tool.
βοΈ 7.2 Add the Multiply Tool
Next, letβs add multiplication.
@mcp.tool()def multiply(a: int, b: int) -> int: """Multiply two numbers together.""" return a * bFor example:
multiply(10, 5)returns:
50Our server now has:
β 7.3 Add the Divide Tool
Finally, letβs add division.
@mcp.tool()def divide(a: float, b: float) -> float: """Divide the first number by the second number.""" return a / bWe are using float here because division doesnβt always produce a whole number.
For example:
divide(10, 2)returns:
5.0And:
divide(10, 4)returns:
2.5But thereβs a problem.
What happens if someone tries:
divide(10, 0)We need to handle that.
π« 7.4 Handle Invalid Input
Division by zero isnβt a valid mathematical operation.
Instead of allowing our function to fail unexpectedly, we should handle it explicitly.
Update the function:
@mcp.tool()def divide(a: float, b: float) -> float: """Divide the first number by the second number.""" if b == 0: raise ValueError("Cannot divide by zero.")
return a / bNow our tool checks the input before performing the calculation.
If b is zero:
divide(10, 0)the tool raises an error:
Cannot divide by zero.This is an important principle when building MCP tools:
Tools should handle invalid inputs explicitly rather than allowing unexpected failures.
π§Ύ 7.5 Our Complete Calculator Server
Our server.py now looks like this:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Calculator Server")
@mcp.tool()def add(a: int, b: int) -> int: """Add two numbers together.""" return a + b
@mcp.tool()def subtract(a: int, b: int) -> int: """Subtract the second number from the first number.""" return a - b
@mcp.tool()def multiply(a: int, b: int) -> int: """Multiply two numbers together.""" return a * b
@mcp.tool()def divide(a: float, b: float) -> float: """Divide the first number by the second number.""" if b == 0: raise ValueError("Cannot divide by zero.")
return a / b
if __name__ == "__main__": mcp.run()We now have four MCP tools.
π 7.6 Tool Descriptions Matter
Notice that every tool has a description:
"""Add two numbers together.""""""Subtract the second number from the first number.""""""Multiply two numbers together.""""""Divide the first number by the second number."""These descriptions are not just comments for developers.
They become part of the information that an MCP client can discover about the tools.
The AI can use this information to understand what each tool does.
For example:
addDescription:Add two numbers together.and:
divideDescription:Divide the first number by the second number.Clear descriptions become increasingly important as the number of tools grows.
π 7.7 Restart the MCP Server
Whenever we change our Python code, restart the server so that the new tools are loaded.
Stop the running server and start it again:
python server.pyOur MCP client can now discover all four tools.
addsubtractmultiplydivideπ§ͺ 7.8 Try the New Tools
Letβs test them through our MCP client.
Ask:
What is 25 + 15?The client can use:
add(25, 15)Result:
40Try subtraction:
What is 50 - 18?The tool call is:
subtract(50, 18)Result:
32Try multiplication:
What is 12 Γ 5?The tool call is:
multiply(12, 5)Result:
60And division:
What is 20 divided by 4?The tool call is:
divide(20, 4)Result:
5β οΈ 7.9 What Happens With an Error?
Now try:
What is 10 divided by 0?The client may attempt:
divide(10, 0)Our server checks:
if b == 0: raise ValueError("Cannot divide by zero.")Instead of returning an incorrect result, the tool reports an error.
The client can then use that result to explain what went wrong.
This demonstrates why error handling matters for MCP tools.
Tools are ultimately code running on a server, so they need the same defensive programming practices as any other application.
β 7.10 What We Have Built
We started with one tiny function:
add(10, 20)Now we have a complete calculator:
Our tools have:
- Names
- Descriptions
- Parameters
- Parameter types
- Return types
- Input validation
- Error handling
More importantly, we now understand the basic lifecycle:
This small calculator may seem simple, but the exact same pattern can be used to build much more powerful MCP servers.
For example, a real-world MCP server could expose tools for:
search_documents()query_database()create_ticket()get_customer()send_email()search_products()The difference is that those tools perform useful real-world operations instead of arithmetic.
And thatβs the real power of MCP: we can expose capabilities from our own applications to AI clients through a standard interface.