Parameter Types, Tool Descriptions, and Additional Customization
Better Control with Pydantic
So at this stage, we have a tool that accepts an integer age and returns an integer:
@mcp.tool
def dog_to_human_age(age: int) -> int:
"""Calculate the real age of a dog in human years."""
return age * 7
Imagine if the age sent by the LLM is negative, for example -3 or if the age is unrealistically high, like 50. The tool would still return a result, but it wouldn't make sense in the real world.
To handle this, we can use the following approach:
from pydantic import Field
from typing import Annotated
@mcp.tool
def dog_to_human_age(
age: Annotated[int, Field(ge=0, le=30)]
) -> int:
"""Calculate the real age of a dog in human years."""
return age * 7
In Python, Annotated is a way to attach additional metadata to type hints to provide more information about the expected values. For example:
age: Annotated[int, "This is the age of the dog in years, which must be a non-negative integer and realistically should not exceed 30 years."]
Pydantic's Field is a function that lets you attach extra information to a type annotation, things like minimum and maximum values, a description, or a default. Instead of just declaring age: int, you can write age: Annotated[int, Field(ge=0, le=30, description="The dog's age in years")] to say: "this is an integer, it must be between 0 and 30 (inclusive), and here is what it means."
FastMCP reads these constraints when building the tool's input schema, so they are sent to the LLM as part of the tool definition. The LLM learns what values are valid before it calls the tool. Pydantic also enforces them server-side, if an invalid value arrives anyway, validation fails before your function runs, and FastMCP returns an error to the caller automatically.
The most commonly used Field parameters for tool arguments are:
gt/lt: greater than / less than (exclusive bounds)ge/le: greater than or equal / less than or equal (inclusive bounds)description: shown to the client in the tool schemadefault: marks the parameter as optional with a fallback value
For our example, to enforce that the age must be between 0 and 30, we can use ge=0 and le=30 in the Field definition.
Here is an example:
from typing import Annotated
from pydantic import FieldPractical MCP with FastMCP & LangChain
Engineering the Agentic ExperienceEnroll now to unlock current content and receive all future updates for free. Your purchase supports the author and fuels the creation of more exciting content. Act fast, as the price will rise as the course nears completion!
