Building my first MCP server: Spain's weather API and its two-step catch A backend engineer built and published a Model Context Protocol (MCP) server for Spain's AEMET weather API, exposing three read-only tools. The API uses a two-step pattern where the first call returns a pointer URL instead of data, and the engineer isolated both hops behind a single client function. Key lessons included validating the body's estado field separately from the HTTP status and handling ISO-8859-1 encoding to avoid mangled Spanish characters. I'm a backend engineer Java/Spring, Kubernetes, that world moving toward AI engineering, and I wanted to actually ship something in the agent ecosystem rather than read about it. So I built and published a small Model Context Protocol MCP server. This is the first of a planned series that gets progressively harder; this one was deliberately trivial in scope, because the real goal was to close the full loop: build → publish to npm → list in the official MCP registry → get discovered. The subject is intentionally boring: AEMET, Spain's national weather agency, has a free public API. No auth headaches beyond an API key, no legal grey area, nothing from my day job. A clean sandbox to learn the mechanics. What I did not expect was that the "boring" API had the two most interesting engineering lessons of the whole exercise. What MCP is, in two sentences MCP is an open protocol that lets AI clients Claude Desktop, IDE agents, etc. call external tools through a standard interface. You write a server that exposes a few typed "tools"; any MCP-compatible client can then discover and invoke them. Mine exposes three, all read-only: get municipality forecast — forecast by municipality INE code get station observation — observation data from a weather station get weather warnings — active weather warnings by region Node.js + TypeScript, the official @modelcontextprotocol/sdk, stdio transport, inputs validated with Zod. Nothing exotic. The two-step pattern the interesting part AEMET's OpenData API does something I hadn't seen before, and it trips up everyone who touches it for the first time. The first call doesn't return your data — it returns a pointer to your data. You ask for a forecast: GET /opendata/api/prediccion/especifica/municipio/diaria/{ine code} Header: api key: