Writing one simple MCP server lets you expose a custom tool to every Model Context Protocol client at once, so the same function works in Claude Code, Cursor, and any other compatible app without rewriting it for each. The Model Context Protocol is a standard way to hand context and callable tools to large language models, and Python's FastMCP framework reduces the whole thing to a decorated function and a few lines of boilerplate.

Quick Answer

A working MCP server in Python needs the official SDK (version 1.2.0 or higher), one function wrapped in an @mcp.tool() decorator, and a single line to run it over stdio. FastMCP reads your type hints and docstring to generate the tool definition automatically, so a useful first server is realistically about 15 lines of code.

What an MCP server actually does

An MCP server publishes capabilities that a client can discover and use. There are three kinds: tools, which are functions the model can call; resources, which are file-like data the client can read; and prompts, which are reusable templates. Tools are where most people start because they let the model take an action, such as querying a database, hitting an internal API, or doing a calculation, and return the result straight back into the conversation. Because the protocol is shared, you build the tool once and any MCP-aware client consumes it the same way.

This kind of local AI tooling runs comfortably on a capable desktop, and the AI PC range at Evetech covers machines with the memory headroom to run models and your own MCP servers side by side.

Build it step by step

  1. Set up the environment. Create a project folder and a virtual environment, then install the SDK. Using the uv package manager, uv add "mcp[cli]" pulls in everything including FastMCP. The mcp[cli] extra gives you the command-line tools for testing.
  2. Create the server object. In a new file, import FastMCP and instantiate it with a name: from mcp.server.fastmcp import FastMCP then mcp = FastMCP("Demo"). The name is how clients identify your server.
  3. Define a tool. Decorate a normal Python function with @mcp.tool(). Give it typed arguments and a clear docstring, because FastMCP turns those into the schema the model sees. A simple example is an add(a: int, b: int) -> int function that returns the sum, with a one-line docstring describing what it does. The quality of that docstring directly affects how well the model uses the tool.
  4. Run the server. Add if __name__ == "__main__": mcp.run() at the bottom. By default it speaks over stdio, which is exactly what local clients expect. One critical rule for stdio servers: never use print() or write anything to stdout inside your tool, because that corrupts the JSON-RPC messages and breaks the connection. Use logging to a file or stderr instead.
  5. Test in isolation. Run the MCP inspector against your file before wiring it into a client. It lets you list the server's tools and call them manually, so you confirm the tool works on its own rather than debugging through a chat interface.
  6. Connect a client. Add the server to your client's config, pointing it at your Python file. In Claude Code or Cursor, that means a small JSON entry with the command and arguments to launch the script. Restart the client and your tool appears in its tool list.

Choosing a transport

stdio is the right default for a server that runs locally on the same machine as the client, and it is the simplest to set up. When you want a server reachable over a network, the SDK also supports Streamable HTTP, which suits a server you host once and let multiple machines reach. Start with stdio while you learn, then move to HTTP only when you genuinely need remote access. Note that the SDK is evolving quickly, with a version 2 in development through mid-2026, so pin your dependency version and read the changelog before upgrading a working server.

Frequently Asked Questions

What language should I use to build an MCP server?

Python and TypeScript both have official, mature SDKs. Python with FastMCP is the gentlest starting point because type hints and docstrings generate the tool schema for you, so there is very little boilerplate to get a first tool running.

Why must I avoid printing to stdout in an MCP server?

For stdio-based servers, the client and server communicate over stdout using JSON-RPC messages. Anything you print to stdout gets mixed into that stream, corrupts the messages, and breaks the server. Log to a file or to stderr instead.

Do I need to write a separate server for Claude Code and Cursor?

No. That is the main benefit. Both are MCP-compatible clients, so one server works with both. You only change a small config entry in each client to point at the same server file.

What hardware do I need to develop and run MCP servers?

The server code itself is lightweight. The demand comes from any local AI models you run alongside it, which benefit from a modern CPU and generous RAM. An AI-focused PC with ample memory keeps a model and several servers responsive at once.

How do I test a server before connecting it to a client?

Use the MCP inspector that ships with the SDK's CLI tools. It connects directly to your server, lists the available tools, and lets you call them with sample inputs, so you can confirm behaviour without going through a chat client.

If you are building AI tooling locally, the machine matters as much as the code. See the AI PC range at Evetech (https://www.evetech.co.za/PC-Components/ai-pcs-445) or browse the PC best sellers (https://www.evetech.co.za/pc-best-sellers/x/1912) for a build with the memory to run your models and MCP servers together.