MCP Server Tutorial: Build Your Own AI Tool from Scratch
MCP Server Tutorial: Build Your Own AI Tool from Scratch
💡 What You Will Learn
MCP Server Tutorial: Build Your Own AI Tool from Scratch
MCPWhat Is
Step 1InstallationMCP SDK
pip install mcp # Python MCP SDKsupports stdio and HTTP transport
# weather_mcp_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types
import httpx
from typing import Any
# MCP Server
server = Server("weather-server")
# DecoratorโโAI
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
return [
types.Tool(
name="get_weather",
description="",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": ""},
"units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
),
types.Tool(
name="get_forecast",
description="7",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string"},
"days": {"type": "integer", "maximum": 7}
},
"required": ["city"]
}
)
]
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict[str, Any]) -> list[types.TextContent]:
if name == "get_weather":
city = arguments["city"]
async with httpx.AsyncClient() as client:
resp = await client.get(f"https://api.weather.com/v1/{city}")
data = resp.json()
return [types.TextContent(type="text", text=json.dumps(data, ensure_ascii=False))]
elif name == "get_forecast":
city = arguments["city"]
days = arguments.get("days", 3)
# ...
return [types.TextContent(type="text", text=f"{city}{days}...")]
raise ValueError(f": {name}")
# StartServerstdioAI
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream, write_stream,
InitializationOptions(server_name="weather-server")
)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
// Claude Desktop Configurationclaude_desktop_config.json
{
"mcpServers": {
"weather-server": {
"command": "python",
"args": ["weather_mcp_server.py"]
}
}
}
// HTTPConfiguration
{
"mcpServers": {
"weather-server": {
"url": "http://localhost:8080/mcp"
}
}
}
# mcp_best_practice.py โ Error
from mcp.server import Server
import mcp.types as types
server = Server("enterprise-server")
TOKEN = "your-service-token"
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
try:
# Parameter
if "auth_token" not in arguments or arguments["auth_token"] != TOKEN:
return [types.TextContent(type="text", text="{\"error\": \"\"}")]
if name == "query_database":
sql = arguments.get("sql", "")
# SQL
if any(kw in sql.upper() for kw in ["DROP", "DELETE", "UPDATE"]):
return [types.TextContent(type="text", text="{\"error\": \"\"}")]
result = execute_readonly_query(sql)
return [types.TextContent(type="text", text=json.dumps(result, ensure_ascii=False))]
elif name == "search_knowledge_base":
query = arguments.get("query", "")
results = vector_db.search(query, top_k=5)
return [types.TextContent(type="text", text=json.dumps(results, ensure_ascii=False))]
except Exception as e:
return [types.TextContent(type="text", text=json.dumps({"error": str(e)}))]
raise ValueError(f": {name}")
|:----|:----|:------------| || Elasticsearch/Meilisearch | 100+ | || Google Drive/Dropbox | 30+ | || Salesforce/SAP | 20+ |
Related Articles
2026-07-20
Ollama vs LM Studio: Which Local LLM Runner Is Best for Beginners in 2026?
2026-07-19
LocalAI Deployment: Run LLMs Locally with Zero API Costs
2026-08-02
OpenTofu 2026: The Open Source Terraform Alternative for AI Infrastructure (29k Stars)
Written by our editorial team; tools listed here are tested or verified against public sources. Links point to official sites or GitHub repos for reference only โ no paid placements.
