MCP Server Tutorial: Build Your Own AI Tool from Scratch

๐Ÿ“˜ Tutorials 2026-07-19 3 min read

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.

๐Ÿ’ฌ Comments (0)

No comments yet. Be the first!

Login to comment