Build a Dynamic MCP Server: Notifications and Resource Templates on macOS

Most MCP servers are static: a fixed set of tools and resources, decided at startup. Two features let a server change shape at runtime. Resource templates serve a whole family of resources from one parameterized URI, so book://1, book://2, and book://999 all resolve without registering a resource per book. list_changed notifications let the server tell a connected client that its tools, resources, or prompts have changed, so the client re-fetches instead of holding a stale list. ...

14 min

Design Great MCP Tools: Annotations and Semantics on macOS

A working MCP tool is not the same as a well-designed one. A model decides whether to call your tool, and a client decides whether to auto-run it or ask the user first, based entirely on what the tool says about itself: its name, its description, its parameters, and its annotations. Get those wrong and a read-only lookup gets a confirmation prompt, a destructive delete runs silently, or the model picks the wrong tool. ...

16 min

Return Structured Output from a FastMCP Server on macOS

A tool that returns only text makes every caller re-parse prose. The model reads "Denver is 21.5°C and clear" and has to extract the number again; a program has to write a regex. MCP’s structured output fixes this: a tool returns typed JSON in a structuredContent field, and advertises the shape up front as an output schema so callers know what to expect before they ever call it. This tutorial builds a small weather server with FastMCP whose tools return a Pydantic model, a nested collection, a bare primitive, and a hand-built result. You will see how FastMCP derives the output schema from a return-type annotation, fills in structuredContent automatically, validates every result against the schema, and how a client reads the typed value back. The stack is Mac-native: uv, make, and pytest. ...

16 min

Use Your MCP Server from VS Code, Cursor, and Zed on macOS

Register a FastMCP Server with Claude Desktop and Claude Code wired a server into the two Claude clients. The AI-assisted code editors speak MCP too — VS Code (Copilot agent mode), Cursor, and Zed — and each keeps its config in a different file, under a different key, in a slightly different shape. This article takes one stdio FastMCP server and connects it to all three. VS Code Cursor Zed File .vscode/mcp.json (or user config) .cursor/mcp.json (or ~/.cursor/mcp.json) ~/.config/zed/settings.json Top-level key servers mcpServers context_servers Entry shape type + command/args (or url) command/args (or url) command/args/env (or url/headers) Scope workspace and user project and global global only Two things are common to all three, and to the Claude clients before them: ...

10 min

Publish a FastMCP Server to PyPI and Run It Anywhere with uvx

Two earlier articles bookend this one. Package and Distribute a FastMCP Server as a uvx Tool gets you to uvx macmcp in your own terminal, and Register a FastMCP Server with Claude Desktop and Claude Code wires a server into clients, but launches it from a local path or git+https. This closes the loop: publish the package to PyPI once, and from then on anyone — and any MCP client — runs it with uvx <name>, no clone, no virtualenv, no path. ...

12 min

Add Observability to a FastMCP Server on macOS

A server in production has to answer three questions: is it up, what is it doing, and when something breaks, why. This tutorial adds the three observability pillars to a FastMCP server — structured logs, a health check, and metrics — using only the standard library plus two FastMCP primitives (middleware and custom routes). The stack is Mac-native: uv, make, and pytest. The design keeps instrumentation out of the tools: Logging is a JSON formatter on the root logger, written to stderr. Metrics are a small in-process registry fed by one piece of middleware, so every tool is measured without touching its code. Health and metrics are exposed twice: as MCP resources (readable over any transport, including stdio) and as HTTP routes (/health, /metrics) for load balancers and Prometheus. The stdio trap. The stdio transport uses stdout for the MCP protocol itself. Anything else written to stdout — a stray print, a log line — corrupts the stream and breaks the client. All logging here goes to stderr, which is safe on both transports. This is the single most common way a working server mysteriously fails once a client connects to it over stdio. ...

16 min

Register a FastMCP Server with Claude Desktop and Claude Code on macOS

You have a working MCP server (see Build an MCP Server with FastMCP and Create and Deploy a FastMCP Server on macOS). A server on its own does nothing until a client connects to it. This tutorial wires one server into the two Claude clients you are most likely to use on a Mac: Claude Code (the CLI) and Claude Desktop (the chat app). They use different configuration systems, so each gets its own walkthrough, and the tricky remote case gets a mcp-remote bridge. ...

15 min

Secure a FastMCP Server with Clerk on macOS

In Add GitHub OAuth to a FastMCP Server you delegated login to GitHub. That is a good fit when your users already have GitHub accounts, but it ties your server to one social provider. This tutorial uses Clerk instead: a full authentication platform where you own the user directory. Clerk gives you email/password, magic links, social logins, and MFA behind a single OAuth authorization server, and FastMCP’s ClerkProvider plugs that server into your MCP server with a few lines of configuration. ...

16 min

Add an apps/ Folder to a uv Workspace: A Simple App and a FastAPI App

The previous tutorial built a uv workspace with a single packages/ folder holding a library and a CLI. That layout mixes reusable libraries and runnable programs in one directory. A common convention is to split them: packages/ for importable libraries, apps/ for deployable programs. This tutorial builds a workspace with both, where a shared greetings library in packages/ is consumed by two apps in apps/: a simple command-line app and a FastAPI web app. A root Makefile runs, serves, and tests every member. ...

12 min

Create a Python uv Workspace with a Shared Makefile

A uv workspace lets several related Python packages live in one repository, share a single lockfile and virtual environment, and depend on each other by name without publishing to a registry. This tutorial builds a two-package workspace: a greetings library and a cli application that imports it. A root Makefile drives sync, run, test, and inspection across every member with one command each. By the end you will have a reproducible layout where editing the library is immediately visible to the application, and make test runs every package’s tests in one pass. ...

11 min