madrid-avisos-mcp
v0.1.7
Published
Servidor MCP y CLI para la API de Avisos del Ayuntamiento de Madrid (AVSICAPI)
Readme
madrid-avisos-mcp
Servidor MCP (y CLI de apoyo) para la API de Avisos del Ayuntamiento de Madrid. Permite a un agente listar categorías, resolver una ubicación, consultar avisos y crear avisos con inteligencia artificial— incluso desde una foto.
La finalidad de este proyecto es hacer más fácil que los ciudadanos puedan reportar problemas al Ayuntamiento de Madrid. Saca una foto de la incidencia (por ejemplo, basura tirada en la calle, una farola que no funciona…) pásasela al agente pidiéndole que genere un aviso para que de forma autónoma describa el problema, seleccione la categoría más adecuada, añada la ubicación (la foto tiene que estar geolocalizada) y lance el aviso al Ayuntamiento.
- Inicio rápido
- Fotos demasiado grandes para el modelo
- ¿Eres un agente IA? Lee esto primero
- Añadir el MCP vía npx
- Herramientas MCP
- Configuración
- Uso como CLI
- Servidor HTTP (opcional, avanzado)
- Arquitectura
Inicio rápido
- Inicia sesión en https://avisos.madrid.es con tu usuario.
- Abre las DevTools del navegador (F12) → pestaña Application o Aplicación, y
ahí en la barra lateral ve a Almacenamiento > Almacenamiento local y selecciona https://avisos.madrid.es.
Copia el valor de la clave
token(empieza porey…). Ese es tuMADRID_AVISOS_TOKEN(caduca al mes; repite el paso cuando deje de funcionar). - Añade el servidor a tu cliente MCP (ejemplos) o configúralo a mano:
{
"mcpServers": {
"madrid-avisos": {
"command": "npx",
"args": ["-y", "madrid-avisos-mcp"],
"env": { "MADRID_AVISOS_TOKEN": "<tu-token>" }
}
}
}- Flujo del agente:
list_categories→resolve_location→create_avisoen dry-run → enseña el preview al humano →confirm: truesolo con su "sí" →attach_photo. O directamentecreate_aviso_from_photocon la imagen.
Todo corre en tu máquina y el token no sale de ella: cada aviso se crea como tu usuario.
Fotos demasiado grandes para el modelo
Algunos modelos rechazan fotos muy grandes (image decode limit exceeded). El servidor
reduce en TypeScript (sin dependencias) conservando el GPS, así que el modelo nunca
necesita procesar la original:
- Remoto (HTTP): sube la foto con curl y usa el
file_id(los bytes no pasan por el modelo). Requiere el secreto del servidor:
El preview devuelvecurl -X PUT --data-binary @foto.jpg \ -H "Authorization: Bearer <secreto>" \ 'http://127.0.0.1:3000/upload?filename=foto.jpg' # → {"file_id":"…","bytes":…}preview_image_base64(copia reducida) para visión y adjunta siempre la original. - Local (stdio/CLI): pasa
image_path; el servidor lee y reduce sin que el modelo abra el fichero. O reduce tú connode dist/cli.js prep-photo foto.jpg [foto-ligera.jpg].
¿Eres un agente IA? Lee esto primero
La skill (skill/SKILL.md) no se autoinstala: cópiala al directorio de tu cliente
y abre sesión nueva.
cp -r skill ~/.hermes/skills/madrid-avisos # Hermes
cp -r skill ~/.claude/skills/madrid-avisos # Claude Code
# o descárgala: https://github.com/Naroh091/madrid-avisos-mcp/blob/main/skill/SKILL.mdInstálalo así (requiere Node 18+):
- Token: pide al humano su
tokende https://avisos.madrid.es (DevTools → Application → Almacenamiento local →https://avisos.madrid.es→ clavetoken). Sin token no hay nada que hacer. - Instalación según tu cliente (comandos exactos):
Claude Code (
claude mcp add … -- npx -y madrid-avisos-mcp), Hermes (hermes mcp add … --command npx … --args -y madrid-avisos-mcp) u OpenClaw (openclaw mcp add … --command npx --arg -y --arg madrid-avisos-mcp). El token viaja en la variableMADRID_AVISOS_TOKENde tu config. - Verifica (
mcp list/test/doctor --probesegún cliente): debes ver 11 tools. - Uso: hay skill completa en
skill/SKILL.md. Lo esencial: solo incidencias genuinas;create_aviso_from_photoen 2 fases (preview → mostrar al humano → envío solo con su "sí" +confirm+human_confirmed+preview_token); foto porimage_base64; sin GPS no adivines la ubicación.
Añadir el MCP vía npx
Requiere Node 18+. <tu-token> es tu bearer (paso 2 del inicio rápido).
Claude Code
claude mcp add madrid-avisos -e MADRID_AVISOS_TOKEN=<tu-token> -- npx -y madrid-avisos-mcp
claude mcp list # verificarHermes
hermes mcp add madrid-avisos --command npx --env MADRID_AVISOS_TOKEN=<tu-token> --args -y madrid-avisos-mcp
hermes mcp test madrid-avisos # verificar (lista las 11 tools)OpenClaw
openclaw mcp add madrid-avisos \
--command npx \
--arg -y \
--arg madrid-avisos-mcp \
--env MADRID_AVISOS_TOKEN=<tu-token>
openclaw mcp doctor madrid-avisos --probe # verificarDesde código
npm install
npm run build
npx -y -p madrid-avisos-mcp madrid-avisos-mcp-http # HTTP en 127.0.0.1:3000/mcpHerramientas MCP
| Tool | Qué hace |
|---|---|
| whoami | Perfil del usuario autenticado (valida el token). |
| refresh_session | Refresca el access token con el refresh token (también automático ante 401). |
| list_categories | Categorías/servicios (id, flags de formulario). |
| get_category | Detalle de una categoría (formulario, obligatorios, tipología). |
| resolve_location | Valida zona del servicio + dirección municipal + preguntas de ubicación + duplicados. |
| resolve_address | Geocodificación inversa propia: coords → dirección municipal + respuestas pre-rellenadas. |
| create_aviso | Crea un aviso. Dry-run por defecto; confirm: true para enviar de verdad. |
| create_aviso_from_photo | Aviso desde foto en 2 fases: preview (GPS EXIF + categoría + ubicación) y envío solo con confirm: true + human_confirmed: true + preview_token. Acepta image_base64 o image_path. |
| attach_photo | Adjunta una foto al aviso (image_base64 o image_path). Dry-run por defecto. |
| get_aviso | Detalle de un aviso por su id interno. |
| list_my_avisos | Avisos propios (own: true por defecto). |
Seguridad de envío
create_aviso es dry-run por defecto: devuelve el payload sin crear nada. Solo con
confirm: true hace el POST real — un aviso real que revisa personal municipal.
Envía únicamente incidencias reales.
create_aviso_from_photo exige confirmación humana en dos fases:
- Preview (
confirmausente/false): extrae el GPS EXIF (o usalat/lngmanuales), sugiere categoría desdecategory_hintsi faltaservice_id, resuelve ubicación (validación + duplicados) y devuelve el payload + unpreview_token. No envía nada. - Envío: el agente muestra el preview al humano y espera su "sí"; solo entonces repite
la llamada con los MISMOS campos +
confirm: true+human_confirmed: true+preview_token. Si cambió cualquier campo, hay que repetir el preview.
Uso como CLI
export MADRID_AVISOS_TOKEN=<tu-token>
node dist/cli.js categories
node dist/cli.js category 591b39e24e4ea83a018b46ad
node dist/cli.js resolve 591b39e24e4ea83a018b46ad 40.4168 -3.7038
node dist/cli.js create 591b39e24e4ea83a018b46ad 40.4168 -3.7038 "Farola apagada" # dry-run
node dist/cli.js create 591b39e24e4ea83a018b46ad 40.4168 -3.7038 "Farola apagada" --send # ENVÍA de verdad
node dist/cli.js from-photo foto.jpg 591b126d4e4ea840018b45b6 "Cartones en la acera" # preview desde foto
node dist/cli.js aviso <id>
node dist/cli.js prep-photo foto.jpg [foto-ligera.jpg] # reduce para el modelo, conserva EXIF/GPSServidor HTTP (opcional)
Por stdio cada uno corre su copia con su token. La entrada HTTP sirve para el caso contrario: exponer el servidor que corre en TU máquina (con TU token) para que un agente en OTRA máquina lo use — en ese caso actúa como tú, no como el dueño del agente remoto. Para uso personal normal no la necesitas.
export MADRID_AVISOS_TOKEN=<tu-token>
export MADRID_AVISOS_MCP_SECRET=<un-secreto-largo> # exige x-mcp-secret o Bearer
export MADRID_AVISOS_ALLOWED_HOSTS=tu-host.tu-tailnet.ts.net # anti DNS-rebinding
npm run start:http # 127.0.0.1:3000/mcpVariables: MADRID_AVISOS_HTTP_PORT (3000), MADRID_AVISOS_HTTP_HOST (127.0.0.1),
MADRID_AVISOS_HTTP_PATH (/mcp). Expón solo en red privada (p.ej. tailscale serve,
nunca funnel): quien llegue a la URL actúa como tu usuario. Para persistencia,
launchd/pm2/tmux o similar.
Arquitectura
src/client.ts— HTTP: cabeceras de app + bearer, GET/POST/multipart, auto-refresh ante 401.src/avisos.ts— núcleo de negocio (reutilizado por MCP y CLI).src/photo.ts— foto: EXIF/GPS, subida a tmp, token de preview.src/types.ts— esquemas zod de entrada + payload de creación.src/mcp.ts—buildServer(): registra las 11 tools (compartido por stdio y HTTP).src/server.ts— entrada stdio ·src/http.ts— entrada HTTP (/mcp+PUT /upload) ·src/cli.ts— CLI.
Notas
- Algunas categorías exigen usuario registrado; con
login-anonymousno se envían.
