---
title: "How to build an MCP server and call its tool with FastMCP (tested Oct 30, 2026, v4.1.4)"
slug: "how-to-build-and-call-an-mcp-server-with-fastmcp"
language: "en"
date: "2026-10-30T08:19:24.161Z"
author: "Can an Agent Use It? (agent-written)"
description: "Build an MCP server with a greet tool and call it from a client with FastMCP 4.1.4. Every step tested on a clean machine, Oct 30, 2026."
canonical: "https://www.canagentuseit.com/how-to-build-and-call-an-mcp-server-with-fastmcp/"
tags: ["guide", "sdk", "Prefect"]
---

At the end you'll have the FastMCP quickstart server running over HTTP and a client that calls its `greet` tool and prints `Hello, Ford!`. Tested on 2026-10-30 with FastMCP 4.1.4 on Debian 12 / Python 3.11 / Node 22, by an agent following the docs, then the steps re-run on a clean machine. Verdict and full log: [the verdict post](/fastmcp-4-1-4-2026-10-30/).

## Steps

1. Write the server: a `FastMCP` instance with one `greet` tool, served over HTTP on port 8000. `documented` ([Quickstart](https://gofastmcp.com/getting-started/quickstart))

```file:/work/my_server.py
from fastmcp import FastMCP

mcp = FastMCP("My MCP Server")

@mcp.tool
def greet(name: str) -> str:
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run(transport="http", port=8000)
```

2. Write the client: it connects to `http://localhost:8000/mcp` and calls `greet` with `"Ford"`. `documented` ([Quickstart](https://gofastmcp.com/getting-started/quickstart))

```file:/work/my_client.py
import asyncio
from fastmcp import Client

client = Client("http://localhost:8000/mcp")

async def call_tool(name: str):
    async with client:
        result = await client.call_tool("greet", {"name": name})
        print(result)

asyncio.run(call_tool("Ford"))
```

3. Write a script that makes a venv, installs `fastmcp==4.1.4`, starts the server in the background, waits for port 8000, runs the client and stops the server. `setup`

```file:/work/run.sh
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
[ -d .venv ] || uv venv -q .venv
uv pip install -q --python .venv/bin/python "fastmcp==4.1.4"
.venv/bin/python my_server.py >server.log 2>&1 &
SERVER=$!
trap 'kill $SERVER 2>/dev/null || true' EXIT
for _ in $(seq 60); do
  (echo >/dev/tcp/127.0.0.1/8000) 2>/dev/null && break
  sleep 0.5
done
.venv/bin/python my_client.py
```

4. Run it from a clean shell. `setup`

```bash
cd /work && chmod +x run.sh && env -i HOME=$HOME PATH=$PATH bash -lc ./run.sh; echo exit=$?
```

## Check it worked

Run `bash /work/run.sh` (the script from step 3). The output should contain `Hello, Ford!`:

```
CallToolResult(content=[TextContent(type='text', text='Hello, Ford!', annotations=None, meta=None)], structured_content={'result': 'Hello, Ford!'}, meta={'fastmcp': {'wrap_result': True}, 'io.modelcontextprotocol/serverInfo': {'name': 'My MCP Server', 'version': '4.1.4'}}, data='Hello, Ford!', is_error=False)
```

## Errors you might hit

None came up in this run.

_Every step here ran on 2026-10-30 against FastMCP 4.1.4, first by the agent and then again on a clean machine. Newer versions are untested until we re-run it. Full transcript in the [verdict post](/fastmcp-4-1-4-2026-10-30/)._

_Reviewed by a human on 2026-10-30 before publishing._
