aemet-mcp

aemet-mcp

Enables querying official Spanish weather data from AEMET, including municipal forecasts, station observations, and weather alerts, through natural language.

Category
访问服务器

README

aemet-mcp

CI npm

npm: @rldona/aemet-mcp · npx -y @rldona/aemet-mcp

Servidor MCP (Model Context Protocol) para el tiempo oficial de España. Da a Claude Desktop, Cursor y cualquier cliente MCP acceso a la API pública OpenData de AEMET: predicción por municipio, observación de estaciones y avisos meteorológicos, con los datos ya resueltos y formateados en texto legible.

  • 🧭 5 herramientas tipadas: buscar municipio, predicción diaria, predicción horaria, observación de estación y avisos por comunidad autónoma.
  • 🇪🇸 8132 municipios del padrón del INE bundleados: resuelve nombres a código INE sin llamadas extra, tolerante a acentos y mayúsculas.
  • ⚙️ Un solo npx, sin backend propio. Caché en memoria y reintentos ante fallos transitorios de AEMET.
  • 🔒 Sin datos inventados: si un endpoint de AEMET falla, se propaga un error claro.
  • 📚 También librería: importa el núcleo de AEMET (AemetClient, resolvers, avisos, formateadores) en cualquier backend Node/TS — ver Uso como librería.

Por qué

AEMET trabaja con códigos INE de 5 dígitos, sirve los datos en dos pasos, con codificaciones inconsistentes (UTF-8/latin1 según el recurso, a veces con mojibake) y los avisos como un tar.gz de XML (CAP). Este servidor esconde toda esa fontanería: le pides el tiempo de "Málaga" y te devuelve texto legible, sin códigos ni JSON crudo.

Requisitos

  • Node.js ≥ 18
  • Una API key gratuita de AEMET OpenData.

Obtener la API key

  1. Ve a https://opendata.aemet.es/centrodedescargas/inicio → "Solicitar API Key".
  2. Introduce tu email; recibirás la key por correo (es un token largo tipo JWT).
  3. Guárdala; se pasa al servidor por la variable de entorno AEMET_API_KEY.

Uso con Claude Desktop

Edita claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "aemet": {
      "command": "npx",
      "args": ["-y", "@rldona/aemet-mcp"],
      "env": { "AEMET_API_KEY": "TU_KEY" }
    }
  }
}

Reinicia Claude Desktop y pregúntale: "¿Qué tiempo hará mañana en Cádiz?" o "¿Hay avisos meteorológicos en Cataluña?".

Uso con Cursor

En ~/.cursor/mcp.json (o Settings → MCP → Add):

{
  "mcpServers": {
    "aemet": {
      "command": "npx",
      "args": ["-y", "@rldona/aemet-mcp"],
      "env": { "AEMET_API_KEY": "TU_KEY" }
    }
  }
}

Herramientas

Herramienta Entrada Devuelve
buscar_municipio nombre Municipios coincidentes + código INE.
prediccion_diaria municipio (nombre o código), dias? Predicción diaria (1-7 días): máx/mín, cielo, prob. lluvia, viento.
prediccion_horaria municipio, dias? Predicción hora a hora (hoy y mañana).
observacion_estacion estacion? (idema o nombre) Última observación (por defecto Madrid-Retiro).
avisos area (CCAA) Avisos meteorológicos vigentes (nivel, zona, periodo).

Los nombres se resuelven a código INE con tolerancia a acentos/mayúsculas; si un nombre es ambiguo (p. ej. "Villanueva"), la herramienta devuelve las opciones con su código para desambiguar.

Ejemplos de salida

prediccion_diaria — Madrid, 2 días

Predicción diaria — Madrid (Madrid)
Elaborada: 2026-07-19 07:23:09

domingo 19/07
  Máx 36 °C / Mín 22 °C  |  Cielo: Poco nuboso  |  Prob. precip.: 0%  |  Viento: SO 15 km/h

lunes 20/07
  Máx 35 °C / Mín 21 °C  |  Cielo: Despejado  |  Prob. precip.: 0%  |  Viento: SO 20 km/h

observacion_estacion — sin argumentos (Madrid-Retiro)

Última observación — MADRID RETIRO (estación 3195)
Hora (UTC): 2026-07-19T07:00:00+0000

Temperatura:  21.7 °C
Humedad:      41 %
Precip. (última hora): 0 mm
Viento:       1.4 m/s del 143°
Presión:      939.2 hPa

avisos — Andalucía

Avisos meteorológicos vigentes — Andalucía
Elaborado: 2026-07-18 21:50:01
52 avisos (12 naranja, 40 amarillo). Nivel máximo: NARANJA.

🟠 NARANJA (12)
  • Cuenca del Genil: Temperaturas máximas  ·  19/07 13:00 → 19/07 20:59  ·  Temperatura máxima: 40 ºC.  ·  prob. 40%-70%
  ...

Comunidades autónomas válidas para avisos

Andalucía, Aragón, Asturias, Islas Baleares, Canarias, Cantabria, Castilla y León, Castilla-La Mancha, Cataluña, Extremadura, Galicia, Comunidad de Madrid, Región de Murcia, Navarra, País Vasco, La Rioja, Comunidad Valenciana, Ceuta, Melilla. Se aceptan alias comunes (p. ej. "euskadi", "madrid", "valencia").

Uso como librería

Además del servidor MCP, el paquete exporta su núcleo de AEMET como librería, para consumirlo desde cualquier backend Node/TS (una web del tiempo, un cron de avisos, etc.) sin pasar por MCP. Toda la fontanería difícil ya está resuelta: patrón de dos pasos, codificación inconsistente + reparación de mojibake, caché con TTL, reintentos con backoff, dataset de municipios del INE, áreas CAP y parseo de avisos (tar + CAP XML).

⚠️ La API key va siempre en el servidor (variable de entorno), nunca en el navegador.

import {
  AemetClient,
  resolverMunicipio,
  resolverArea,
  obtenerAvisos,
  formatDiaria,
  type PrediccionDiariaMunicipio,
} from "@rldona/aemet-mcp";

const client = new AemetClient({ apiKey: process.env.AEMET_API_KEY! });

// 1) Nombre -> código INE (offline; dataset del INE bundleado, sin gastar cuota)
const madrid = resolverMunicipio("Madrid"); // { codigo: "28079", nombre: "Madrid" }

// 2) Predicción diaria TIPADA (dos pasos + encoding + caché ya resueltos)
const [pred] = await client.fetchJson<PrediccionDiariaMunicipio[]>(
  `/prediccion/especifica/municipio/diaria/${madrid.codigo}`,
);
console.log(pred.prediccion.dia[0]?.temperatura); // { maxima, minima, dato, ... }

// (opcional) texto legible ya formateado
console.log(formatDiaria(pred, 3));

// 3) Avisos vigentes de una CCAA (descomprime el tar.gz y parsea el CAP por ti)
const andalucia = resolverArea("Andalucía"); // { codigo: "61", nombre: "Andalucía" }
const { avisos } = await obtenerAvisos(client, andalucia.codigo);

Qué se exporta

Categoría Exports
Cliente AemetClient, TTL, AemetError, describeEstado, TtlCache
Encoding reparaMojibake, reparaProfundo
Municipios resolverMunicipio, buscarMunicipios, municipioPorCodigo, esCodigoINE, normalize, totalMunicipios
Áreas / avisos AREAS, resolverArea, areaParaMunicipio, obtenerAvisos, extraerAvisos, parseCapAlert, claveAviso
Estaciones resolverEstacion, pareceIdema
Formateadores formatDiaria, formatHoraria, formatObservacion, formatAvisos, formatMunicipios
Bajo nivel untar
Tipos PrediccionDiariaMunicipio, PrediccionHorariaMunicipio, Observacion, Municipio, Aviso, NivelAviso, ResultadoAvisos, …

El AemetClient acepta opciones (maxRetries, backoffBaseMs, fetchImpl, sleep) además de apiKey. Los tipos van incluidos (dist/lib.d.ts).

📖 Referencia completa (todas las funciones, tipos, rutas de endpoint y recetas para una web del tiempo): docs/library.md.

Cómo funciona (interno)

  • Patrón de dos pasos de AEMET: la primera respuesta trae { estado, datos: url }; el contenido real se descarga en un segundo GET. Encapsulado en AemetClient.
  • Encoding: AEMET mezcla UTF-8 y latin1 según el recurso/nodo CDN (y a veces declara mal el charset, produciendo mojibake). Se auto-detecta la codificación y se repara el mojibake; los sobres de error van en latin1. Ver ADR-0012.
  • Estados 200/401/404/429 mapeados a errores claros; reintentos con backoff ante 429 y fallos de red/5xx transitorios.
  • Avisos: tar.gz de CAP XML descomprimido y parseado sin dependencias.
  • Caché en memoria con TTL: ~10 min predicción/avisos, ~5 min observación, 24 h inventario de estaciones.

Documentación

Desarrollo

npm install
npm test                 # unitarios (fetch mockeado; sin API key)
npm run typecheck
npm run build

# Test de integración real contra AEMET:
AEMET_API_KEY=xxx npx vitest run test/integration.aemet.test.ts

# Probar con el MCP Inspector:
AEMET_API_KEY=xxx npm run inspector

Regenerar el dataset de municipios

src/data/municipios.json se genera del diccionario oficial del INE:

node scripts/generate-municipios.mjs   # descarga y parsea el padrón del INE

Créditos y licencia

Datos meteorológicos: © AEMET. Uso de la información autorizado citando a AEMET como autora. Dataset de municipios: INE.

Licencia del software: MIT.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选