How to Build Your First MCP Server in 2026

Published May 14, 2026 Β· 12 min read Β· By YunDu AI

The Model Context Protocol (MCP) is the standard way AI agents connect to external tools and data sources. Every major AI platform β€” Claude, ChatGPT, Cursor, Windsurf β€” now supports MCP. If you're building AI-powered tools, you need to know how to build MCP servers.

In this guide, you'll build a working MCP server from scratch using Python. No prior MCP experience needed.

πŸ“‹ Table of Contents

What is MCP?

MCP is a protocol that lets AI models interact with external tools, resources, and prompts. Think of it as a USB port for AI β€” any tool that speaks MCP can be plugged into any AI that supports MCP.

An MCP server exposes:

Why MCP matters in 2026: Microsoft's Playwright MCP has 32K+ stars. Figma's MCP has 14K+ stars. MCP is the standard for AI tool integration. Building MCP servers is a high-value skill.

Prerequisites

Step 1: Project Setup

mkdir my-first-mcp-server
cd my-first-mcp-server
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install mcp

Create the project structure:

my-first-mcp-server/
β”œβ”€β”€ src/
β”‚   └── my_server/
β”‚       β”œβ”€β”€ __init__.py
β”‚       β”œβ”€β”€ __main__.py
β”‚       └── server.py
β”œβ”€β”€ requirements.txt
└── README.md

Step 2: Define Your Server

Create src/my_server/server.py:

from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio

server = Server("my-first-server")

@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="hello",
            description="Say hello to someone",
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The person's name"
                    }
                },
                "required": ["name"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "hello":
        return [TextContent(
            type="text",
            text=f"Hello, {arguments['name']}! πŸ‘‹ Welcome to MCP."
        )]
    raise ValueError(f"Unknown tool: {name}")

Create src/my_server/__main__.py:

import asyncio
from .server import server, mcp

async def main():
    async with mcp.server.stdio.stdio_server() as (read, write):
        await server.run(read, write, server.create_initialization_options())

if __name__ == "__main__":
    asyncio.run(main())

Step 3: Add More Tools

Let's add a tool that does something useful β€” generate a timestamp:

from datetime import datetime, timezone

@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="hello",
            description="Say hello to someone",
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "Name"}
                },
                "required": ["name"]
            }
        ),
        Tool(
            name="timestamp",
            description="Get the current timestamp in various formats",
            inputSchema={
                "type": "object",
                "properties": {
                    "format": {
                        "type": "string",
                        "description": "Format: 'iso', 'unix', or 'readable'",
                        "enum": ["iso", "unix", "readable"]
                    }
                },
                "required": ["format"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "hello":
        return [TextContent(type="text", text=f"Hello, {arguments['name']}! πŸ‘‹")]
    
    if name == "timestamp":
        now = datetime.now(timezone.utc)
        fmt = arguments["format"]
        if fmt == "iso":
            result = now.isoformat()
        elif fmt == "unix":
            result = str(int(now.timestamp()))
        else:
            result = now.strftime("%B %d, %Y at %I:%M %p UTC")
        return [TextContent(type="text", text=result)]
    
    raise ValueError(f"Unknown tool: {name}")

Step 4: Test Your Server

Use the MCP Inspector to test:

npx @modelcontextprotocol/inspector python -m my_server

This opens a web UI where you can:

Step 5: Connect to Claude

Add to your Claude Code settings (~/.claude/settings.json):

{
  "mcpServers": {
    "my-server": {
      "command": "python",
      "args": ["-m", "my_server"],
      "cwd": "/path/to/my-first-mcp-server"
    }
  }
}

Now ask Claude: "What tools do you have?" and it will list your custom tools!

πŸŽ‰ Congratulations! You've built a working MCP server. Claude can now use your custom tools.

Deployment Options

Docker (Recommended)

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ src/
CMD ["python", "-m", "my_server"]

stdio Transport (Default)

Best for local development and Claude Code integration.

SSE Transport (Remote)

For cloud deployment, use Server-Sent Events:

# In your server.py
from mcp.server.sse import SseServerTransport

sse = SseServerTransport("/messages")
app = Starlette(routes=[sse.get_sse_endpoint(), ...])

Best Practices

  1. Clear tool descriptions β€” The AI reads these to decide when to use your tool
  2. Detailed input schemas β€” Use JSON Schema with descriptions for each property
  3. Handle errors gracefully β€” Return helpful error messages, not stack traces
  4. Keep responses concise β€” LLMs have context limits; don't return megabytes of text
  5. Test with MCP Inspector β€” Always test before deploying
  6. Add a good README β€” Include installation, usage, and configuration examples

What's Next?

Now that you can build MCP servers, here are ideas for your next project:

Want production-ready MCP servers? Check out our collection of 15 professional AI Skills for Claude, including MCP server development templates.
⭐ MCP Server Convert πŸ“¦ AI Skills Collection