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

> Source: <https://dev.to/_02121fbe984480fd65fc/building-a-custom-mcp-server-for-claude-code-a-fortune-telling-tool-with-fastmcp-2j0d>
> Published: 2026-08-13 15:04:18+00:00

"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.

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.

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.

You'll need Python 3.10 or later.

```
python --version
```

If it's not installed, grab it from [python.org](https://www.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
```

Once activated, you should see `(venv)`

at the start of your prompt.

Install FastMCP:

```
pip install fastmcp
```

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

Create a project folder and, inside it, a `server.py`

file with the following:

``` python
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()
```

Three things matter here:

`FastMCP("uranai")`

creates the server instance.`@mcp.tool`

to the function is all it takes to turn it into something Claude can call.`"""..."""`

part) is what the AI reads to decide 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.

From the project directory, run:

```
python server.py
```

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

If you don't have the Claude Code CLI installed yet, install it first — see the [official installation docs](https://code.claude.com/docs/en/installation) for your platform (macOS, Linux, or Windows).

Then register the server:

```
claude mcp add uranai -- python /path/to/server.py
```

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:

`~/Library/Application Support/Claude/claude_desktop_config.json`

`%APPDATA%\Claude\claude_desktop_config.json`

```
{
  "mcpServers": {
    "uranai": {
      "command": "/path/to/venv/bin/python",
      "args": ["/path/to/uranai/server.py"]
    }
  }
}
```

(On Windows, `command`

would instead point to something like `C:\\Users\\yourname\\uranai\\venv\\Scripts\\python.exe`

.)

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.

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

:

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.

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.*
