axis-camera-mcp
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 triedEn 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íneaskey=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/passwordconfig.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.serverBase 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):requestssimple + BeautifulSoup contradeveloper.axis.com(un sitio Docusaurus renderizado en servidor, sin necesidad de navegador headless), más el propio README/docs/vapix/*.pyde 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 comostreamProfileName) 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.npzsimple 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 herramientarag_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.ingestEdita 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 cameraLos 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.
This server cannot be installed
Maintenance
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
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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