Serve Resources Well from an MCP Server on macOS

Resources are the read side of MCP: addressable, cacheable data a client fetches by URI, separate from the tools that take action. Serving them well means more than returning a string. A resource has a MIME type, metadata a client shows in a picker, a choice between a fixed URI and a parameterized template, a text-or-binary body, and, for data that changes, a way to push updates instead of making clients poll. ...

12 min

Design MCP Prompts: Arguments, Templates, and Embedded Resources on macOS

Tools let a model do things; prompts let a user start things. An MCP prompt is a named, parameterized message template a client surfaces as a slash command or a menu entry — the user picks it, fills in a couple of arguments, and the client drops a ready-made conversation into the model. Most tutorials define one prompt in passing and move on. This one treats prompts as the subject. ...

11 min

Add Argument Completions to an MCP Server on macOS

When a user fills in a prompt argument or a resource URI in an MCP client, the client can offer autocomplete, the same way a shell completes a path. That only works if the server answers a completion/complete request with suggestions scoped to what the user has typed. Without it, the user guesses at valid values and finds out they were wrong only when the call fails. This tutorial adds completions to a small documentation server built with FastMCP. One handler serves suggestions for a prompt’s arguments and a resource template’s parameters, filters by the typed prefix, reads from the same data the server actually serves, and narrows one argument based on another (topics depend on the chosen language). The stack is Mac-native: uv, make, and pytest. ...

12 min

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