【いま話題】MCPサーバーを10分で構築してみた
こんにちは。
今話題のMCPサーバーを構築してみようと思い、備忘録としてこの記事にログを残していこうと思います。
MCPのイントロダクション
上記の絵がMCPの役割を簡潔に表してくれていると思います。各サービスとの連携時にMCPがハブになってくれるようです。
(エンジニアバブルの終焉は近いですね。)
MCPサーバーの構築
サンプルにはPythonとNodeJSがありましたが、普段TypeScriptをよく触るので、勉強がてらにPythonで構築してみます。
環境
- Python 3.10 or higher installed.
- You must use the Python MCP SDK 1.2.0 or higher.
uvのインストール
そもそもuvとは?
Rust製のpythonのパッケージ管理ツールのようです。
詳しくはこちらを参照してみてください。わかりやすく解説してくださっています。
実際にuv入れてみよう
以下コマンドでuvがインストールできるようなので、やってみる。
curl -LsSf https://astral.sh/uv/install.sh | sh
結果
(base) maakusaito ~ % curl -LsSf https://astral.sh/uv/install.sh | sh
downloading uv 0.5.21 aarch64-apple-darwin
no checksums to verify
installing to /Users/maakusaito/.local/bin
uv
uvx
everything's installed!
To add $HOME/.local/bin to your PATH, either restart your shell or run:
source $HOME/.local/bin/env (sh, bash, zsh)
source $HOME/.local/bin/env.fish (fish)
入れれた。
プロジェクトを作っていく
以下の手順通りにやっていきます。
# Create a new directory for our project
(base) maakusaito mark % uv init weather
Initialized project `weather` at `/Users/maakusaito/Desktop/work/mark/weather`
(base) maakusaito mark % cd weather
# Create virtual environment and activate it
(base) maakusaito weather % uv venv
Using CPython 3.12.3 interpreter at: /Users/maakusaito/miniconda3/bin/python3.12
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
(base) maakusaito weather % source .venv/bin/activate
# Install dependencies
(weather) (base) maakusaito weather % uv add "mcp[cli]" httpx
Resolved 27 packages in 250ms
Prepared 25 packages in 139ms
Installed 25 packages in 11ms
+ annotated-types==0.7.0
...
# Create our server file
(weather) (base) maakusaito weather % touch weather.py
(weather) (base) maakusaito weather % ls
README.md hello.py pyproject.toml uv.lock weather.py
プロジェクトの作成までいけた。
サーバーをたてる
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
The FastMCP class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
型とdocstringからツール定義を自動生成してくれるらしい。
National Weather Service APIからデータを取得し、フォーマットするためのヘルパー関数を追加。
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
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:
"""Format an alert feature into a readable string."""
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')}
"""
実行処理の追加。
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
サーバーの起動処理の追加。
if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport='stdio')
これでOKぽい。
いざ起動
uv run weather.py
エラーは出ていないのでおそらくいけてるはず..!
Let’s now test your server from an existing MCP host, Claude for Desktop.
では、Claudeのデスクトップアプリを入れて確認してみましょう。
Claude for Desktopのインストールはこちらから
いけた!
Claude Desktopで動作確認
VSCodeにてclaude_desktop_config.json
を開く。
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
そして以下のコードを追加
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather
は先ほど作成したweatherディレクトリへの絶対パスです。
weatherディレクトリにてpwd
コマンドを実装すると確認できます。
さあいけるか..!
何やらuvコマンドでエラー出てそう。
You may need to put the full path to the uv executable in the command field. You can get this by running which uv on MacOS/Linux or where uv on Windows.
uvコマンドはフルパスでの指定が必要かもしれないとの注意書きが。。
(weather) (base) maakusaito ~ % which uv
/Users/maakusaito/.local/bin/uv
/Users/maakusaito/.local/bin/uv
({full-path-to-uv})を指定すれば良いわけか。
上記はご自身のものでお願いします。
{
"mcpServers": {
"weather": {
"command": "{full-path-to-uv}",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
Claude Desktopを再起動してみる。
成功してるみたいです!!
テキサス州の天気を聞いてみる
公式Docにあるように、What are the active weather alerts in Texas?
という質問をしてみると..
National Weather Service APIを呼び出して天気を教えてくれました!
これで最低限の動作確認まで完了ですね!!
コマンド実行時に何が起こっているのか
公式ドキュメントの直訳ですが、以下の処理が実行されているようです。
- クライアントがあなたの質問をClaudeに送信します
- Claudeが利用可能なツールを分析し、使用するツールを選択します
- クライアントがMCPサーバーを通じて選択したツールを実行します
- 結果がClaudeに返送されます
- Claudeが自然な言語で回答を作成します
- 回答があなたに表示されます!
最後に
今話題のMCPサーバーの構築を公式ドキュメントに沿って完了させてみました。
Pythonでの実装に慣れていないという点以外は非常にシンプルに構築できたかなと。
ぜひ、なぞって手を動かしてみることをお勧めします!
参考記事
Xでは、FlutterやAIについてキャッチアップした情報を発信しています!
Discussion