MCP Server Quickstart Guide

Overview

MCP (Model Context Protocol) is an open protocol designed to enable large language models (LLMs) to interact with external tools, data sources, and environments in a secure and structured way. In simple terms, MCP allows you to build servers (or "tools") that LLMs like Claude can call when they need information or need to take actions—such as fetching weather data, querying a database, or triggering a workflow.

Key Features of MCP:

  • Tool execution: LLMs can call functions you expose (e.g., get_forecast) via an MCP server.
  • Resources: LLMs can request access to file-like data (e.g., documents, images, APIs).
  • Prompts: Predefined templates to guide model interactions.
  • Transport-agnostic: Communication can happen over standard input/output, sockets, or other channels.
  • Secure-by-default: Tools are invoked only with user approval in supported clients.

Common Use Cases:

  • Connecting LLMs to APIs or databases
  • Automating admin tasks from within a chat interface
  • Powering intelligent agents (e.g., assistants, bots)
  • Customizing LLM behavior in desktop or enterprise environments

MCP Server Capabilities

This example walks you through building a basic MCP-compliant weather server. The server will expose two tools:

  • get-alerts: fetch weather alerts by U.S. state
  • get-forecast: fetch forecast data based on latitude and longitude

Prerequisites

Before starting:

  • Familiarity with Python or Node.js (depending on language used)
  • Python 3.10+ or Node.js 16+
  • MCP SDK installed (latest version)

Python Setup (with uv)

  1. Install uv
  2. Create the server project
uv init weather
cd weather
uv venv
source .venv/bin/activate  # Use .venv\Scripts\activate on Windows
uv add "mcp[cli]" httpx
touch weather.py

Windows:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

macOS/Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Building the Python Server

Start the server:

if __name__ == "__main__":
    mcp.run(transport='stdio')

Define tools:

@mcp.tool()
async def get_alerts(state: str) -> str:
    url = f"{NWS_API_BASE}/alerts/active/area/{state}"
    data = await make_nws_request(url)
    if not data or "features" not in data or not data["features"]:
        return "No active alerts or unable to fetch alerts."
    return "\n---\n".join(format_alert(f) for f in data["features"])

@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)
    if not points_data:
        return "Failed to retrieve forecast data."

    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)
    if not forecast_data:
        return "Unable to fetch detailed forecast."

    periods = forecast_data["properties"]["periods"]
    return "\n---\n".join(
        f"""{p['name']}:
Temperature: {p['temperature']}°{p['temperatureUnit']}
Wind: {p['windSpeed']} {p['windDirection']}
Forecast: {p['detailedForecast']}""" for p in periods[:5]
    )

Helper functions:

async def make_nws_request(url: str) -> dict[str, Any] | None:
    headers = {
        "User-Agent": USER_AGENT,
        "Accept": "application/geo+json"
    }
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, headers=headers, timeout=30.0)
            response.raise_for_status()
            return response.json()
        except Exception:
            return None

def format_alert(feature: dict) -> str:
    props = feature["properties"]
    return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""

Initialize the server:

from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather")
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"

Connecting to Claude for Desktop

  1. Locate config file
    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json
  2. Edit JSON to register your server
  3. Restart Claude for Desktop. The tools should now be available.

Example (Windows):

{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "C:\\PATH\\TO\\weather",
        "run",
        "weather.py"
      ]
    }
  }
}

Example (macOS):

{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/weather",
        "run",
        "weather.py"
      ]
    }
  }
}

Verifying and Troubleshooting

  • Confirm tool visibility via the MCP UI panel in Claude.
  • Example test prompts:
    • “What’s the weather in Sacramento?”
    • “Are there any weather alerts in Texas?”

What Happens Behind the Scenes

  1. Your message is sent to Claude.
  2. Claude selects a tool from the MCP server.
  3. Claude runs the tool and gets structured output.
  4. Claude responds with natural language based on the tool’s results.