DEV Community

Nebula
Nebula

Posted on

How to Build a Custom MCP Tool in Under 10 Min

Your AI agent can browse the web, read files, and call APIs. But what if you need it to query your database or call your internal service?

That's where custom MCP tools come in. MCP (Model Context Protocol) lets you expose any Python function as a tool that AI agents can discover and call. Here's how to build one in under 10 minutes.

Install FastMCP

FastMCP is the fastest way to create MCP-compatible tools. Install it:

pip install fastmcp
Enter fullscreen mode Exit fullscreen mode

The Code

Create a file called my_tools.py:

from fastmcp import FastMCP

mcp = FastMCP(name="MyTools")

# Sample data — swap this with your real database
USERS = {
    "u001": {"name": "Alice Chen", "role": "engineer", "team": "platform"},
    "u002": {"name": "Bob Park", "role": "designer", "team": "growth"},
    "u003": {"name": "Carol Silva", "role": "engineer", "team": "infra"},
}


@mcp.tool
def lookup_user(user_id: str) -> dict:
    """Look up an employee by their user ID. Returns name, role, and team."""
    if user_id not in USERS:
        return {"error": f"No user found with ID '{user_id}'"}
    return USERS[user_id]


@mcp.tool
def list_team_members(team: str) -> list[dict]:
    """List all employees on a given team."""
    members = [
        {"id": uid, **info}
        for uid, info in USERS.items()
        if info["team"] == team
    ]
    return members if members else [{"error": f"No members found for team '{team}'"}]


if __name__ == "__main__":
    mcp.run()
Enter fullscreen mode Exit fullscreen mode

That's it. Two custom tools in 30 lines.

What's Happening Here

FastMCP(name="MyTools") creates your MCP server. The name identifies your tool collection when agents connect to it.

@mcp.tool is the decorator that registers a function as a callable tool. FastMCP automatically:

  • Uses the function name (lookup_user) as the tool name
  • Uses the docstring as the tool description (this is what the AI reads to decide when to call it)
  • Generates an input schema from your type annotations (user_id: str)
  • Validates parameters before your function runs

Return types matter. The -> dict and -> list[dict] annotations tell FastMCP what schema to advertise. Agents use this to parse your response correctly.

Docstrings are critical. The AI agent reads your docstring to decide whether this tool solves its current problem. Write them like you're explaining the function to a coworker: short, specific, and focused on what it returns.

Run It

Start the server:

python my_tools.py
Enter fullscreen mode Exit fullscreen mode

FastMCP launches a local MCP server using stdio transport by default. Any MCP-compatible client (Claude Desktop, Cursor, or your own agent) can now discover and call lookup_user and list_team_members.

To connect from Claude Desktop, add this to your config:

{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["my_tools.py"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Make It Your Own

The sample uses a dictionary, but swap USERS with anything:

  • Database query: Replace the dict lookup with sqlite3 or sqlalchemy
  • API call: Use httpx to hit your internal service
  • File search: Read from local logs or config files

The pattern stays the same: decorate a function, add type hints, write a clear docstring. FastMCP handles the rest.

One Gotcha

Your function signature cannot use *args or **kwargs. FastMCP needs explicit parameters to generate the JSON schema that agents use. Every parameter must have a type annotation.

Next Steps

You now have a working MCP server with custom tools. From here you can:

  • Add more tools to the same server (just add more @mcp.tool functions)
  • Use Annotated types to add parameter descriptions for better agent behavior
  • Deploy it as an HTTP server with mcp.run(transport="streamable-http")

If you want your custom tools to run as part of a managed agent workflow without setting up infrastructure, Nebula connects to MCP servers and lets your agents call custom tools on a schedule.

This is part of the AI Agent Quick Tips series. Follow for more bite-sized agent tutorials.

Top comments (0)