Skip to main content
Glama

Caiyun Weather MCP Server

by marcusbai
geocode-service.ts7.28 kB
import axios from 'axios'; import { GeocodingResponse } from './types.js'; export class GeocodeService { private apiKey: string | undefined; constructor(apiKey?: string) { this.apiKey = apiKey; } /** * 常见城市坐标映射 */ private cityCoordinates: { [key: string]: [number, number] } = { // 直辖市 '北京': [116.3976, 39.9075], '北京市': [116.3976, 39.9075], '上海': [121.4737, 31.2304], '上海市': [121.4737, 31.2304], '天津': [117.1901, 39.1084], '天津市': [117.1901, 39.1084], '重庆': [106.5516, 29.5630], '重庆市': [106.5516, 29.5630], // 省会及主要城市 '广州': [113.2644, 23.1291], '广州市': [113.2644, 23.1291], '深圳': [114.0579, 22.5431], '深圳市': [114.0579, 22.5431], '杭州': [120.1551, 30.2741], '杭州市': [120.1551, 30.2741], '南京': [118.7969, 32.0603], '南京市': [118.7969, 32.0603], '武汉': [114.3055, 30.5928], '武汉市': [114.3055, 30.5928], '成都': [104.0665, 30.5723], '成都市': [104.0665, 30.5723], '西安': [108.9402, 34.3416], '西安市': [108.9402, 34.3416], '长沙': [112.9825, 28.1959], '长沙市': [112.9825, 28.1959], '沈阳': [123.4315, 41.8057], '沈阳市': [123.4315, 41.8057], '大连': [121.6147, 38.9140], '大连市': [121.6147, 38.9140], '青岛': [120.3826, 36.0671], '青岛市': [120.3826, 36.0671], '厦门': [118.1102, 24.4905], '厦门市': [118.1102, 24.4905], '苏州': [120.5853, 31.2989], '苏州市': [120.5853, 31.2989], '郑州': [113.6254, 34.7466], '郑州市': [113.6254, 34.7466], '济南': [117.1205, 36.6520], '济南市': [117.1205, 36.6520], '哈尔滨': [126.5358, 45.8023], '哈尔滨市': [126.5358, 45.8023], '石家庄': [114.5149, 38.0428], '石家庄市': [114.5149, 38.0428], '太原': [112.5489, 37.8706], '太原市': [112.5489, 37.8706], '合肥': [117.2272, 31.8206], '合肥市': [117.2272, 31.8206], '南昌': [115.8922, 28.6765], '南昌市': [115.8922, 28.6765], '福州': [119.3063, 26.0745], '福州市': [119.3063, 26.0745], '南宁': [108.3669, 22.8176], '南宁市': [108.3669, 22.8176], '昆明': [102.8329, 24.8801], '昆明市': [102.8329, 24.8801], '贵阳': [106.7135, 26.5783], '贵阳市': [106.7135, 26.5783], '兰州': [103.8343, 36.0611], '兰州市': [103.8343, 36.0611], '西宁': [101.7782, 36.6171], '西宁市': [101.7782, 36.6171], '拉萨': [91.1322, 29.6604], '拉萨市': [91.1322, 29.6604], '呼和浩特': [111.7519, 40.8425], '呼和浩特市': [111.7519, 40.8425], '海口': [110.3312, 20.0458], '海口市': [110.3312, 20.0458], '银川': [106.2309, 38.4872], '银川市': [106.2309, 38.4872], '乌鲁木齐': [87.6177, 43.7928], '乌鲁木齐市': [87.6177, 43.7928] }; /** * 将地址转换为经纬度坐标 * @param address 地址字符串 * @returns 经纬度坐标 [longitude, latitude] */ async geocode(address: string): Promise<[number, number]> { try { // 首先检查是否是常见城市 const cityKey = this.normalizeCityName(address); if (this.cityCoordinates[cityKey]) { console.log(`✓ 使用内置坐标缓存: ${address} -> [${this.cityCoordinates[cityKey][0]}, ${this.cityCoordinates[cityKey][1]}]`); return this.cityCoordinates[cityKey]; } // 如果有高德地图API密钥,使用API服务 if (this.apiKey) { console.log(`🔍 使用高德地图API解析地址: ${address}`); const response = await axios.get<GeocodingResponse>('https://restapi.amap.com/v3/geocode/geo', { params: { address, key: this.apiKey, output: 'JSON' } }); if (response.data.status === '1' && response.data.geocodes.length > 0) { const location = response.data.geocodes[0].location.split(','); const coords = [parseFloat(location[0]), parseFloat(location[1])] as [number, number]; console.log(`✓ API解析成功: ${address} -> [${coords[0]}, ${coords[1]}]`); return coords; } else { console.warn(`⚠️ 高德地图API无法解析地址: ${address}`); } } // 如果没有API密钥且不是常见城市,返回默认坐标(北京市中心) console.warn(`⚠️ 无法识别地址"${address}",使用默认坐标(北京市中心)`); console.warn(`💡 建议: 配置高德地图API密钥以获得更准确的地址解析`); console.warn(` 设置环境变量: AMAP_API_KEY=您的高德地图API密钥`); console.warn(` 支持的常见城市: ${Object.keys(this.cityCoordinates).filter(key => !key.endsWith('市')).join('、')}`); return [116.3976, 39.9075]; // 北京市中心坐标 } catch (error) { if (axios.isAxiosError(error)) { console.warn(`❌ 地理编码API调用失败: ${error.response?.data?.info || error.message}`); console.warn(`💡 建议检查高德地图API密钥配置是否正确`); } else { console.warn(`❌ 地址解析出错: ${error instanceof Error ? error.message : String(error)}`); } // 出错时返回默认坐标 console.warn(`📍 使用默认坐标(北京市中心)`); return [116.3976, 39.9075]; } } /** * 标准化城市名称,用于匹配缓存 * @param address 原始地址 * @returns 标准化的城市名称 */ private normalizeCityName(address: string): string { // 移除空格和特殊字符 let normalized = address.trim(); // 如果地址包含省市信息,提取主要城市名 const cityPatterns = [ /^(.+?)市.+$/, // "上海市浦东新区" -> "上海市" /^(.+?)省.+$/, // "浙江省杭州市" -> "浙江省杭州市" /^(.+?)区.+$/, // "黄浦区南京东路" -> "黄浦区"(如果有区级数据的话) ]; for (const pattern of cityPatterns) { const match = normalized.match(pattern); if (match) { normalized = match[1]; break; } } // 处理一些常见的别名 const aliases: { [key: string]: string } = { '申城': '上海市', '魔都': '上海市', '帝都': '北京市', '京城': '北京市', '羊城': '广州市', '鹏城': '深圳市', '津门': '天津市', '山城': '重庆市', '蓉城': '成都市', '江城': '武汉市', '古都': '西安市', '金陵': '南京市', '钱塘': '杭州市', }; if (aliases[normalized]) { normalized = aliases[normalized]; } return normalized; } /** * 获取支持的城市列表 * @returns 支持的城市名称数组 */ getSupportedCities(): string[] { return Object.keys(this.cityCoordinates).filter(city => !city.endsWith('市')); } /** * 获取默认坐标(北京市中心) * @returns 默认坐标 [longitude, latitude] */ getDefaultCoordinates(): [number, number] { return [116.3976, 39.9075]; // 北京市中心坐标 } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/marcusbai/caiyun-weather-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server