FastMCP: Write Your Own MCP Server in Python (Linux, Windows, Mac)
Before you start
- 21 min read
Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#
FastMCP is the Python framework for writing your own MCP server: you decorate ordinary functions with @mcp.tool, and it builds the tool definitions, checks the arguments and speaks the protocol, so Claude Code, Open WebUI and other AI clients can call your code.

Logo: the official FastMCP project (github.com/PrefectHQ/fastmcp)
MCP (Model Context Protocol) is the standard way an AI client asks outside code to do something: read a file, query a database, call your API. You write the Python once and any MCP client can use it. This guide builds a small server, runs it over stdio and HTTP, connects it to Claude Code and Open WebUI, and protects it.
One thing to know first: the project moved. It used to live at github.com/jlowin/fastmcp; the maintained home is now github.com/PrefectHQ/fastmcp (the Prefect team), and the old address redirects there.
| Current version | FastMCP 4.1.6 on PyPI (uploaded November 2026). FastMCP 4.0 became stable in August 2026 |
| Time needed | About 30 minutes (our estimate) |
| Size on disk | Not published by the project; we did not measure it |
| Ports | None for stdio. HTTP uses 8000 and the path /mcp by default |
| Licence | Apache 2.0 |
| Needs | Python 3.10 or newer, and the uv tool (Step 1) |
| Official docs | gofastmcp.com and github.com/PrefectHQ/fastmcp |
At a glance:
- What it is: a Python library plus a
fastmcpcommand, not a program you run. - Two ways to connect: stdio (the AI client starts your script on the same computer) and HTTP (your script listens on a URL).
- Authentication: off by default. Only HTTP can be protected; stdio relies on being local.
- Works with: Claude Code, Open WebUI, Claude Desktop, Cursor, Gemini CLI and other MCP clients.
- Status: alive and open source. Version 4.1.6 appeared in early November 2026, and the 3.x line still gets fixes.
- Cost: free. Prefect also sells hosting (Horizon); you do not need it.
How it fits together#
Your Python file is the only thing you write. FastMCP turns it into an MCP server, and the transport you pick decides who can reach it. Dashed parts are optional.
Drawn from the FastMCP running-server, HTTP deployment and authentication docs, November 2026.
Before you start#
You need Python 3.10 or newer (per PyPI) and uv, the package manager FastMCP's docs recommend; Step 1 installs it. Check Python first:
python3 --version
python --version
Checklist:
- [ ] Python 3.10 or newer
- [ ] A terminal and an empty folder for the project
- [ ] For Step 5: Claude Code installed (
claude --versionprints a version) - [ ] For Step 8 with Open WebUI: an admin account (see our Open WebUI MCP guide)
- [ ] For HTTPS: a domain pointing at your server and ports 80 and 443 free, or a home-only name
Tested on: not run by DIY Lab Hub. Every command and setting comes from the official FastMCP, uv, Claude Code, Open WebUI and Caddy docs, read in November 2026.
Step 1: Install uv#
uv creates the project, installs FastMCP and runs your server. It is a separate tool from FastMCP.
Linux#
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows (PowerShell)#
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Mac (Terminal)#
Same command as Linux, or use Homebrew:
brew install uv
Check it worked. Open a new terminal and run uv --version. It prints a version number. If the command is not found, open another new terminal window first.
Step 2: Create the project and install FastMCP#
Pin the exact version: the docs say minor releases can contain breaking changes.
Linux#
uv init fastmcp-demo cd fastmcp-demo uv add "fastmcp==4.1.6"
Windows (PowerShell)#
uv init fastmcp-demo cd fastmcp-demo uv add "fastmcp==4.1.6"
Mac (Terminal)#
Same commands as Linux:
uv init fastmcp-demo cd fastmcp-demo uv add "fastmcp==4.1.6"
Check it worked. Run uv run fastmcp version. The docs show output of this shape (their example, with an older number): lines for "FastMCP version", "MCP version", "Python version" and "Platform". Your FastMCP line should say 4.1.6.
Tip: If you use plain
pip install fastmcpinstead of uv, know this: the docs warn that onepipupgrade from FastMCP 3.2 or older to 3.3 or newer can leaveimport fastmcpbroken. The fix ispip install --force-reinstall fastmcp. A fresh uv project avoids it.
Step 3: Write the server#
A server is a file with a FastMCP object and decorated functions. Type hints become the argument rules, and the docstring becomes the description the AI reads. This file has each kind of capability: two tools (actions), one resource (read-only data) and one prompt (a reusable question).
Linux#
cat > server.py <<'EOF'
from fastmcp import FastMCP
mcp = FastMCP("Demo Server")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two whole numbers."""
return a + b
@mcp.tool
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
@mcp.resource("resource://about")
def about() -> str:
"""What this server is."""
return "A small demo server built with FastMCP."
@mcp.prompt
def summarize(text: str) -> str:
"""Ask the model for a three-bullet summary."""
return f"Summarize this in three bullets: {text}"
if __name__ == "__main__":
mcp.run()
EOF
Windows (PowerShell)#
Set-Content -Path server.py -Encoding utf8 -Value @'
from fastmcp import FastMCP
mcp = FastMCP("Demo Server")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two whole numbers."""
return a + b
@mcp.tool
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
@mcp.resource("resource://about")
def about() -> str:
"""What this server is."""
return "A small demo server built with FastMCP."
@mcp.prompt
def summarize(text: str) -> str:
"""Ask the model for a three-bullet summary."""
return f"Summarize this in three bullets: {text}"
if __name__ == "__main__":
mcp.run()
'@
Mac (Terminal)#
Same as Linux (the cat > server.py <<'EOF' block).
Check it worked. uv run python -c "import server" prints nothing. A syntax error shows here instead of inside an AI client.
Tip: Give every tool a docstring and real type hints: the AI sees only the name, the docstring and the argument types. The docs also say functions with
*argsor**kwargscannot be tools, because the protocol needs a complete argument list.
Step 4: Test it without any AI client#
Before you involve Claude, call the server with FastMCP's own command-line client; list and call accept the file itself.
Linux#
uv run fastmcp list server.py uv run fastmcp call server.py add a=2 b=3 uv run fastmcp call server.py word_count text="one two three"
Windows (PowerShell)#
uv run fastmcp list server.py uv run fastmcp call server.py add a=2 b=3 uv run fastmcp call server.py word_count text="one two three"
Mac (Terminal)#
Same commands as Linux.
Check it worked. list prints your tools as function signatures (add and word_count, with argument names and types), as the docs describe it. The call lines return 5 and 3: the docs say the CLI converts your text values to the types the tool expects.
Step 5: Connect it to Claude Code over stdio#
With stdio, Claude Code starts your script itself and talks to it through standard input and output. There is no port and no password. Right for tools only you use, on this computer.
Register it with claude mcp add. Everything after the -- is the command Claude Code runs. Use absolute paths, because Claude Code starts it from whatever folder you are in. The commands assume the project is in your home folder.
Linux#
claude mcp add --transport stdio fastmcp-demo -- uv run --project "$HOME/fastmcp-demo" fastmcp run "$HOME/fastmcp-demo/server.py"
Windows (PowerShell)#
claude mcp add --transport stdio fastmcp-demo -- uv run --project "$HOME\fastmcp-demo" fastmcp run "$HOME\fastmcp-demo\server.py"
Mac (Terminal)#
Same command as Linux.
Check it worked. Run claude mcp get fastmcp-demo; Claude Code's docs say it shows whether the server connected. Then start claude, type /mcp and look for fastmcp-demo. Ask: "Use the add tool to add 2 and 3." Claude asks permission, calls your function and answers 5.
Tip: FastMCP also has
fastmcp install claude-code server.py. Its docs say it looks for the Claude Code program at the old default location,~/.claude/local/claude, so the manualclaude mcp addabove is the safer route.
Stdio or HTTP: which one do you need?#
| stdio | HTTP (Streamable) | |
|---|---|---|
| Who starts the server | The AI client, per session | You, and it keeps running |
| Who can connect | Only that client on this computer | Anyone who can reach the URL |
| Port | None | 8000 by default, path /mcp |
| Authentication | Not used; inherits local security | Off by default; turn it on (Step 7) |
| Good for | Your own tools in Claude Code or Claude Desktop | A shared server, Open WebUI in a container, another computer |
| HTTPS | Not needed | Needed once it leaves your computer |
SSE, a third option, is legacy: the docs keep it only for old clients, and Claude Code marks it deprecated.
Step 6: Run the same server over HTTP#
You do not need to change the file: fastmcp run picks the transport. It binds to 127.0.0.1 by default, so only this computer can connect.
Linux#
uv run fastmcp run server.py --transport http --port 8000
Windows (PowerShell)#
uv run fastmcp run server.py --transport http --port 8000
Mac (Terminal)#
Same command as Linux.
Leave that terminal open. In a second terminal in the same project folder, check it. The server has no authentication yet, so pass --auth none: the docs say the CLI's default for HTTP is oauth.
uv run fastmcp list http://127.0.0.1:8000/mcp --auth none
Check it worked. The same two tools appear. Stop the server with Ctrl-C in its terminal.
Tip:
fastmcp runignores theif __name__ == "__main__":block at the bottom of your file, so setup code placed there never runs. The docs' fix: put it in a function and point at it, for examplefastmcp run server.py:create_server.
Step 7: Protect it with a token#
FastMCP's docs say a server starts with auth=None: anyone who can reach the HTTP port can use every tool. They call authentication "highly recommended" for remote servers, and some AI clients refuse an unprotected one.
For learning the pattern, the simplest protection is a static token. The docs are plain that StaticTokenVerifier keeps tokens as plain text and is for development and testing, never production. It suits a test on your own computer. For a server on the internet use an option from the next section.
First change server.py. Replace the line mcp = FastMCP("Demo Server") with this block. When MCP_TOKEN is not set (for example the stdio server from Step 5), the server starts as before.
import os
from fastmcp.server.auth.providers.jwt import StaticTokenVerifier
auth = None
token = os.environ.get("MCP_TOKEN")
if token:
auth = StaticTokenVerifier(
tokens={token: {"client_id": "me", "scopes": ["read:data"]}},
required_scopes=["read:data"],
)
mcp = FastMCP("Demo Server", auth=auth)
Then create a random token, keep it out of git, start the server with it, and test from a second terminal (set MCP_TOKEN there the same way).
Linux#
umask 077 openssl rand -hex 32 > token.txt echo "token.txt" >> .gitignore export MCP_TOKEN="$(cat token.txt)" uv run fastmcp run server.py --transport http --port 8000
In the second terminal (run export MCP_TOKEN="$(cat token.txt)" there first):
curl -i http://127.0.0.1:8000/mcp uv run fastmcp list http://127.0.0.1:8000/mcp --auth "$MCP_TOKEN"
Windows (PowerShell)#
function New-HexSecret { $b = New-Object byte[] 32; [Security.Cryptography.RandomNumberGenerator]::Fill($b); -join ($b | ForEach-Object { $_.ToString("x2") }) }
New-HexSecret | Set-Content -Encoding ascii token.txt
Add-Content .gitignore "token.txt"
$env:MCP_TOKEN = (Get-Content token.txt)
uv run fastmcp run server.py --transport http --port 8000
In the second terminal (run $env:MCP_TOKEN = (Get-Content token.txt) there first):
curl.exe -i http://127.0.0.1:8000/mcp uv run fastmcp list http://127.0.0.1:8000/mcp --auth $env:MCP_TOKEN
Mac (Terminal)#
Same commands as Linux (if openssl is missing, brew install openssl).
Check it worked. The request without a token must be refused; we expect an HTTP 401 status, but the docs do not print the output. The list with the token shows your tools. If the first request shows tools instead of an error, the token was not set in the server's terminal.
Tip: The docs say custom routes, such as a
/healthendpoint added with@mcp.custom_route, are never protected by the server's authentication. Use them only for harmless status checks.
Authentication for remote servers#
When the server leaves your computer, pick the row that matches what you already have. These are the classes in FastMCP's authentication docs.
| You have | Use | Notes from the docs |
|---|---|---|
| A login service that issues JWT tokens | JWTVerifier with jwks_uri, issuer, audience | Your server only checks tokens; keys can rotate |
| Services you control, one shared secret | JWTVerifier with algorithm="HS256", secret in public_key | A random secret of 32+ characters, never in git or logs |
| An identity provider with Dynamic Client Registration (WorkOS AuthKit, Descope) | RemoteAuthProvider, e.g. AuthKitProvider | Clients register themselves |
| GitHub, Google, Azure, which need a fixed app registration | OAuthProxy and providers such as GitHubProvider | Register an app once; give client ID and secret |
| Only a quick test | StaticTokenVerifier, DebugTokenVerifier | Development only |
Clients send Authorization: Bearer <token>; FastMCP's own client takes Client(url, auth="<token>") without the word Bearer. If a gateway in front enforces authentication instead, the docs say you must stop anyone reaching the server directly.
Step 8: Connect Claude Code and Open WebUI over HTTP#
With the server from Step 7 running, add it to Claude Code as an HTTP server. The header carries the token.
Linux#
claude mcp add --transport http fastmcp-demo-http http://127.0.0.1:8000/mcp --header "Authorization: Bearer $MCP_TOKEN"
Windows (PowerShell)#
claude mcp add --transport http fastmcp-demo-http http://127.0.0.1:8000/mcp --header "Authorization: Bearer $env:MCP_TOKEN"
Mac (Terminal)#
Same command as Linux.
Check it worked. claude mcp get fastmcp-demo-http reports the connection, and /mcp lists the tools. Claude Code saves the header in its own settings, so treat that file like a password. Remove the test servers with claude mcp remove fastmcp-demo and claude mcp remove fastmcp-demo-http.
Open WebUI. It supports MCP servers that speak Streamable HTTP, which is what FastMCP's HTTP mode is. Our Open WebUI MCP guide has the full setup; in short, from Open WebUI's docs:
- Sign in as an admin (only admins can add MCP servers), open Settings, Admin, Integrations, and under External Tool Servers choose Add Connection.
- Set Type to MCP (Streamable HTTP), not OpenAPI.
- Enter the URL, for example
http://host.docker.internal:8000/mcpwhen Open WebUI runs in a container and your server runs on the same machine (the docs saylocalhostinside a container means the container). - For Auth choose Bearer and paste the token. The docs warn that Bearer with an empty key sends an empty header, and many servers reject it.
- Use a model that is good at tool calling; the docs say a weak model may ignore tools even when the connection works.
On Linux, a container cannot reach a server that listens only on 127.0.0.1. Start it with --host 0.0.0.0, keep the token on, and firewall the port. This is general Docker behaviour, not from the FastMCP or Open WebUI docs.
Put it behind HTTPS (with or without Traefik)#
Skip this while only you use the server on the same computer. Use it when other devices connect: the server speaks plain HTTP, so a token alone travels in clear text. Keep FastMCP on 127.0.0.1 and let a proxy on the same machine do HTTPS.
With Traefik#
FastMCP is a Python program, not a container, so there are no labels. If you already run Traefik, add a file-provider service that points to http://<this-computer>:8000 as in the Traefik file provider docs, and check that streamed answers arrive (we did not test Traefik with FastMCP). Otherwise use Caddy.
Without Traefik: Caddy#
Caddy gets and renews its own certificates. Its docs describe automatic Let's Encrypt certificates for a public domain (ports 80 and 443 must reach it) and tls internal for a local certificate at home. Caddy passes the original Host header through and flushes event-stream responses at once, which MCP streaming needs. Create a Caddyfile. For a public domain with a DNS record pointing at the server:
mcp.example.com {
reverse_proxy localhost:8000
}
For a home-only name:
mcp.home.arpa {
tls internal
reverse_proxy localhost:8000
}
Our Caddy guide has the full walk-through, including trusting Caddy's local root certificate.
Linux#
Caddy's install page gives the official Debian and Ubuntu repository (other distributions are listed there):
sudo apt install --yes debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy
The package runs Caddy as a service that reads /etc/caddy/Caddyfile. Put your Caddyfile there, then sudo systemctl reload caddy.
Windows (PowerShell)#
Download the Windows build from the Caddy releases (open "Assets"), then in the folder with your Caddyfile:
caddy run --config Caddyfile
Mac (Terminal)#
Homebrew is a community-maintained route on Caddy's install page:
brew install caddy caddy run --config Caddyfile
For tls internal, every device must trust Caddy's local root certificate: caddy trust does it on the Caddy machine. Claude Code reads the operating system's certificate store (native installer), and its docs name NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem for extra roots. Optional hardening in FastMCP: pass host_origin_protection=True and allowed_hosts=["mcp.example.com"] to mcp.run(...). It is off by default, and if you turn it on without your public name in allowed_hosts, every request fails (see Common mistakes).
Check it worked. curl -I https://mcp.example.com/mcp returns an HTTP status line over HTTPS. The exact code is not documented; a certificate or connection error is the sign of a problem. Then add the server to Claude Code again with the https address.
Tip: With nginx instead, the docs call buffering "the most common issue" for FastMCP: set
proxy_buffering off,proxy_http_version 1.1, an emptyConnectionheader and a longproxy_read_timeout(the docs use 300 seconds), or progress updates and results never arrive. Caddy needs none of that.
Security and testing#
- Bind to localhost.
fastmcp rundefaults to127.0.0.1. Use--host 0.0.0.0only with a token on and the port blocked from the internet. - Secrets in the environment, not in the file. Read them with
os.environ, keeptoken.txtin.gitignore, and on Linux and Mac keep it private (umask 077, as in Step 7). - Tools run as you. Whatever a tool can do, the AI can do. Keep tools narrow, mark read-only ones with
annotations={"readOnlyHint": True}(a documented option), and be careful with tools that run commands or touch files. - Test as a program. The testing docs use pytest with FastMCP's client (
async with Client(transport=mcp) as client, thenclient.call_tool(...)), pluspytest-asyncio. - Status check. Add
@mcp.custom_route("/health", methods=["GET"])andcurlit.
Common mistakes#
Each row comes from the FastMCP docs or a real issue (state as read in November 2026). The last row is about AI assistants.
| Mistake | Why it happens | Do this instead |
|---|---|---|
print() in a stdio server, then nothing shows | With stdio, standard output is the protocol channel (maintainer's answer in issue #3278, closed February 2026) | Log with await ctx.info(...), Python's logging, or print(..., file=sys.stderr) |
A tool written with yield instead of return | Same issue #3278: an async generator does not run as the author expected | Use return |
Setup code in the if __name__ == "__main__": block | fastmcp run and fastmcp dev inspector skip that block (docs warning) | Put setup in a factory function: fastmcp run server.py:create_server |
HTTP on 0.0.0.0 without authentication | The default is auth=None, so anyone who can reach the port can call every tool | Add a verifier (Step 7), use HTTPS, firewall the port |
StaticTokenVerifier for a real service | Easy to copy; the docs say it keeps plain-text tokens and must not be used in production | JWTVerifier or an OAuth provider (table above) |
Host check turned on behind a proxy, then 421 Misdirected Request on every call | Issue #4468 (closed July 2026): a proxy that rewrites Host hides the public name; uvicorn's --proxy-headers does not help | Put your public name in allowed_hosts, or keep a proxy that passes the original Host (Caddy does) |
| OpenAPI instead of MCP in Open WebUI, or Bearer with an empty key | Open WebUI's docs: MCP settings in an OpenAPI connection break the page; an empty Bearer key sends an empty header | Type MCP (Streamable HTTP); None, or Bearer with the key filled in |
| Trusting an AI assistant's FastMCP example | Assistants copy old tutorials: from mcp.server.fastmcp import FastMCP (the FastMCP 1.0 copy in the SDK), host and port inside FastMCP(...), ctx.sample() or ctx.list_roots() (removed in FastMCP 4), transport="sse" (legacy). Our assessment from the upgrade guide, not a measured test | Import from fastmcp import FastMCP, pass host and port to mcp.run(transport="http", ...), check each call at gofastmcp.com, and give the assistant gofastmcp.com/llms.txt |
Tip: After every change to a tool, run
uv run fastmcp list server.pyand onefastmcp call. It catches a broken signature before an AI client reports a vague "failed to connect".
Tip: When Claude Code shows "Failed to connect", read the detail line:
claude mcp get <name>adds the HTTP status or error text. A wrong path in the stdio command and a missing token look different there.
Troubleshooting#
| Problem | Solution |
|---|---|
claude mcp add saves the server but it does not connect | Run the command after the -- by hand in a terminal and fix the error; use absolute paths |
| Open WebUI says it failed to connect | Check the type (MCP, not OpenAPI), the URL (host.docker.internal from a container), and Auth (None, or Bearer with a key) |
| 401 from your own server | Token missing or wrong; the client needs the same value the server was started with |
| Streaming results never arrive behind nginx | proxy_buffering off and the other settings in the HTTPS section |
| A tool is missing from the list | Missing decorator, unsaved file, or the function sits in the __main__ block |
import fastmcp fails after a pip upgrade | pip install --force-reinstall fastmcp; if that fails, pip uninstall -y fastmcp fastmcp-slim, then install again |
Exact error texts#
✘ Failed to connect is the status Claude Code shows for a server it could not reach; the detail line after it names the HTTP status or error code (Claude Code docs).
421 Misdirected Request on every call while /health works is the symptom reported in issue #4468.
Known bugs (open on the day we read them)#
- #2837 (January 2026): a stdio server started by hand with
python server.pyneeds several Ctrl-C presses and prints tracebacks; a commenter says the bare MCP SDK does the same. Claude Code starts and stops stdio servers for you, so it matters only when you test by hand. - #4192 (May 2026): on Windows, one reporter's HTTP server hung after about 12 sequential client sessions. Another tester could not reproduce it in runs of 30 and 110 sessions, so it may depend on the machine. If it freezes, restart it; there is no confirmed fix.
Updates and backups#
Update. Read the changelog first; releases come every few days, and 4.2.0 alphas already exist (pip and uv skip pre-releases unless you ask). Then change the pin:
uv add "fastmcp==<NEW_VERSION>" uv run fastmcp list server.py
uv add "fastmcp==<NEW_VERSION>" uv run fastmcp list server.py
From 3.x, FastMCP's upgrade guide says most servers run unchanged and lists the breaks.
Back up. FastMCP holds no data of its own. Keep the project folder (server.py, pyproject.toml, uv.lock) in git. The token is a secret, so keep a copy in your password manager instead. A dated archive without the virtual environment, on Linux and Mac:
mkdir -p ~/backups tar --exclude=.venv --exclude=token.txt -czf ~/backups/fastmcp-demo-$(date +%F).tar.gz -C ~ fastmcp-demo
On Windows PowerShell:
New-Item -ItemType Directory -Force $HOME\backups | Out-Null Get-ChildItem "$HOME\fastmcp-demo" -Exclude .venv,token.txt | Compress-Archive -DestinationPath "$HOME\backups\fastmcp-demo-$(Get-Date -Format yyyy-MM-dd).zip" -Force
Schedule it with cron at 03:00 on Linux and Mac, or Windows Task Scheduler.
Restore test. Extract the archive into a new folder, then run uv sync and uv run fastmcp list server.py there. If the tools list, the backup works.
Keep it running. The docs give a systemd service for Linux only (uvicorn on the ASGI app from mcp.http_app(), Restart=always). For Windows and Mac they give no recipe; use your system's own service tool.
Performance and resources#
- No published figures. The FastMCP docs give no memory or speed numbers, and we measured none.
- Several workers. The docs say you must turn on stateless mode (
fastmcp run ... --stateless, orFASTMCP_STATELESS_HTTP=true) so any worker can answer any request. - Long tools. Proxies close idle connections; for tools that run for minutes the docs describe SSE polling with an event store.
- Watch it. Use the
/healthroute plustop, Activity Monitor or Task Manager.
FAQ#
Is FastMCP the same as the official MCP Python SDK? They are related. FastMCP 1.0 was folded into the official SDK in 2024; the standalone fastmcp package is the actively maintained, much larger framework, and FastMCP 4 is built on SDK version 2.
Do I need a GPU or Docker? No. It is an ordinary Python program, and the docs name no ready-made Docker image.
Can one server work with Claude Code and Open WebUI at once? Yes, in HTTP mode: both are clients of the same URL. stdio serves one client per started process.
Is the project still maintained? Yes. The repository is not archived, the newest release is from November 2026, and fixes also go to the 3.x line.
Sources#
- FastMCP documentation - read November 2026: installation, quickstart, running your server, HTTP deployment, authentication, CLI client, FAQ
- FastMCP on GitHub (Apache 2.0; moved from
jlowin/fastmcp) and fastmcp on PyPI - read November 2026 - GitHub issues in PrefectHQ/fastmcp: #3278, #4468, #2837, #4192 - read November 2026
- Claude Code docs: MCP and network configuration - read November 2026
- Open WebUI MCP docs, uv and Caddy - read November 2026
- Related guides: Open WebUI MCP, REA MCP, AnythingMCP, Claude Code, Caddy, Tailscale
Checked against the official docs on 2026-11-05.