TypeScript SDK を使用して単純な MCP 天気予報サーバを構築し、それをホスト Claude for Desktop に接続します。基本的なセットアップから始めて、より複雑なユースケースへと進みます。
Model Context Protocol (MCP) : クイックスタート : サーバ開発者向け (TypeScript SDK)
作成 : クラスキャット・セールスインフォメーション
作成日時 : 05/06/2025
* 本記事は github modelcontextprotocol の以下のページを独自に翻訳した上でまとめ直し、補足説明を加えています :
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
◆ お問合せ : 下記までお願いします。
- クラスキャット セールス・インフォメーション
- sales-info@classcat.com
- ClassCatJP
Model Context Protocol (MCP) : クイックスタート : サーバ開発者向け (TypeScript SDK)
Claude for Desktop やその他のクライアントで使用するあなた自身のサーバを構築することから始めましょう。
このチュートリアルでは、単純な MCP 天気予報サーバ (weather server) を構築してそれをホスト Claude for Desktop に接続します。基本的なセットアップから始めて、より複雑なユースケースへと進みます。
構築していくもの
多くの LLM は現在、天気予報と重大な天気警報を取得する機能を持ちません。MCP を使用してそれを解決しましょう!
2 つのツール: get-alerts と get-forecast を公開するサーバを構築します。それからそのサーバを MCP ホスト (この場合、Claude for Desktop) に接続します :
Note : サーバは任意のクライアントに接続できます。ここでは単純化のために Claude for Desktop を選択しましたが、独自のクライアントを構築する ためのガイドや その他のクライアントのリスト もあります。
Why Claude for Desktop and not Claude.ai?
サーバがローカルで実行されるため、現在 MCP はデスクトップホストだけをサポートしています。Remote hosts are in active development.
中核の MCP コンセプト
MCP サーバは 3 つの種類の主な機能を提供できます :
- Resources : クライアントが読めるファイルのようなデータ (API レスポンスやファイルコンテンツのような)
- Tools : LLM により呼び出せる関数 (ユーザ承認を伴う)
- Prompts : ユーザが特定のタスクを達成するのに役立つ事前作成されたテンプレート
このチュートリアルは主としてツールに焦点を当てます。
天気予報サーバを構築することから始めましょう!構築していくものの完全なコードは こちら にあります。
前提知識
このクイックスタートは以下に精通していることを仮定しています :
- TypeScript
- Claude のような LLM
システム要件
TypeScript について、Node の最新版がインストールされていることを確認してください。
環境のセットアップ
まず、Node.js と npm をまだインストールしていないならインストールしましょう。nodejs.org からそれらをダウンロードできます。Node.js インストールを検証してください :
node --version
npm --version
このチュートリアルについては、Node.js バージョン 16 以降が必要です。
Now, let’s create and set up our project:
# Create a new directory for our project
mkdir weather
cd weather
# Initialize a new npm project
npm init -y
# Install dependencies
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
# Create our files
mkdir src
touch src/index.ts
package.json を更新して type: “module” と build script を追加します :
{
"type": "module",
"bin": {
"weather": "./build/index.js"
},
"scripts": {
"build": "tsc && chmod 755 build/index.js"
},
"files": [
"build"
],
}
プロジェクトのルートに tsconfig.json を作成します :
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Now let’s dive into building your server.
サーバの構築
パッケージをインポートとインスタンスのセットアップ
src/index.ts の先頭に以下を追加してください :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const NWS_API_BASE = "https://api.weather.gov";
const USER_AGENT = "weather-app/1.0";
// Create server instance
const server = new McpServer({
name: "weather",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
ヘルパー関数
次に、National Weather Service API からのデータをクエリーしてフォーマットするヘルパー関数を追加しましょう :
// Helper function for making NWS API requests
async function makeNWSRequest(url: string): Promise {
const headers = {
"User-Agent": USER_AGENT,
Accept: "application/geo+json",
};
try {
const response = await fetch(url, { headers });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return (await response.json()) as T;
} catch (error) {
console.error("Error making NWS request:", error);
return null;
}
}
interface AlertFeature {
properties: {
event?: string;
areaDesc?: string;
severity?: string;
status?: string;
headline?: string;
};
}
// Format alert data
function formatAlert(feature: AlertFeature): string {
const props = feature.properties;
return [
`Event: ${props.event || "Unknown"}`,
`Area: ${props.areaDesc || "Unknown"}`,
`Severity: ${props.severity || "Unknown"}`,
`Status: ${props.status || "Unknown"}`,
`Headline: ${props.headline || "No headline"}`,
"---",
].join("\n");
}
interface ForecastPeriod {
name?: string;
temperature?: number;
temperatureUnit?: string;
windSpeed?: string;
windDirection?: string;
shortForecast?: string;
}
interface AlertsResponse {
features: AlertFeature[];
}
interface PointsResponse {
properties: {
forecast?: string;
};
}
interface ForecastResponse {
properties: {
periods: ForecastPeriod[];
};
}
ツール実行の実装
ツール実行ハンドラは各ツールのロジックを実際に実行する役割を担います。それを追加しましょう :
// Register weather tools
server.tool(
"get-alerts",
"Get weather alerts for a state",
{
state: z.string().length(2).describe("Two-letter state code (e.g. CA, NY)"),
},
async ({ state }) => {
const stateCode = state.toUpperCase();
const alertsUrl = `${NWS_API_BASE}/alerts?area=${stateCode}`;
const alertsData = await makeNWSRequest(alertsUrl);
if (!alertsData) {
return {
content: [
{
type: "text",
text: "Failed to retrieve alerts data",
},
],
};
}
const features = alertsData.features || [];
if (features.length === 0) {
return {
content: [
{
type: "text",
text: `No active alerts for ${stateCode}`,
},
],
};
}
const formattedAlerts = features.map(formatAlert);
const alertsText = `Active alerts for ${stateCode}:\n\n${formattedAlerts.join("\n")}`;
return {
content: [
{
type: "text",
text: alertsText,
},
],
};
},
);
server.tool(
"get-forecast",
"Get weather forecast for a location",
{
latitude: z.number().min(-90).max(90).describe("Latitude of the location"),
longitude: z.number().min(-180).max(180).describe("Longitude of the location"),
},
async ({ latitude, longitude }) => {
// Get grid point data
const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`;
const pointsData = await makeNWSRequest(pointsUrl);
if (!pointsData) {
return {
content: [
{
type: "text",
text: `Failed to retrieve grid point data for coordinates: ${latitude}, ${longitude}. This location may not be supported by the NWS API (only US locations are supported).`,
},
],
};
}
const forecastUrl = pointsData.properties?.forecast;
if (!forecastUrl) {
return {
content: [
{
type: "text",
text: "Failed to get forecast URL from grid point data",
},
],
};
}
// Get forecast data
const forecastData = await makeNWSRequest(forecastUrl);
if (!forecastData) {
return {
content: [
{
type: "text",
text: "Failed to retrieve forecast data",
},
],
};
}
const periods = forecastData.properties?.periods || [];
if (periods.length === 0) {
return {
content: [
{
type: "text",
text: "No forecast periods available",
},
],
};
}
// Format forecast periods
const formattedForecast = periods.map((period: ForecastPeriod) =>
[
`${period.name || "Unknown"}:`,
`Temperature: ${period.temperature || "Unknown"}°${period.temperatureUnit || "F"}`,
`Wind: ${period.windSpeed || "Unknown"} ${period.windDirection || ""}`,
`${period.shortForecast || "No forecast available"}`,
"---",
].join("\n"),
);
const forecastText = `Forecast for ${latitude}, ${longitude}:\n\n${formattedForecast.join("\n")}`;
return {
content: [
{
type: "text",
text: forecastText,
},
],
};
},
);
サーバの実行
最後に、サーバを実行する main 関数を実装します :
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Weather MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
“npm run build” を実行してサーバを確実にビルドしてください!これはサーバを接続させるために非常に重要なステップです。
Let’s now test your server from an existing MCP host, Claude for Desktop.
Claude for Desktop でサーバをテストする
最初に、Claude for Desktop がインストールされていることを確認してください。最新版は こちら でインストールできます。既に Claude for Desktop を持っているなら、最新版に更新されていることを確認しましょう。
使用したい MCP サーバが何であれ、そのために Claude for Desktop を設定する必要があります。そのため、テキストエディタで “~/Library/Application Support/Claude/claude_desktop_config.json” にある Claude for Desktop App の設定ファイルを開いてください。存在しないなら必ずファイルを作成してください。
For example, if you have VS Code installed:
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
それから mcpServers キーにサーバを追加します。MCP UI 要素は、少なくとも 1 つのサーバが正しく構成されている場合に Claude for Desktop に表示されます。
In this case, we’ll add our single weather server like so:
{
"mcpServers": {
"weather": {
"command": "node",
"args": [
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js"
]
}
}
}
これは Claude for Desktop に以下を伝えます :
- “weather” という名前の MCP サーバがある
- それを起動するには “node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js” を実行する。
コマンドでテストする
Claude for Desktop が、weather サーバで公開した 2 つのツールをピックアップしていることを確認しましょう。ハンマー アイコンを探すことでこれを行うことができます :
ハンマーアイコンをクリックすると、2 つのツールがリストされるのを見るはずです :
サーバが Claude for Desktop によりピックアップされていない場合、Troubleshooting section for debugging tips に進んでください。
ハンマーアイコンが表示されている場合は、Claude for Desktop で次のコマンドを実行してサーバをテストすることができます :
- What’s the weather in Sacramento?
- What are the active weather alerts in Texas?
What’s happening under the hood
あなたが質問すると :
- クライアントは質問を Claude に送信します
- Claude は利用可能なツールを分析してどれを使用するか決定します。
- クライアントは選択されたツールを MCP サーバ経由で実行します。
- 結果は Claude に送り返されます。
- Claude は自然言語のレスポンスを作成します。
- レスポンスがあなたに表示されます!
以上