DEV Community

Jansen003
Jansen003

Posted on

## How to Build a Python MCP Server for Claude in 30 Minutes

What is MCP?

MCP (Model Context Protocol) is Anthropic's protocol for connecting AI models to external tools. Think of it as USB-C for AI — one standard plug that works with everything.

With MCP, Claude can:

  • Read and write files on your computer
  • Query databases
  • Browse the web
  • Interact with APIs
  • Run shell commands

The ecosystem is growing fast. The official MCP servers repo has 86k stars. But there are gaps — especially in Python.

The Gap

Most MCP servers are written in JavaScript or Go. Python developers have very few options for database access, file operations, and other common tasks.

I wanted Python MCP servers. So I built mcp-database — a multi-database MCP server supporting SQLite, PostgreSQL, and MySQL.

mcp-database

pip install mcp-database
claude mcp add mcp-database -e MCP_DATABASE_URL=sqlite:///your.db -- mcp-database
Enter fullscreen mode Exit fullscreen mode

Now you can ask Claude things like "What tables are in my database?" or "Query the top 10 orders by amount."

8 tools: list_tables, get_table_info, get_schema, query, execute, sample_rows, search_tables, list_databases.

Key design decisions:

  • Read-only by default — safe for production databases
  • Uses official mcp SDK (FastMCP) — not reinventing the wheel
  • Multi-database support — one server for SQLite, PostgreSQL, MySQL

How to Build an MCP Server in Python

The MCP Python SDK makes it surprisingly simple. Here is the minimal working server:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-server")

@mcp.tool()
def hello(name: str) -> str:
    # Docstring becomes the tool description
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run()
Enter fullscreen mode Exit fullscreen mode

That is it. The @mcp.tool() decorator turns any Python function into an MCP tool. Type hints become the input schema automatically.

For database servers, the interesting part is the lifespan pattern — managing connections on startup/shutdown:

from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from dataclasses import dataclass
from mcp.server.fastmcp import FastMCP, Context

@dataclass
class AppContext:
    db: Database

@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
    db = await Database.connect()
    try:
        yield AppContext(db=db)
    finally:
        await db.disconnect()

mcp = FastMCP("DB Server", lifespan=app_lifespan)

@mcp.tool()
def query(sql: str, ctx: Context) -> str:
    db = ctx.request_context.lifespan_context.db
    return db.execute(sql)
Enter fullscreen mode Exit fullscreen mode

What I Learned

  1. The official SDK is good. FastMCP handles all the protocol details. You just write Python functions.

  2. Security matters. A database MCP server that allows arbitrary writes is dangerous. Read-only by default, explicit opt-in for writes.

  3. Type hints are your API. The SDK converts Python type hints to JSON Schema automatically. Good types = good tool descriptions.

  4. The ecosystem needs Python servers. Every time I searched for a Python MCP server, I found nothing. The demand is there, the supply is not.

Links


The MCP ecosystem is still early. If you are a Python developer, now is a great time to build MCP servers. The bar is low and the demand is high.

What MCP server would you find most useful? Let me know in the comments.

Top comments (0)