Build Our First MCP Tool

From the previous chapter, our MCP server is running, and we have connected it to Jan.

Now let’s make our server actually do something. 🚀

We’ll start with a very simple tool:

add(10, 20)

The tool will take two numbers, add them together, and return the result.

By the end of this chapter, we’ll be able to ask our AI:

What is 10 + 20?

and the AI will be able to use our MCP tool to calculate the answer.

Let’s build it step by step.


🛠️ 5.1 What Is an MCP Tool?

An MCP tool is a function that an MCP server makes available to an MCP client.

The function can perform some action on behalf of the AI application.

For example, a tool could:

add two numbers
read a file
query a database
call an API
search documents
create a ticket

In our case, we’ll start with something much simpler:

add(10, 20)

Think of it like this:

I need to add two numbers

Call add()

AI

MCP Client

MCP Server

add(10, 20)

30

The important idea is that the AI doesn’t implement the calculation itself.

Instead, it can ask the MCP server to execute the tool.


✍️ 5.2 Define Our First Tool

Open the server.py file we created earlier.

Currently, we have:

from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Calculator Server")
if __name__ == "__main__":
mcp.run()

Let’s add our first tool.

Add the following function:

@mcp.tool()
def add(a: int, b: int) -> int:
return a + b

Our complete server now looks like this:

from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Calculator Server")
@mcp.tool()
def add(a: int, b: int) -> int:
return a + b
if __name__ == "__main__":
mcp.run()

That’s our first MCP tool! 🎉

But there are several things happening in these few lines, so let’s understand them.


🧩 5.3 How Do We Define a Tool?

The MCP Python SDK provides the @mcp.tool() decorator.

@mcp.tool()

This tells the MCP server:

“Expose the following Python function as an MCP tool.”

Without this decorator, add() would simply be a normal Python function.

With the decorator, it becomes a tool that MCP clients can discover and call.

So:

def add(a: int, b: int) -> int:

is a normal Python function, while:

@mcp.tool()
def add(a: int, b: int) -> int:

is an MCP tool.


🏷️ 5.4 Tool Name

Our tool is called:

add

The name comes from the Python function name:

def add(a: int, b: int) -> int:

So an MCP client will see a tool named:

add

Tool names should be clear and descriptive.

For example:

add
subtract
search_documents
get_weather
create_ticket

A good tool name makes it easier for an AI model to understand what the tool does.


📝 5.5 Tool Description

A tool also needs a description.

The description helps the AI understand when and why it should use the tool.

Let’s add one to our tool:

@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b

Now the complete function is:

@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b

The description is:

Add two numbers together.

This may look like a small detail, but descriptions become very important when a server exposes many tools.

For example, imagine our server has:

add
search_documents
create_ticket
get_customer
delete_customer

The AI needs enough information to understand what each tool does.

A clear description helps it choose the right tool.


🔢 5.6 Tool Arguments

Our tool needs two numbers.

We define them here:

def add(a: int, b: int) -> int:

The arguments are:

a
b

Both are integers:

a: int
b: int

So our tool expects:

a → integer
b → integer

For example:

a = 10
b = 20

The tool receives:

add(10, 20)

and performs:

10 + 20

↩️ 5.7 Return Value

The function returns:

return a + b

So:

add(10, 20)

returns:

30

We also specify the return type:

-> int

So the function signature tells us:

def add(a: int, b: int) -> int:

In simple terms:

Input:
a → integer
b → integer
Output:
integer

This information is also useful to the MCP SDK when exposing the tool to clients.


🧾 5.8 Our Complete MCP Tool

Let’s look at the complete tool again:

@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b

We can break it down like this:

@mcp.tool()

Expose this function as an MCP tool

add

Tool name

a: int, b: int

Tool arguments

Docstring

Tool description

-> int

Return type

return a + b

Tool implementation

Now we have a real MCP tool.


▶️ 5.9 Run Our MCP Server

Let’s start the server again.

From the project directory:

Terminal window
python server.py

Our server is now running with the add tool available.

The architecture has changed slightly:

MCP Server

Tools

add()

But how does Jan know that the add tool exists?

That’s where MCP’s tool discovery mechanism comes in.

When an MCP client connects to our server, it can discover the tools that the server exposes.

We’ll look at exactly how that works in a later chapter.

For now, let’s use the tool.


🧪 5.10 Try Our First Tool

Open Jan and make sure our MCP server is connected.

Now ask:

What is 10 + 20?

The AI can determine that it needs to perform an addition and use our add tool.

Conceptually, the flow is:

What is 10 + 20?

Call add(10, 20)

30

You

Jan

MCP Server

add(10, 20)

30

🎉 We’ve just built and used our first MCP tool!


✅ 5.11 What We Have Learned

Our first tool was intentionally simple, but it introduced the core pieces of an MCP tool.

We learned:

PartExample
Tool decorator@mcp.tool()
Tool nameadd
DescriptionAdd two numbers together.
Argumentsa, b
Argument typesint, int
Return typeint
Implementationreturn a + b

Our server now looks like:

Calculator MCP Server

add(a, b)

This is the basic pattern we’ll use for every tool we build later.

In the next chapter, we’ll take a closer look at what happens between Jan and our MCP server.

We’ll see how the client discovers our add tool and how it asks the server to execute it.