# Build your first MCP server in Python and use it in Claude Desktop

> Write a small Model Context Protocol server with the official Python SDK, expose a tool, and connect it to Claude Desktop so Claude can call it.

Level: Advanced
Tool: Claude
Category: Building
Time: About 35 minutes
Checked: 2026-10-15
Tools: [MCP docs](https://modelcontextprotocol.io/docs/develop/build-server), [Claude Desktop](https://claude.ai/download)
HTML page: https://easyaihowtos.com/guides/build-an-mcp-server

MCP lets Claude and other AI apps use your own tools. In this guide you build a working MCP server in about 30 lines of Python and plug it into Claude Desktop. Terms like server, host, and stdio are explained as you go.

## What you need

- Python 3.10 or newer
- The uv package manager (installed in step 1)
- Claude Desktop installed and signed in

## Steps

### 1. Know what you're building

**MCP (Model Context Protocol)** is an open standard for connecting AI apps to tools and data. An **MCP server** is a small program that offers **tools** (functions the AI can call, with your approval). An **MCP host**, such as Claude Desktop, starts your server and passes Claude's tool calls to it. This server will count words and characters in text.

### 2. Set up the project

Install uv, then create a project and add the MCP SDK (version 2.0 or newer, per the official tutorial):
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
uv init textstats && cd textstats
uv venv && source .venv/bin/activate
uv add "mcp[cli]"
```

### 3. Write the server

Save this as `server.py`. Type hints and the docstring become the tool's description and input schema (the rules for what arguments it accepts).
```python
import logging
from mcp.server import MCPServer

logger = logging.getLogger(__name__)
mcp = MCPServer("textstats")

@mcp.tool()
def text_stats(text: str) -> str:
    """Count words, characters, and sentences in a piece of text.

    Args:
        text: The text to analyze
    """
    words = len(text.split())
    sentences = sum(text.count(p) for p in ".!?") or 1
    logger.info("Analyzed %d words", words)
    return f"Words: {words}\nCharacters: {len(text)}\nSentences: {sentences}"

if __name__ == "__main__":
    mcp.run(transport="stdio")
```

### 4. Never print to stdout

This server talks over **stdio**: the host sends messages through the program's standard input and reads replies from standard output. A stray `print()` corrupts those messages. Use `logging` (which writes to stderr) as shown.

### 5. Register it in Claude Desktop

Open Claude Desktop's config file: `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%AppData%\Claude\claude_desktop_config.json` on Windows (create it if missing). Add your server with an absolute path:
```json
{
  "mcpServers": {
    "textstats": {
      "command": "uv",
      "args": ["--directory", "/ABSOLUTE/PATH/TO/textstats", "run", "server.py"]
    }
  }
}
```
If Claude can't find `uv`, put its full path (from `which uv`) in `command`.

### 6. Restart and test

Fully quit Claude Desktop (Cmd+Q on Mac, or Quit from the system tray on Windows) and reopen it. Open the **+** menu by the message box and look under **Connectors** for `textstats`. Then ask: "Use text_stats on this paragraph: ..." and approve the tool call.

## Tips

- If the server doesn't appear, check the logs: `~/Library/Logs/Claude/mcp*.log` on macOS.
- Write clear docstrings. The model decides when to call a tool from its name and description.
- The same server works with other MCP hosts, such as Claude Code and other MCP-compatible editors.

## FAQ

### Can I write MCP servers in other languages?

Yes. There are official SDKs for TypeScript, Java, Kotlin, C#, Go, Ruby, Rust, and more. The official tutorial has a version for each.

### What's the difference between tools, resources, and prompts?

Tools are functions the model calls. Resources are readable data, like files. Prompts are reusable templates the user picks.

### Is it safe to give Claude tools?

Hosts ask for your approval before calling tools. Still, only expose actions you'd be comfortable with, and avoid tools that delete or send things without checks.

---

This guide is from Easy AI How-To (https://easyaihowtos.com). It is independent of the tools named above. Screens and free-plan limits change, so check the date before you rely on a button name.
