Skip to main content
Glama

axis-camera-mcp

Un servidor MCP (Model Context Protocol) que permite a un LLM (Claude Code/Desktop) comunicarse con una cámara de red Axis a través de VAPIX (la API HTTP/JSON de cámaras de Axis): ver la transmisión en vivo en VLC, controlar paneo/inclinación/zoom, ajustar la configuración del sensor de imagen (brillo, exposición, ganancia, balance de blancos), capturar instantáneas, añadir superposiciones de texto/imagen, obtener/establecer el reloj, gestionar cuentas de usuario locales de la cámara y controlar la luz.

Construido y verificado en vivo contra una AXIS M3057-PLVE Mk II en una red local. Consulta docs/live-verification-checklist.md para ver exactamente qué se ha probado en vivo y qué no, y docs/open-questions.md para una limitación confirmada de esta cámara específica: los comandos PTZ se ejecutan correctamente y la posición reportada se actualiza, pero no producen un efecto visual real de paneo/inclinación/zoom en este modelo de cámara fija.

Arquitectura

axis_camera_mcp/
  config.py            Loads camera host/username/password from config.json
  vapix/
    session.py          requests.Session + HTTP Digest auth
    jsonrpc.py           Client for VAPIX's modern JSON-RPC-style APIs
    legacy.py             Client for VAPIX's legacy query-param/plain-text CGIs
    client.py              VapixClient facade - the only thing tools/* imports
    exceptions.py
  vlc_launcher.py       Starts/stops the local VLC install to view the RTSP stream
  rag/                  Local knowledge base: VAPIX docs + this project's own
                        live-verified findings, hybrid BM25+embedding search
                        (see "Knowledge base (RAG)" below)
  app.py / context.py  Shared FastMCP instance + lazy VapixClient/VlcLauncher/
                        HybridRetriever singletons
  tools/                One module per capability, each registering @mcp.tool()s
  server.py             Entrypoint: import tools, preload_rag(), mcp.run()
tests/
  test_*.py             Unit tests, mocked HTTP, no live camera needed
  manual/                Plain scripts (not pytest) exercised against the real camera
docs/
  live-verification-checklist.md   One row per tool - what's actually been tested live
  open-questions.md                Confirmed limitations and things not yet tried

En esta cámara coexisten dos estilos de solicitud VAPIX, y la capa de cliente maneja ambos sin filtrar la diferencia al código de las herramientas:

  • Estilo JSON-RPC moderno (api-discovery, basicdeviceinfo, streamprofile, lightcontrol, time.cgi, dynamicoverlay): cuerpo JSON POST {"apiVersion", "method", "params"}, respuesta {"data"} o {"error"}.

  • CGI heredados de parámetros de consulta/texto plano (com/ptz.cgi, com/ptzconfig.cgi, pwdgrp.cgi, usergroup.cgi, jpg/image.cgi): GET simple con parámetros de consulta, las respuestas son texto plano (a veces líneas key=value) o, para el endpoint de instantáneas, bytes JPEG sin procesar.

Configuración

Las credenciales residen en un archivo de configuración, nunca en código ni en variables de entorno:

copy config.example.json config.json
notepad config.json   # fill in host/username/password

config.json está en gitignore: nunca se confirma en el repositorio.

py -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"

Ejecución

.venv\Scripts\python -m axis_camera_mcp.server

Base de conocimiento (RAG)

Una base de conocimiento local y sin conexión permite al LLM buscar en la documentación real de la API VAPIX y en los hallazgos propios de este proyecto, obtenidos con esfuerzo y verificados en vivo (campos obligatorios no documentados, valores de parámetros reales confirmados solo mediante prueba y error en vivo, etc.) en lugar de adivinarlos o volver a deducirlos cada vez.

Todo de código abierto, todo local: sin API de pago, sin servicio de base de datos vectorial:

  • Crawler (rag/crawler.py): requests simple + BeautifulSoup contra developer.axis.com (un sitio Docusaurus renderizado en servidor, sin necesidad de navegador headless), más el propio README/docs/vapix/*.py de este proyecto como fuentes locales.

  • Segmentación (rag/chunker.py): consciente de párrafos, ~700 caracteres con 100 de solapamiento.

  • Recuperación (rag/retriever.py): híbrida: BM25 (rank-bm25, coincidencias exactas de palabras clave como streamProfileName) y embeddings densos (sentence-transformers, all-MiniLM-L6-v2, solo CPU, para preguntas parafraseadas), combinados mediante fusión de rangos recíproca. Un archivo numpy .npz simple sirve como almacén vectorial (unos cientos de fragmentos hacen que la búsqueda coseno por fuerza bruta sea de escala de microsegundos: no merece la pena una dependencia de base de datos vectorial real).

  • Seguimiento (rag/tracking.py): un archivo SQLite local registra cada ejecución de ingesta (recuentos de fragmentos/caracteres por fuente, estado ok/error) y cada consulta (texto, resultados, puntuaciones), inspeccionable directamente o mediante la herramienta rag_stats.

Configuración: sentence-transformers arrastra torch, una instalación realmente pesada. En una máquina solo con CPU, instala primero explícitamente el wheel solo para CPU para que sea mucho más pequeño que la compilación resuelta por defecto:

.venv\Scripts\python -m pip install torch --index-url https://download.pytorch.org/whl/cpu
.venv\Scripts\python -m pip install -e ".[dev]"

Compilar/actualizar el índice (un paso separado que se ejecuta manualmente; nunca se ejecuta automáticamente al iniciar el servidor, por lo que el arranque sigue siendo rápido y sin llamadas de red):

.venv\Scripts\python -m axis_camera_mcp.rag.ingest

Edita axis_camera_mcp/rag/sources.json para añadir/eliminar páginas de documentación o archivos locales y, a continuación, vuelve a ejecutar el comando anterior. El modelo de embeddings (~80MB) se descarga una vez desde Hugging Face Hub en la primera ejecución y queda en caché después; todo lo demás es totalmente sin conexión. Los archivos de índice generados (rag/data/*.jsonl, *.npz, *.sqlite3) están en gitignore.

Consúltala con las herramientas search_knowledge y rag_stats (consulta la referencia de herramientas más abajo).

Registro con Claude Code/Desktop

{
  "mcpServers": {
    "axis-camera": {
      "command": "<path-to-repo>\\.venv\\Scripts\\python.exe",
      "args": ["-m", "axis_camera_mcp.server"]
    }
  }
}

Reinicia Claude Code/Desktop después de añadir esto para que aparezcan las herramientas.

Pruebas

.venv\Scripts\python -m pytest tests/ --ignore=tests/manual   # unit tests, mocked HTTP
.venv\Scripts\python tests/manual/live_smoke_test.py           # read-only checks against the real camera

Los scripts de tests/manual/ se comunican con la cámara real en config.json: revisa qué hace cada uno antes de ejecutarlo contra una cámara que te importe. live_smoke_test.py es de solo lectura. Los scripts mcp_harness_*.py ejercitan la ruta completa de llamada a herramientas MCP (incluidas mutaciones como movimientos PTZ, cambios de reloj/zona horaria y alta/eliminación de usuarios); estos fueron los scripts de verificación en vivo de este proyecto; trátalos como referencia, no como algo para re-ejecutar a la ligera contra una cámara de producción.

Referencia de herramientas

Información del dispositivo/API (solo lectura): get_device_info, get_supported_apis, get_camera_overview

Transmisión (ver la transmisión en vivo en la instalación local de VLC): start_stream, stop_stream, get_stream_status, list_stream_profiles

Instantánea (un solo fotograma fijo, separado de la transmisión de video): save_snapshot (solo archivo, el LLM nunca ve la imagen), get_snapshot (se devuelve directamente al LLM para que pueda describir lo que hay a la vista)

PTZ (paneo/inclinación/zoom; consulta docs/open-questions.md sobre la ausencia de efecto visual en esta cámara específica): ptz_move_absolute, ptz_move_relative, ptz_get_position, ptz_save_preset, ptz_goto_preset, ptz_list_presets

Sensor de imagen (brillo/contraste/saturación/nitidez, exposición, ganancia, obturador, balance de blancos: la configuración real del sensor/ISP, distinta del encuadre/recorte del PTZ y del iluminador físico de la luz): get_image_settings, set_image_appearance, set_exposure_mode, set_exposure_value, set_manual_gain, set_manual_shutter, set_white_balance

Superposiciones (texto/imagen incrustados en la transmisión de video): add_text_overlay, set_text_overlay, add_image_overlay, set_image_overlay, list_overlays, remove_overlay, get_overlay_capabilities

Reloj: get_clock_info, set_clock, set_timezone

Luz (esta cámara específica no tiene hardware de luz, confirmado mediante get_light_status, que lo informa claramente): get_light_status, activate_light/deactivate_light, enable_light/disable_light, set_light_intensity, get_valid_intensity, set_light_auto_mode

Usuarios: las mutaciones requieren confirm: true, la única área con consecuencias de seguridad reales: list_users (devuelve todas las cuentas con sus grupos de privilegios, para un llamador privilegiado), add_user, update_user, remove_user

Base de conocimiento (consulta "Base de conocimiento (RAG)" más arriba): search_knowledge (búsqueda híbrida BM25+embeddings en la documentación de VAPIX y en los hallazgos verificados en vivo de este proyecto, con citas de fuentes y puntuaciones), rag_stats (qué está indexado, de dónde, cuándo y el historial reciente de consultas; indica claramente si el índice necesita ejecutar rag.ingest)

Seguridad

Las mutaciones de cuentas de usuario (add_user, update_user, remove_user) requieren un argumento de herramienta explícito confirm: true y, sin él, lanzan un error claro: esta es la única área donde una llamada descuidada tiene consecuencias de seguridad reales (acceso no autorizado o un bloqueo accidental). Todo lo demás (PTZ, luz, reloj, transmisión, superposiciones, instantáneas) no requiere confirmación por diseño: es libremente reversible y se trata de una sola cámara que el usuario posee directamente, no de un sistema de producción compartido.

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.

  • MCP server for Clipkit — gives AI agents a video toolbox via the Clipkit schema.

  • MCP server for AI dialogue using various LLM models via AceDataCloud

View all MCP Connectors

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/cdp/GSX2026-axis-camera-mcp'

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