#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { TokyoLocation } from './types.js';
import { WBGTService } from './wbgt-service.js';
/**
* Tokyo WBGT MCP Server
* 東京都のWBGT(暑さ指数)データを提供するMCPサーバー
*/
class TokyoWBGTServer {
private server: Server;
private wbgtService: WBGTService;
constructor() {
this.server = new Server({
name: "tokyo-wbgt-server",
version: "1.0.0",
});
this.wbgtService = new WBGTService();
this.setupToolHandlers();
}
/**
* MCPツールハンドラーの設定
*/
private setupToolHandlers(): void {
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_tokyo_wbgt_forecast",
description: "東京都のWBGT(暑さ指数)予測値を取得します",
inputSchema: {
type: "object",
properties: {
location: {
type: "string",
description: "東京都内の観測地点(tokyo, hachioji, fuchu, nerima, ome, ogochi, edogawa)",
enum: ["tokyo", "hachioji", "fuchu", "nerima", "ome", "ogochi", "edogawa"],
default: "tokyo"
}
},
},
},
{
name: "get_all_tokyo_locations",
description: "東京都内の全WBGT観測地点の予測値を一括取得します",
inputSchema: {
type: "object",
properties: {},
},
},
{
name: "get_tokyo_realtime_data",
description: "東京都の実測WBGT値を取得します(実測地点のみ)",
inputSchema: {
type: "object",
properties: {
year: {
type: "number",
description: "年(4桁)",
default: new Date().getFullYear()
},
month: {
type: "number",
description: "月(1-12)",
minimum: 1,
maximum: 12,
default: new Date().getMonth() + 1
}
},
},
}
],
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case "get_tokyo_wbgt_forecast":
return await this.handleGetTokyoWBGTForecast((args as any)?.location || "tokyo");
case "get_all_tokyo_locations":
return await this.handleGetAllTokyoLocations();
case "get_tokyo_realtime_data":
return await this.handleGetTokyoRealtimeData(
(args as any)?.year || new Date().getFullYear(),
(args as any)?.month || new Date().getMonth() + 1
);
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
});
}
/**
* 東京都内指定地点のWBGT予測データ取得ハンドラー
*/
private async handleGetTokyoWBGTForecast(location: string): Promise<any> {
const data = await this.wbgtService.getTokyoWBGTForecast(location as TokyoLocation);
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
/**
* 東京都内全地点のWBGT予測データ取得ハンドラー
*/
private async handleGetAllTokyoLocations(): Promise<any> {
const data = await this.wbgtService.getAllTokyoLocations();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
/**
* 東京都のWBGTリアルタイムデータ取得ハンドラー
*/
private async handleGetTokyoRealtimeData(year: number, month: number): Promise<any> {
const data = await this.wbgtService.getTokyoRealtimeData(year, month);
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
/**
* サーバーを起動
*/
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("Tokyo WBGT MCP server running on stdio");
}
}
const server = new TokyoWBGTServer();
server.run().catch(console.error);