Skip to main content
Glama

chiclana-avisos-mcp (GECOR Avisos MCP)

Servidor Model Context Protocol (MCP) para gestionar avisos e incidencias municipales en Chiclana de la Frontera (Cádiz) y cualquier municipio soportado por la plataforma GECOR.

Inspirado en el diseño y patrones de seguridad de madrid-avisos-mcp.

Permite que un agente de IA pueda:

  • Recibir una foto y dirección o referencia escrita, y extraer GPS EXIF cuando exista.

  • Elegir categorías oficiales GECOR y aclarar dudas antes de actuar.

  • Previsualizar un aviso sin enviarlo y registrarlo solo tras confirmación explícita del resumen exacto.

  • Consultar incidencias previamente registradas y su estado.


📦 Instalación

Requiere Node.js 20 o superior. El paquete se publica en npm como chiclana-avisos-mcp y se ejecuta con npx, sin clonar el repositorio.

1. Obtener el token de GECOR

Autentica con GECOR y obtén el token de la sesión (por ejemplo, desde localStorage en DevTools de gecorweb.com, clave user → campo token). El servidor únicamente acepta GECOR_TOKEN en el entorno de su propio proceso MCP. No guarda sesiones ni admite inicio de sesión con email y contraseña.

2. Configurar en tu cliente MCP

Claude Desktop

Añade a claude_desktop_config.json:

{
  "mcpServers": {
    "chiclana-avisos": {
      "command": "npx",
      "args": ["-y", "chiclana-avisos-mcp"],
      "env": {
        "GECOR_TOKEN": "<tu-token-gecor>",
        "GECOR_AYTO_ID": "268"
      }
    }
  }
}

Claude Code

claude mcp add chiclana-avisos \
  -e GECOR_TOKEN=<tu-token-gecor> \
  -e GECOR_AYTO_ID=268 \
  -- npx -y chiclana-avisos-mcp

Otros clientes MCP (OpenCode, Hermes, etc.)

Cualquier cliente que lance servidores MCP por stdio necesita los mismos tres elementos: comando, argumentos y entorno.

  • command: npx

  • args: ["-y", "chiclana-avisos-mcp"]

  • env: GECOR_TOKEN y GECOR_AYTO_ID (por defecto 268)

Consulta la documentación de tu cliente para el formato exacto del fichero de configuración.

Confirmar una previsualización envía un aviso real al ayuntamiento. Antes de enviar, el agente siempre te muestra el resumen y espera tu «sí».

Para agentes de IA

Si eres un agente configurando este servidor para un usuario:

  1. Pide al usuario su token de GECOR (ver 1. Obtener el token de GECOR); no lo busques ni lo extraigas por tu cuenta.

  2. Configura la entrada MCP con npx -y chiclana-avisos-mcp y el token en env de esa entrada. Chiclana es GECOR_AYTO_ID=268; para otro municipio, obtén su ID con list_ayuntamientos.

  3. Reinicia el cliente y llama a whoami: confirma el municipio activo y que hay token configurado, pero no valida el token. Para comprobar que GECOR lo acepta, llama a list_my_avisos (solo lectura).

  4. Sigue el flujo de skill/SKILL.md: previsualizar, mostrar el resumen y enviar solo tras confirmación explícita.

  5. Confirmar envía un aviso real al ayuntamiento: llama al envío confirmado únicamente después de un «sí» explícito de la persona al resumen exacto mostrado. Nunca confirmes por inferencia, por silencio ni ante una respuesta ambigua.

Desde el código

git clone https://github.com/dfernandezdaw/chiclana-avisos-mcp.git
cd chiclana-avisos-mcp
npm install
npm run build

Y apunta tu cliente MCP a dist/index.js (por ejemplo, en claude_desktop_config.json):

{
  "mcpServers": {
    "chiclana-avisos": {
      "command": "node",
      "args": ["/ruta/absoluta/a/chiclana-avisos-mcp/dist/index.js"],
      "env": {
        "GECOR_AYTO_ID": "268",
        "GECOR_TOKEN": "<tu-token-gecor>"
      }
    }
  }
}

Configura el token directamente en env para cada entrada MCP que inicie este servidor. No uses una exportación global del token: así las credenciales quedan limitadas al proceso MCP correspondiente.


Related MCP server: valencia-avisos-mcp

⚙️ Configuración

Variables de entorno leídas por el proceso MCP:

Variable

Por defecto

Descripción

GECOR_TOKEN

(vacío)

Token de sesión GECOR. Obligatorio para list_my_avisos y para enviar avisos; también identifica al peticionario.

GECOR_AYTO_ID

268

Municipio activo inicial (Chiclana de la Frontera).

GECOR_API_URL

https://gecorapiwe.azurewebsites.net/api

URL base de la API de GECOR.

GECOR_PROCEDENCIA_WEB

1390

Procedencia del aviso cuando la ficha del ayuntamiento en GECOR no incluye ProcedenciaWeb. Valores que no sean enteros positivos usan el defecto.

GECOR_LANGUAGE

es

Idioma de las consultas a GECOR (p. ej. listado de municipios).

GECOR_TIMEOUT_MS

20000

Tiempo máximo por petición, en ms. Valores no válidos usan el defecto; el máximo es 120000.

GECOR_PHOTO_DIRS

tmp, ~/Downloads, ~/Pictures, ~/Desktop, ~/.hermes

Directorios permitidos para image_path, separados por : (; en Windows). Solo rutas absolutas; sustituyen a los valores por defecto.

GECOR_MAX_PHOTO_BYTES

20971520 (20 MB)

Tamaño máximo de la foto recibida.


🛠️ Herramientas MCP Disponibles

Tool

Descripción

whoami

Muestra el municipio activo y si GECOR_TOKEN está configurado.

list_ayuntamientos

Lista los municipios que usan GECOR, con su AyuntamientoID (filtro opcional search).

set_ayuntamiento

Cambia el municipio activo de la sesión MCP (ayuntamientoID).

list_categories

Lista las familias, elementos/subcategorías y tipologías de avería disponibles (admite filtro de texto: ej. farola, basura).

resolve_location

Con lat+lng, devuelve hasta 5 calles cercanas (radio 150 m) con CalleID y Numero. Con street_name, busca en el callejero oficial y devuelve hasta 10 coincidencias (CalleID, Nombre, TipoVia) sin coordenadas: no es geocodificación.

create_aviso_from_photo

Única herramienta pública para avisos: previsualiza con descripción, categoría GECOR, ubicación y una foto obligatoria (image_path o image_base64, no ambos); procesa EXIF, reduce la foto si procede y devuelve un resumen con foto y un preview_token válido 10 minutos y de un solo uso, más una miniatura como contenido de imagen para que el agente redacte y verifique la descripción. Sin description, devuelve phase: need_description con la miniatura y sin token. Tras confirmación explícita, acepta únicamente preview_token, confirm: true y human_confirmed: true. La foto se sube solo en el envío confirmado.

list_my_avisos

Lista las incidencias registradas por el usuario del token con su estado de tramitación. Es la comprobación obligatoria tras un envío ambiguo.


🔒 Seguridad y confirmación explícita

El flujo de envío requiere confirmación explícita; la previsualización por sí sola no crea ningún aviso ni sube la foto, pero confirmarla envía un aviso real al ayuntamiento:

  1. Usa create_aviso_from_photo para ambas fases. Para previsualizar, envía los campos del aviso y una foto no vacía mediante image_path o image_base64, sin token ni campos de confirmación. Usa list_categories para identificar categorías. La herramienta procesa EXIF internamente durante la previsualización; no existe una herramienta independiente parse_photo_gps.

  2. Muestra un resumen breve de categoría, descripción, dirección/referencia, foto y ubicación disponible. No incluyas peticionario, tokens, payload crudo ni identidad privada.

  3. Espera un sí inequívoco al resumen exacto en la misma conversación. Ante cambios o respuesta ambigua, crea una previsualización nueva y vuelve a pedir confirmación.

  4. Tras confirmar, llama al mismo tool solo con preview_token, confirm: true y human_confirmed: true. Haz esta llamada solo tras un «sí» explícito al resumen exacto. Si falla la validación o la subida de la foto, informa que el aviso NO se envió; nunca reintentes una escritura posiblemente completada.

  5. estado: ENVIADO_EXITOSAMENTE en la respuesta wrapper de Chiclana indica que la llamada MCP/API tuvo éxito, no que ese sea el estado de tramitación municipal. Comunica únicamente lo que devolvió la API: informa un número oficial de ticket o estado de tramitación solo si aparece en resultado devuelto por GECOR o está verificado inequívocamente; no lo adivines.

La dirección textual no se geocodifica en este proyecto: resolve_location por nombre de calle solo devuelve el CalleID. Si la foto no aporta GPS EXIF, solicita coordenadas explícitas; nunca inventes ubicación. Prefiere la foto original para conservar EXIF. No se admite subida remota HTTP.

Fotos

  • Formatos: solo JPEG o PNG, detectados por su contenido. HEIC no se admite: conviértela antes (en iPhone, Ajustes › Cámara › Formatos › «Más compatible»).

  • Tamaño máximo: 20 MB (GECOR_MAX_PHOTO_BYTES).

  • image_path debe estar dentro de los directorios permitidos (GECOR_PHOTO_DIRS; por defecto el temporal del sistema, ~/Downloads, ~/Pictures, ~/Desktop y ~/.hermes) y apuntar a un fichero regular. Si no, usa image_base64 (admite prefijo data:image/...;base64,).

  • GPS: solo se lee el EXIF de JPEG. Los PNG, las fotos reenviadas por apps que eliminan metadatos (p. ej. Telegram, salvo envío como archivo) y las capturas no aportan coordenadas.

  • Reducción: los JPEG cuyo lado mayor supera 2048 px se reducen a 2048 px (calidad 85) conservando los segmentos EXIF/XMP originales, incluida la orientación. Si la reducción no es posible, se sube el original y la previsualización lo indica en foto.aviso_reduccion. Los PNG se suben sin cambios.

  • Miniatura: la previsualización devuelve al modelo una imagen JPEG de lado mayor ≤ 1024 px (calidad 80) sin EXIF ni GPS, con la orientación ya aplicada; los PNG de hasta 1 MB se devuelven tal cual y los mayores no tienen miniatura. La miniatura nunca se sube: GECOR recibe la copia de 2048 px con EXIF. Si no se puede generar, la previsualización continúa sin ella.

  • La previsualización incluye foto con mime, original_bytes, upload_bytes, width, height, reducida, exif_conservado y miniatura (más aviso_miniatura si no se pudo generar).

Errores y reintentos

  • Cada petición a GECOR expira tras GECOR_TIMEOUT_MS (20 s por defecto). Las consultas (get*) se reintentan una vez ante timeout, error de red o 5xx; las escrituras nunca se reintentan automáticamente.

  • El preview_token se consume antes de cualquier efecto: un mismo token no puede crear dos avisos.

  • Si falla la subida de la foto, no se crea ningún aviso; genera una nueva previsualización.

  • Si la creación devuelve «Envío NO confirmado» tras timeout, error de red o 5xx, el resultado es ambiguo: el aviso podría haberse creado. Consulta list_my_avisos y, solo si no aparece, crea una nueva previsualización y pide confirmación otra vez. Un 4xx sí descarta la creación.

Skill reutilizable

El artefacto de instrucciones, independiente de cualquier plataforma o harness, está en skill/SKILL.md. Su instalación es manual: colócalo en el directorio de skills que admita tu cliente. Mantén el proceso MCP en un entorno con acceso a las rutas locales que le proporciones; este proyecto no modifica configuraciones externas.


🌐 Soporte Multi-Ayuntamiento

Aunque está preconfigurado por defecto para Chiclana de la Frontera (ID 268), el servidor está pensado para los municipios que usan GECOR (Torremolinos, Vélez-Málaga, Viladecans, etc.).

Para listar todos los municipios disponibles:

node dist/cli.js ayuntamientos

Para usar otro municipio por defecto, define la variable de entorno:

export GECOR_AYTO_ID=143 # Ejemplo: Torremolinos

💻 CLI de Apoyo

Se incluye una utilidad de línea de comandos para realizar pruebas directas:

node dist/cli.js ayuntamientos [filtro]    # Buscar municipios GECOR
node dist/cli.js whoami                   # Ver estado de configuración
node dist/cli.js categories [filtro]      # Ver categorías y tipologías
node dist/cli.js photo <foto.jpg>         # Inspeccionar metadatos GPS EXIF (misma restricción de directorios)
node dist/cli.js calles [filtro]          # Consultar callejero oficial

🏗️ Construcción y Desarrollo

npm install
npm run build
npm run typecheck
npm test

📄 Licencia

MIT. Consulta LICENSE.

Inspirado en madrid-avisos-mcp.

Available Tools

7 tools
create_aviso_from_photoA

Única herramienta para avisos, en dos fases. Para previsualizar, llama con los campos del aviso y una foto obligatoria (image_path o image_base64), sin preview_token ni campos de confirmación. La previsualización devuelve además una miniatura de la foto (imagen JPEG ≤1024 px sin EXIF, o el PNG pequeño tal cual) para que redactes la descripción y compruebes la categoría con lo visible; si omites description, devuelve phase: need_description con la miniatura y sin preview_token. Enseña el resumen exacto y espera un sí explícito. Solo entonces vuelve a llamar con únicamente preview_token, confirm:true y human_confirmed:true. Si el usuario pide cambios, crea una nueva previsualización; nunca envíes por inferencia. La previsualización no envía nada; confirmar envía un aviso real al ayuntamiento y la foto se sube únicamente durante ese envío confirmado.

Inputs: lat, lng, calleID, confirm, +11 more.

list_ayuntamientosB

Lista todos los municipios soportados por la plataforma GECOR (con sus identificadores y nombres).

Inputs: search.

list_categoriesA

Obtiene el catálogo de tipologías de incidencias (familias, elementos/subcategorías y tipos de incidencia) para el ayuntamiento activo.

Inputs: search.

list_my_avisosB

Consulta los avisos previamente registrados por el usuario para consultar su estado de tramitación.

Inputs: no named parameters.

resolve_locationB

Valida y resuelve una ubicación en el municipio activo mediante coordenadas GPS o búsqueda de calles en el callejero oficial de GECOR.

Inputs: lat, lng, street_name.

set_ayuntamientoA

Cambia el ayuntamiento activo para las consultas e incidencias.

Inputs: ayuntamientoID (required).

whoamiA

Muestra el municipio activo y si GECOR_TOKEN está configurado.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 7 tools

    Disambiguation4/5

    Each tool targets a distinct action: identity check, listing municipalities, setting active municipality, catálogos, location resolution, aviso creation, and listing own avisos. The overlapping but functional pair of list_ayuntamientos/set_ayuntamiento is clearly differentiated by verb. create_aviso_from_photo is a single tool handling both preview and confirm, reducing ambiguity.

    Naming Consistency4/5

    Mostly consistent snake_case verb_noun (list_ayuntamientos, set_ayuntamiento, list_categories, resolve_location, list_my_avisos). whoami and create_aviso_from_photo deviate slightly but remain readable and domain-appropriate.

    Tool Count5/5

    Seven tools is well-scoped for a municipal incident-reporting MCP. Each tool serves a clear role in the workflow without redundancy.

    Completeness4/5

    Covers the core lifecycle: authentication, municipality selection, category lookup, location resolution, incident creation, and status listing. Missing update/delete or detail view for avisos, but an agent can work around via create+list for the stated purpose.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      C
      maintenance
      Enables AI agents to report street incidents to Valencia City Council by listing categories, geocoding streets, checking existing reports, and creating nuevos avisos from text or photos with human-confirmed previews. Supports stdio and HTTP transports, with identity and device registration handled locally.
      11
      9 npm
      1
      AGPL 3.0
    • A
      license
      B
      quality
      C
      maintenance
      Enables AI agents to report incidents to the Bilbao City Council (MeJora Bilbao / Bilbo Hobetuz) by listing categories, looking up streets, reviewing existing reports, and creating new ones — including generating a report directly from a geolocated photo. Drafts are dry-run by default and real submissions require explicit human confirmation.
      12
      7 npm
      1
      AGPL 3.0
    • A
      license
      B
      quality
      C
      maintenance
      Enables an AI agent to list the incident categories of Gijón's municipal reporting system and file real service notices on a citizen's behalf, including generating one from a photo by reading its EXIF GPS and suggesting the matching category. Report creation is dry-run by default and only sends after explicit human confirmation, using a saved email as the contact identity and no credentials.
      7
      6 npm
      AGPL 3.0