Sponsored by Deepsite.site

mcp-server

Created By
milk198 months ago
Content

mcp-server

{ "name": "weather-mcp", "version": "1.0.0", "description": "Weather MCP server for Cline using OpenWeatherMap API", "main": "build/index.js", "scripts": { "build": "tsc", "start": "node build/index.js", "dev": "ts-node src/index.ts" }, "author": "", "license": "MIT", "dependencies": { "@modelcontextprotocol/server": "^0.5.0", "axios": "^1.6.7", "node-cache": "^5.1.2" }, "devDependencies": { "@types/node": "^20.11.5", "ts-node": "^10.9.2", "typescript": "^5.3.3" } } { "compilerOptions": { "target": "es2020", "module": "commonjs", "lib": ["es2020"], "outDir": "./build", "rootDir": "./src", "strict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"] } import { Server, McpError, ErrorCode, Tool, ToolParam, ToolExecuteRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/server"; import axios from "axios"; import NodeCache from "node-cache";

// 日志级别 const LOG_LEVEL = process.env.LOG_LEVEL || "info"; const DEBUG = LOG_LEVEL === "debug";

// 天气API配置 interface WeatherConfig { apiKey: string; baseUrl: string; units: "metric" | "imperial" | "standard"; }

// 缓存配置(秒) const CACHE_TTL = { CURRENT_WEATHER: 30 * 60, // 30分钟 FORECAST: 60 * 60, // 1小时 };

// 主类 class WeatherMcpServer { private config: WeatherConfig; private server: Server; private cache: NodeCache;

constructor() { console.error("[Setup] Initializing Weather MCP server...");

// 获取API密钥
const apiKey = process.env.OPENWEATHERMAP_API_KEY;
if (!apiKey) {
  console.error("[Error] Missing OPENWEATHERMAP_API_KEY environment variable");
  process.exit(1);
}

// 初始化配置
this.config = {
  apiKey,
  baseUrl: "https://api.openweathermap.org/data/2.5",
  units: (process.env.WEATHER_UNITS as any) || "metric"
};

// 初始化缓存
this.cache = new NodeCache({
  stdTTL: CACHE_TTL.CURRENT_WEATHER,
  checkperiod: 120
});

// 初始化MCP服务器
this.server = new Server();

// 注册处理程序
this.registerHandlers();

console.error("[Setup] Weather MCP server initialized successfully");

}

private registerHandlers(): void { // 工具执行处理 this.server.setRequestHandler(ToolExecuteRequestSchema, async (request) => { console.error([Tool] Executing tool: ${request.params.name});

  try {
    switch (request.params.name) {
      case "get_current_weather":
        return await this.getCurrentWeather(request.params.params);
      case "get_weather_forecast":
        return await this.getWeatherForecast(request.params.params);
      default:
        throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
    }
  } catch (error) {
    console.error(`[Error] Tool execution failed: ${error instanceof Error ? error.message : String(error)}`);
    
    if (error instanceof McpError) {
      throw error;
    }
    
    return {
      content: [{
        type: "text",
        text: `Error: ${error instanceof Error ? error.message : String(error)}`
      }],
      isError: true
    };
  }
});

// 工具列表
this.server.setRequestHandler(ToolExecuteRequestSchema.definitions.toolsRequest, async () => {
  console.error("[Tools] Getting tools list");
  
  return {
    tools: [
      {
        name: "get_current_weather",
        description: "Get the current weather for a location",
        parameters: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')"
            }
          },
          required: ["location"]
        }
      },
      {
        name: "get_weather_forecast",
        description: "Get a 5-day weather forecast for a location",
        parameters: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')"
            },
            days: {
              type: "number",
              description: "Number of days to forecast (1-5)",
              default: 3
            }
          },
          required: ["location"]
        }
      }
    ]
  };
});

// 资源列表
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
  console.error("[Resources] Getting resources list");
  
  return {
    resources: [
      {
        uri: "file:///weather-mcp/readme.md",
        name: "Weather MCP Server README",
        mimeType: "text/markdown"
      }
    ]
  };
});

// 资源读取
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  console.error(`[Resources] Reading resource: ${request.params.uri}`);
  
  if (request.params.uri === "file:///weather-mcp/readme.md") {
    return {
      contents: [{
        uri: request.params.uri,
        mimeType: "text/markdown",
        text: this.getReadmeContent()
      }]
    };
  }
  
  throw new McpError(ErrorCode.ResourceNotFound, `Resource not found: ${request.params.uri}`);
});

}

private async getCurrentWeather(params: any): Promise<Tool.ExecuteResponse> { this.validateLocation(params.location);

const location = params.location;
const cacheKey = `current:${location}`;

// 检查缓存
const cachedData = this.cache.get<any>(cacheKey);
if (cachedData) {
  console.error(`[Cache] Using cached current weather for: ${location}`);
  return cachedData;
}

try {
  console.error(`[API] Getting current weather for: ${location}`);
  
  const response = await axios.get(`${this.config.baseUrl}/weather`, {
    params: {
      q: location,
      appid: this.config.apiKey,
      units: this.config.units
    }
  });
  
  const data = response.data;
  
  // 格式化数据
  const result = {
    content: [{
      type: "text",
      text: this.formatCurrentWeather(data)
    }]
  };
  
  // 存入缓存
  this.cache.set(cacheKey, result, CACHE_TTL.CURRENT_WEATHER);
  
  return result;
} catch (error) {
  if (axios.isAxiosError(error) && error.response?.status === 404) {
    throw new McpError(ErrorCode.InvalidParams, `Location not found: ${location}`);
  }
  throw error;
}

}

private async getWeatherForecast(params: any): Promise<Tool.ExecuteResponse> { this.validateLocation(params.location);

const location = params.location;
const days = Math.min(Math.max(parseInt(params.days || "3", 10), 1), 5);
const cacheKey = `forecast:${location}:${days}`;

// 检查缓存
const cachedData = this.cache.get<any>(cacheKey);
if (cachedData) {
  console.error(`[Cache] Using cached forecast for: ${location} (${days} days)`);
  return cachedData;
}

try {
  console.error(`[API] Getting ${days}-day forecast for: ${location}`);
  
  const response = await axios.get(`${this.config.baseUrl}/forecast`, {
    params: {
      q: location,
      appid: this.config.apiKey,
      units: this.config.units
    }
  });
  
  const data = response.data;
  
  // 格式化数据
  const result = {
    content: [{
      type: "text",
      text: this.formatForecast(data, days)
    }]
  };
  
  // 存入缓存
  this.cache.set(cacheKey, result, CACHE_TTL.FORECAST);
  
  return result;
} catch (error) {
  if (axios.isAxiosError(error) && error.response?.status === 404) {
    throw new McpError(ErrorCode.InvalidParams, `Location not found: ${location}`);
  }
  throw error;
}

}

private validateLocation(location: unknown): asserts location is string { if (typeof location !== "string" || location.trim() === "") { throw new McpError(ErrorCode.InvalidParams, "A valid location is required"); } }

private formatCurrentWeather(data: any): string { const temp = Math.round(data.main.temp); const feelsLike = Math.round(data.main.feels_like); const unit = this.config.units === "imperial" ? "°F" : "°C"; const windUnit = this.config.units === "imperial" ? "mph" : "m/s";

const weatherDescription = data.weather[0].description;
const weatherEmoji = this.getWeatherEmoji(data.weather[0].id);

return `# Current Weather in ${data.name}, ${data.sys.country} ${weatherEmoji}\n\n` +
       `**Temperature:** ${temp}${unit} (Feels like: ${feelsLike}${unit})\n` +
       `**Condition:** ${this.capitalizeFirst(weatherDescription)}\n` +
       `**Humidity:** ${data.main.humidity}%\n` +
       `**Wind:** ${data.wind.speed} ${windUnit} from ${this.getWindDirection(data.wind.deg)}\n` +
       `**Visibility:** ${(data.visibility / 1000).toFixed(1)} km\n` +
       `**Pressure:** ${data.main.pressure} hPa\n\n` +
       `*Last updated: ${new Date(data.dt * 1000).toLocaleString()}*`;

}

private formatForecast(data: any, days: number): string { const city = data.city.name; const country = data.city.country; const unit = this.config.units === "imperial" ? "°F" : "°C";

// 按天分组
const dailyForecasts: any = {};

// 处理5天/3小时预报数据
for (const item of data.list) {
  const date = new Date(item.dt * 1000);
  const day = date.toISOString().split('T')[0];
  
  if (!dailyForecasts[day]) {
    dailyForecasts[day] = {
      date: date,
      minTemp: Infinity,
      maxTemp: -Infinity,
      conditions: [],
      conditionIds: [],
      rainfall: 0,
      windSpeed: 0,
      entries: 0
    };
  }
  
  const forecast = dailyForecasts[day];
  forecast.entries++;
  
  // 更新温度
  forecast.minTemp = Math.min(forecast.minTemp, item.main.temp_min);
  forecast.maxTemp = Math.max(forecast.maxTemp, item.main.temp_max);
  
  // 更新天气状况
  forecast.conditions.push(item.weather[0].description);
  forecast.conditionIds.push(item.weather[0].id);
  
  // 统计降水量
  if (item.rain && item.rain['3h']) {
    forecast.rainfall += item.rain['3h'];
  }
  
  // 统计风速
  forecast.windSpeed += item.wind.speed;
}

// 选择最靠前的几天
const forecastDays = Object.keys(dailyForecasts).sort().slice(0, days);

// 构建结果字符串
let result = `# ${days}-Day Weather Forecast for ${city}, ${country}\n\n`;

for (const day of forecastDays) {
  const forecast = dailyForecasts[day];
  
  // 计算每天的平均值
  const avgWindSpeed = forecast.windSpeed / forecast.entries;
  
  // 找出最常见的天气状况
  const conditionCounts = forecast.conditionIds.reduce((acc: any, id: number) => {
    acc[id] = (acc[id] || 0) + 1;
    return acc;
  }, {});
  
  const mostCommonConditionId = Object.entries(conditionCounts)
    .sort((a: any, b: any) => b[1] - a[1])[0][0];
  
  const conditionIndex = forecast.conditionIds.indexOf(Number(mostCommonConditionId));
  const mostCommonCondition = forecast.conditions[conditionIndex];
  const weatherEmoji = this.getWeatherEmoji(Number(mostCommonConditionId));
  
  // 格式化日期
  const dateOptions: Intl.DateTimeFormatOptions = { weekday: 'long', month: 'short', day: 'numeric' };
  const formattedDate = forecast.date.toLocaleDateString('en-US', dateOptions);
  
  result += `## ${formattedDate} ${weatherEmoji}\n\n` +
            `**Temperature:** ${Math.round(forecast.minTemp)}${unit} to ${Math.round(forecast.maxTemp)}${unit}\n` +
            `**Conditions:** ${this.capitalizeFirst(mostCommonCondition)}\n`;
  
  if (forecast.rainfall > 0) {
    result += `**Precipitation:** ${forecast.rainfall.toFixed(1)} mm\n`;
  }
  
  result += `**Wind:** ${avgWindSpeed.toFixed(1)} ${this.config.units === "imperial" ? "mph" : "m/s"}\n\n`;
}

return result;

}

private getWeatherEmoji(weatherId: number): string { // 根据OpenWeatherMap的天气ID选择表情 if (weatherId >= 200 && weatherId < 300) return "⛈️"; // 雷暴 if (weatherId >= 300 && weatherId < 400) return "🌧️"; // 小雨 if (weatherId >= 500 && weatherId < 600) return "🌧️"; // 雨 if (weatherId >= 600 && weatherId < 700) return "❄️"; // 雪 if (weatherId >= 700 && weatherId < 800) return "🌫️"; // 雾 if (weatherId === 800) return "☀️"; // 晴天 if (weatherId > 800 && weatherId < 900) return "☁️"; // 多云 return "🌡️"; // 默认 }

private getWindDirection(degrees: number): string { const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; const index = Math.round(degrees / 45) % 8; return directions[index]; }

private capitalizeFirst(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); }

private getReadmeContent(): string { return `# Weather MCP Server

A Cline MCP server that provides real-time weather data using the OpenWeatherMap API.

Features

  • Get current weather for any location worldwide
  • Get 5-day weather forecasts with detailed information
  • Support for metric and imperial units
  • Efficient caching to minimize API calls
  • Beautifully formatted markdown responses

Setup

  1. Sign up for a free API key at OpenWeatherMap

  2. Install the MCP server:

    ```json { "mcpServers": { "weather-mcp": { "command": "node", "args": [ "/path/to/weather-mcp/build/index.js" ], "env": { "OPENWEATHERMAP_API_KEY": "YOUR_API_KEY", "WEATHER_UNITS": "metric" }, "disabled": false, "autoApprove": [] } } } ```

  3. Set `WEATHER_UNITS` to "metric" (°C, m/s) or "imperial" (°F, mph)

Available Tools

get_current_weather

Gets the current weather conditions for a specified location.

Parameters:

  • `location`: City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')

get_weather_forecast

Gets a 5-day weather forecast for a specified location.

Parameters:

  • `location`: City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')
  • `days`: Number of days to forecast (1-5, default: 3)

Example Output

Current Weather

```

Current Weather in London, GB ☁️

Temperature: 12°C (Feels like: 10°C) Condition: Overcast clouds Humidity: 76% Wind: 4.12 m/s from SW Visibility: 10.0 km Pressure: 1013 hPa

Last updated: 1/15/2024, 2:30:00 PM ```

Weather Forecast

```

3-Day Weather Forecast for London, GB

Monday, Jan 15 🌧️

Temperature: 10°C to 13°C Conditions: Light rain Precipitation: 2.4 mm Wind: 5.2 m/s

Tuesday, Jan 16 ☁️

Temperature: 9°C to 12°C Conditions: Cloudy Wind: 4.8 m/s

Wednesday, Jan 17 ☀️

Temperature: 8°C to 14°C Conditions: Clear sky Wind: 3.5 m/s ```

License

MIT `; }

public start(): void { this.server.start(); console.error("[Server] Weather MCP server started successfully"); } }

// 启动服务器 const server = new WeatherMcpServer(); server.start();

MCP Server Development Protocol

⚠️ CRITICAL: DO NOT USE attempt_completion BEFORE TESTING ⚠️

Step 1: Planning (PLAN MODE)

  • What problem does this tool solve?
  • What API/service will it use?
  • What are the authentication requirements? □ Standard API key □ OAuth (requires separate setup script) □ Other credentials

Step 2: Implementation (ACT MODE)

  1. Bootstrap

    • For web services, JavaScript integration, or Node.js environments:
      npx @modelcontextprotocol/create-server my-server
      cd my-server
      npm install
      
    • For data science, ML workflows, or Python environments:
      pip install mcp
      # Or with uv (recommended)
      uv add "mcp[cli]"
      
  2. Core Implementation

    • Use MCP SDK
    • Implement comprehensive logging
      • TypeScript (for web/JS projects):
        console.error('[Setup] Initializing server...');
        console.error('[API] Request to endpoint:', endpoint);
        console.error('[Error] Failed with:', error);
        
      • Python (for data science/ML projects):
        import logging
        logging.error('[Setup] Initializing server...')
        logging.error(f'[API] Request to endpoint: {endpoint}')
        logging.error(f'[Error] Failed with: {str(error)}')
        
    • Add type definitions
    • Handle errors with context
    • Implement rate limiting if needed
  3. Configuration

    • Get credentials from user if needed
    • Add to MCP settings:
      • For TypeScript projects:
        {
          "mcpServers": {
            "my-server": {
              "command": "node",
              "args": ["path/to/build/index.js"],
              "env": {
                "API_KEY": "key"
              },
              "disabled": false,
              "autoApprove": []
            }
          }
        }
        
      • For Python projects:
        # Directly with command line
        mcp install server.py -v API_KEY=key
        
        # Or in settings.json
        {
          "mcpServers": {
            "my-server": {
              "command": "python",
              "args": ["server.py"],
              "env": {
                "API_KEY": "key"
              },
              "disabled": false,
              "autoApprove": []
            }
          }
        }
        

Step 3: Testing (BLOCKER ⛔️)

BEFORE using attempt_completion, I MUST verify: □ Have I tested EVERY tool? □ Have I confirmed success from the user for each test? □ Have I documented the test results?

If ANY answer is "no", I MUST NOT use attempt_completion.

  1. Test Each Tool (REQUIRED) □ Test each tool with valid inputs □ Verify output format is correct ⚠️ DO NOT PROCEED UNTIL ALL TOOLS TESTED

Step 4: Completion

❗ STOP AND VERIFY: □ Every tool has been tested with valid inputs □ Output format is correct for each tool

Only after ALL tools have been tested can attempt_completion be used.

Key Requirements

  • ✓ Must use MCP SDK

  • ✓ Must have comprehensive logging

  • ✓ Must test each tool individually

  • ✓ Must handle errors gracefully

  • ⛔️ NEVER skip testing before completion

    Weather MCP Server

A Cline MCP server that provides real-time weather data using the OpenWeatherMap API.

Features

  • Get current weather for any location worldwide
  • Get 5-day weather forecasts with detailed information
  • Support for metric and imperial units
  • Efficient caching to minimize API calls
  • Beautifully formatted markdown responses

Setup

  1. Sign up for a free API key at OpenWeatherMap

  2. Clone this repository:

    git clone https://github.com/yourusername/weather-mcp.git
    cd weather-mcp
    npm install
    npm run build
    
  3. Add the MCP server to your Cline settings:

    {
      "mcpServers": {
        "weather-mcp": {
          "command": "node",
          "args": [
            "/path/to/weather-mcp/build/index.js"
          ],
          "env": {
            "OPENWEATHERMAP_API_KEY": "YOUR_API_KEY",
            "WEATHER_UNITS": "metric"
          },
          "disabled": false,
          "autoApprove": []
        }
      }
    }
    
  4. Set WEATHER_UNITS to "metric" (°C, m/s) or "imperial" (°F, mph)

Available Tools

get_current_weather

Gets the current weather conditions for a specified location.

Parameters:

  • location: City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')

get_weather_forecast

Gets a 5-day weather forecast for a specified location.

Parameters:

  • location: City name (e.g., 'London'), or city name with country code (e.g., 'London,uk')
  • days: Number of days to forecast (1-5, default: 3)

Development

  1. Install dependencies:

    npm install
    
  2. Run in development mode:

    npm run dev
    
  3. Build for production:

    npm run build
    

License

MIT

Recommend Servers
TraeBuild with Free GPT-4.1 & Claude 3.7. Fully MCP-Ready.
EdgeOne Pages MCPAn MCP service designed for deploying HTML content to EdgeOne Pages and obtaining an accessible public URL.
TimeA Model Context Protocol server that provides time and timezone conversion capabilities. This server enables LLMs to get current time information and perform timezone conversions using IANA timezone names, with automatic system timezone detection.
DeepChatYour AI Partner on Desktop
BlenderBlenderMCP connects Blender to Claude AI through the Model Context Protocol (MCP), allowing Claude to directly interact with and control Blender. This integration enables prompt assisted 3D modeling, scene creation, and manipulation.
CursorThe AI Code Editor
Amap Maps高德地图官方 MCP Server
Jina AI MCP ToolsA Model Context Protocol (MCP) server that integrates with Jina AI Search Foundation APIs.
Howtocook Mcp基于Anduin2017 / HowToCook (程序员在家做饭指南)的mcp server,帮你推荐菜谱、规划膳食,解决“今天吃什么“的世纪难题; Based on Anduin2017/HowToCook (Programmer's Guide to Cooking at Home), MCP Server helps you recommend recipes, plan meals, and solve the century old problem of "what to eat today"
WindsurfThe new purpose-built IDE to harness magic
Tavily Mcp
AiimagemultistyleA Model Context Protocol (MCP) server for image generation and manipulation using fal.ai's Stable Diffusion model.
Context7Context7 MCP Server -- Up-to-date code documentation for LLMs and AI code editors
Baidu Map百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Serper MCP ServerA Serper MCP Server
MCP AdvisorMCP Advisor & Installation - Use the right MCP server for your needs
MiniMax MCPOfficial MiniMax Model Context Protocol (MCP) server that enables interaction with powerful Text to Speech, image generation and video generation APIs.
ChatWiseThe second fastest AI chatbot™
Zhipu Web SearchZhipu Web Search MCP Server is a search engine specifically designed for large models. It integrates four search engines, allowing users to flexibly compare and switch between them. Building upon the web crawling and ranking capabilities of traditional search engines, it enhances intent recognition capabilities, returning results more suitable for large model processing (such as webpage titles, URLs, summaries, site names, site icons, etc.). This helps AI applications achieve "dynamic knowledge acquisition" and "precise scenario adaptation" capabilities.
Playwright McpPlaywright MCP server
Visual Studio Code - Open Source ("Code - OSS")Visual Studio Code