
How to Build and Connect a Custom Model Context Protocol (MCP) Server in 5 Minutes
Minimal Python FastMCP Server Implementation
The Model Context Protocol (MCP) is an open JSON-RPC standard that enables AI assistants to execute local tools and query databases securely.
To build and run an MCP server in Python right now, install FastMCP and the official CLI inspector:
pip install "mcp[cli]>=1.2.0" "fastmcp>=0.4.0"
Create server.py:
from fastmcp import FastMCP
import shutil
mcp = FastMCP("SystemUtilities")
@mcp.tool()
def get_disk_usage(path: str = "/") -> str:
"""Return disk usage statistics for the given filesystem path."""
total, used, free = shutil.disk_usage(path)
return f"Total: {total // (2**30)}GB | Used: {used // (2**30)}GB | Free: {free // (2**30)}GB"
if __name__ == "__main__":
mcp.run()
Run and test the server immediately in your terminal inspector:
mcp dev server.py
1. Connecting Your MCP Server to AI Clients
Once your server runs locally, register it with your primary AI coding assistant by specifying the absolute path to your Python interpreter and server file.
Configuration for Claude Code and Claude Desktop
Add this configuration block to ~/.claude/mcp.json or claude_desktop_config.json:
{
"mcpServers": {
"system-utils": {
"command": "python3",
"args": ["/home/user/scripts/server.py"]
}
}
}
Configuration for Cursor and Antigravity
In your project root or global settings (.cursor/mcp.json or mcp_config.json):
{
"mcpServers": {
"system-utils": {
"type": "stdio",
"command": "python3",
"args": ["/home/user/scripts/server.py"]
}
}
}
If your client fails during initial handshake, see our guide on how to fix MCP connection closed STDIO errors to isolate broken JSON-RPC frames.
2. FastMCP vs Standard Low-Level SDK Comparison
While the official MCP Python SDK provides the raw low-level mcp protocol bindings, FastMCP wraps boilerplate schema generation and transport initialization into standard Python decorators.
| Feature / Dimension | FastMCP (Recommended) | Official Low-Level MCP SDK |
|---|---|---|
| Setup Time | Under 2 minutes | 15 to 20 minutes of boilerplate |
| Type Hinting & Schema Generation | Automatic from Python docstrings | Manual Pydantic / JSON Schema dicts |
| Transport Support | STDIO, SSE, and Unix Domain Sockets | Requires custom transport listeners |
| Context Window Protection | Built-in output truncation hooks | Manual token truncation required |
| Best Production Fit | Rapid custom tools & internal APIs | Custom C++ wrappers & legacy systems |
For production database integrations using this SDK pattern, review our walkthrough on building a PostgreSQL and SQLite MCP server.
3. Best Practices for Production MCP Tools
Writing tools for LLMs requires different design patterns than writing traditional REST APIs.
1. Protect STDIO from Standard Print Statements
STDIO transport relies on standard output (stdout) to exchange clean JSON-RPC packets. Calling raw print() inside your Python tools injects unstructured strings into the protocol stream, corrupting message framing. Use sys.stderr.write() or the standard logging module configured to stderr:
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logger = logging.getLogger("mcp-server")
@mcp.tool()
def execute_safe_query(query: str) -> str:
"""Execute a sanitized query and report status."""
logger.info("Processing query: %s", query)
return "Query executed successfully"
2. Guard Against Asynchronous Deadlocks
If an external tool hangs on an unresponsive subprocess or remote database lock, your AI coding agent enters an infinite wait loop. If you run multiple concurrent tools or long-running shell scripts, follow our troubleshooting instructions to fix MCP tool timeout deadlocks in FastMCP on Linux.
3. Implement Strict Network Isolation for Remote Transports
When moving from local STDIO pipes to network-accessible SSE (Server-Sent Events) or HTTP endpoints, verify that your endpoints do not allow DNS rebinding or unauthorized internal network requests. Review our security architecture guide on securing remote MCP servers against SSRF.
4. Route Tools Across Multi-Agent Workflows
As your server inventory expands beyond single utilities to specialized memory, database, and terminal tools, avoid cluttering a single agent context. For persistent cross-session vector recall without external cloud databases, see our guide on building a local MCP memory server with sqlite-vec.
Summary Checklist
- Install
fastmcpto eliminate boilerplate JSON Schema definitions. - Expose functions using the
@mcp.tool()decorator with concrete docstrings and type hints. - Direct all debugging logs to
stderrto avoid corrupting STDIO JSON-RPC streams. - Test your server using
mcp dev server.pybefore linking to your editor. - Connect your server file using absolute paths in
mcp.json.