Building Your Own MCP Server
What This Article Covers
- What the Model Context Protocol (MCP) is.
- How MCP servers are structured.
- How to define tools, resources, and prompts.
- Available transport mechanisms.
- A simple example in TypeScript and Python.
- Best practices and common pitfalls.
Introduction: Building Your Own MCP Server
The Model Context Protocol (MCP) is an open standard for connecting AI agents to external data sources and tools. An MCP server provides functions that an MCP client can invoke. By building your own MCP server, you can integrate company-specific databases, APIs, or local tools into AI workflows.
This article walks you through creating a simple MCP server from scratch. It’s written for developers and self-hosters who want to make their own tools accessible to agents.
What Is MCP?
MCP defines standardized communication between an MCP client and an MCP server. The client is typically an AI agent or chat interface. The server provides:
- Tools: Functions the agent can call.
- Resources: Data the agent can read.
- Prompts: Templates for specific tasks.
- Sampling: Reverse requests from the server to the client.
Communication happens over JSON-RPC 2.0.
Key Concepts
- MCP Host: An application containing an MCP client, such as Claude Desktop or an agent framework.
- MCP Client: Communicates with one or more MCP servers.
- MCP Server: Provides tools, resources, and prompts.
- Tool: An executable function with a name, description, and JSON schema.
- Resource: An addressable data source, such as a file or database table.
- Transport: The communication pathway, usually stdio or Server-Sent Events over HTTP.
- JSON-RPC: A lightweight protocol for remote procedure calls.
Transport Mechanisms
stdio
The server runs as a subprocess of the client. Communication happens through standard input and output. This is particularly straightforward for local tools.
SSE over HTTP
The server runs as its own service. The client connects via HTTP and receives messages through Server-Sent Events. This works well for remote setups or multiple clients.
Structure of an MCP Server
An MCP server must provide the following:
- Initialization: Exchange protocol version and capabilities.
- Capabilities: Announce which tools, resources, and prompts are available.
- Tool Handlers: Execute functions for each tool.
- Resource Handlers: Return resources on demand.
- Error Handling: Send clear error messages to the client.
Simple Example in Python
This server offers a get_current_time tool that returns the current time.
# server.py
import json
import sys
from datetime import datetime
def send_message(msg):
payload = json.dumps(msg)
print(payload, flush=True)
def handle_request(req):
method = req.get("method")
id_ = req.get("id")
if method == "initialize":
return {
"jsonrpc": "2.0",
"id": id_,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "time-server", "version": "1.0.0"},
},
}
if method == "tools/list":
return {
"jsonrpc": "2.0",
"id": id_,
"result": {
"tools": [
{
"name": "get_current_time",
"description": "Returns the current time.",
"inputSchema": {
"type": "object",
"properties": {},
},
}
]
},
}
if method == "tools/call":
name = req["params"]["name"]
if name == "get_current_time":
now = datetime.now().isoformat()
return {
"jsonrpc": "2.0",
"id": id_,
"result": {
"content": [{"type": "text", "text": f"Current time: {now}"}]
},
}
return {"jsonrpc": "2.0", "id": id_, "error": {"code": -32601, "message": "Tool not found"}}
return {"jsonrpc": "2.0", "id": id_, "error": {"code": -32601, "message": "Method not found"}}
def main():
for line in sys.stdin:
line = line.strip()
if not line:
continue
req = json.loads(line)
resp = handle_request(req)
send_message(resp)
if __name__ == "__main__":
main()
The server reads JSON-RPC requests line by line from stdin and writes responses to stdout.
Setting Up in Claude Desktop
Once you’ve built the server file, you can register it in Claude Desktop. On macOS, the configuration lives at ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"time": {
"command": "python3",
"args": ["/path/to/server.py"]
}
}
}
After restarting Claude Desktop, the get_current_time tool becomes available.
MCP SDKs
Rather than building everything by hand, you can use SDKs:
- Python SDK:
mcpon PyPI. - TypeScript SDK:
@modelcontextprotocol/sdkon npm. - Java SDK:
mcp-java.
These SDKs handle protocol versions, transport, and JSON-RPC details for you.
Best Practices
- Clear tool descriptions: The language model decides whether to use a tool based on its description.
- Secure input validation: Validate every tool argument.
- Meaningful error messages: Return errors that help the agent respond appropriately.
- Statelessness: Tools should avoid hidden state where possible.
- Permissions: The server should only perform operations it’s authorized to do.
- Logging: Write output to stderr so stdout stays clean for JSON-RPC.
Common Pitfalls
- Malformed JSON-RPC: Missing
jsonrpcoridfields. - Polluted stdout: Debug output on stdout instead of stderr.
- Missing capabilities: Client doesn’t know which tools are available.
- Unclear tool descriptions: Model calls the wrong tool.
- No input validation: Malicious input causes errors.
- Transport mixing: Don’t mix stdio and HTTP in the same server.
Further Resources
- BotServ.de MCP Basics
- BotServ.de MCP Client
- BotServ.de Running MCP Locally
- BotServ.de Tool-Calling Basics
FAQ: Building Your Own MCP Server
Do I need a special framework? No. An MCP server can be implemented in any language that speaks JSON-RPC. SDKs make it easier to get started.
Can an MCP server offer multiple tools?
Yes. tools/list returns an array of all available tools.
How secure is an MCP server? It runs locally and only executes what’s defined in the code. Still, validate every input and restrict permissions.
What’s the difference between stdio and SSE? stdio is simpler for local processes; SSE suits network or container setups.
Can I run an MCP server in Docker? Yes. In that case, SSE over HTTP or a wrapper that provides stdio to the client works well.
Sources and Further Reading
- MCP Specification: https://modelcontextprotocol.io/
- MCP Python SDK: https://github.com/modelcontextprotocol/python-sdk
- MCP TypeScript SDK: https://github.com/modelcontextprotocol/typescript-sdk
Summary: Building Your Own MCP Server
Your own MCP server extends AI agents with specialized tools and data sources. The Model Context Protocol relies on JSON-RPC and supports both stdio and HTTP transport. Clear tool descriptions, secure input validation, clean error handling, and proper separation of stdout and stderr are essential. Once you understand the protocol, you can safely integrate company-specific functionality into local agent workflows.


