DEV Community

GridPort
GridPort

Posted on

Building a Custom MCP Server for Claude Code — A Fortune-Telling Tool with FastMCP

"MCP servers sound complicated" — if that's your reaction, FastMCP might change your mind. It handles almost all the plumbing for you. Add one decorator to a plain Python function, and you've got a custom tool Claude Code can call.

In this post, we'll build a small fortune-telling tool as a learning exercise, and walk through what FastMCP is actually doing for you along the way.

What is MCP, anyway?

MCP (Model Context Protocol) is a common standard for giving AI models like Claude "external tools" to work with.

An AI model itself is great at generating text, but on its own it can't do concrete things like "tell today's fortune based on the date" or "query an internal database."

That's where an MCP server comes in: you register callable tools on it, and Claude Code invokes them whenever it needs to.

Hand-writing an MCP server from scratch is a fair amount of work, but with FastMCP you can build a working fortune-telling tool that Claude Code can call in just a few dozen lines of code.

Why FastMCP makes this easy

Normally, an MCP server has to implement a lot of low-level protocol details — what message format to use, how to advertise the list of available tools, and so on. FastMCP takes care of all that "plumbing" for you.

All you do as a developer is write a normal Python function and mark it with @mcp.tool. FastMCP inspects the function's argument types and return type to auto-generate the schema (the "instruction manual") that gets handed to the AI. Since none of the transport or protocol details are something you need to think about, anyone who's written a basic web app can have their first tool running in a few minutes.

Note on decorator syntax: the standalone fastmcp package (what we're using here) accepts a bare @mcp.tool, no parentheses needed. If you're instead using the MCPServer bundled with the official mcp Python SDK, the decorator requires parentheses: @mcp.tool(). Mixing the two up is a common source of confusing errors, so if you copy code from a different MCP tutorial, double-check which package it's using.

Setting up the Python environment

You'll need Python 3.10 or later.

python --version
Enter fullscreen mode Exit fullscreen mode

If it's not installed, grab it from python.org.

Then create and activate a virtual environment:

# macOS / Linux
python -m venv venv
source venv/bin/activate

# Windows
python -m venv venv
venv\Scripts\activate.bat
Enter fullscreen mode Exit fullscreen mode

Once activated, you should see (venv) at the start of your prompt.

Install FastMCP:

pip install fastmcp
Enter fullscreen mode Exit fullscreen mode

That's it — no database, no config files.

Building the fortune-telling tool

Create a project folder and, inside it, a server.py file with the following:

import random
from datetime import date
from fastmcp import FastMCP

# Create the server ("uranai" is Japanese for "fortune-telling" — the name of this tool group)
mcp = FastMCP("uranai")

@mcp.tool
def fortune(name: str, birthday: str = "") -> str:
    """Tells today's fortune based on a name (and optionally a birthday)."""
    # Seed the RNG with name + birthday + today's date, so the result
    # stays the same for a given person on a given day, but changes daily.
    seed = f"{name}|{birthday}|{date.today().isoformat()}"
    rng = random.Random(seed)

    levels = ["Great luck", "Good luck", "Modest luck", "Luck", "Fading luck", "Bad luck"]
    items = ["reading a book", "taking a walk", "coffee", "sleeping early", "a new app", "cleaning"]
    colors = ["red", "blue", "green", "yellow", "white", "purple"]

    return (
        f"Today's fortune for {name}\n"
        f"Fortune: {rng.choice(levels)}\n"
        f"Lucky activity: {rng.choice(items)}\n"
        f"Lucky color: {rng.choice(colors)}\n"
        f"Lucky number: {rng.randint(1, 49)}"
    )

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

Three things matter here:

  1. FastMCP("uranai") creates the server instance.
  2. Adding @mcp.tool to the function is all it takes to turn it into something Claude can call.
  3. The docstring (the """...""" part) is what the AI reads to decide when to use this tool — write it clearly.

The trick worth noting is seeding the random number generator with today's date. That gives you fortune-telling-app behavior for free: the same person gets the same result if asked again on the same day, and a different result the next day.

Starting the server

From the project directory, run:

python server.py
Enter fullscreen mode Exit fullscreen mode

If it starts without errors, you're ready to connect it to Claude Code.

Connecting to Claude Code

If you don't have the Claude Code CLI installed yet, install it first — see the official installation docs for your platform (macOS, Linux, or Windows).

Then register the server:

claude mcp add uranai -- python /path/to/server.py
Enter fullscreen mode Exit fullscreen mode

Replace /path/to/server.py with the actual path (if you're using a virtual environment, point to that environment's Python executable to be safe).

Restart or reload Claude Code, and the uranai server should be recognized. You can check connection status with the /mcp command.

If you're using the Claude desktop app instead, add this to your config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "uranai": {
      "command": "/path/to/venv/bin/python",
      "args": ["/path/to/uranai/server.py"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

(On Windows, command would instead point to something like C:\\Users\\yourname\\uranai\\venv\\Scripts\\python.exe.)

Try it out

Open Claude Code, ask it for your fortune, and approve the tool call when prompted. You should get back a fortune generated by your own tool.

Ideas for taking it further

Once the basics work, adding more tools is just a matter of writing another function and decorating it with @mcp.tool:

  • Tarot / omikuji mode: expand the pool of results and messages for more variety.
  • Zodiac-based fortunes: parse the birthday into a zodiac sign and tailor results accordingly.
  • External API integration: pull in weather or calendar data to add some real-world flavor.
  • Persisting results: log fortune history to a file or database.

If things get heavier — image generation, larger-scale analysis — you don't have to run this on your laptop. You could offload the compute to a GPU cloud instance and expose the MCP server from there instead.

Wrapping up

With FastMCP, building an MCP server comes down to "write a Python function, add @mcp.tool." We walked through the whole loop here — environment setup, writing the tool, connecting it to Claude Code, and confirming it works — using a fortune-telling tool as the example.

The same pattern scales to far more useful things: wrapping internal tools, automating repetitive tasks, and more. Fortune-telling is just the toy example — try swapping in your own idea next.

📌 This post reflects Claude Code's behavior as of June 2026. Since Claude Code updates frequently, check the official docs for the latest details.

This article was edited with AI assistance.
*Originally published in Japanese on EdgeHUB.

Top comments (0)