Skip to content

About

Agent-native CLI + MCP server for Axis VAPIX. 65 commands (56 endpoint mirrors + 9 transcendence). Live-tested against Q6358-LE / Q6325-LE / P3285-LVE.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

VAPIX CLI

Every VAPIX call you'd reach for, plus a local SQLite history, fleet sweep, and an MCP server no other Axis wrapper has.

A single Go binary for fleet operations against Axis IP cameras. It absorbs every operation in the open VAPIX wrapper landscape (param.cgi, PTZ, applications, analytics, events, MQTT bridge), keeps a per-camera SQLite history of parameters and presets, and exposes an MCP server so an LLM agent can sweep a subnet, drive a PTZ camera to a preset, or diff parameter trees from a conversation. Built around the quirks that bite real Axis fleets: the Q6325-LE basicdeviceinfo digest loop, the AXIS OS 12 ONVIF/VAPIX user-database split, and the AOA + analytics-MQTT surfaces that landed in OS 12.2.

Install

git clone https://github.com/oneshot2001/vapix-pp-cli ~/Projects/vapix-pp-cli
cd ~/Projects/vapix-pp-cli
go build -o ~/go/bin/vapix-pp-cli ./cmd/vapix-pp-cli

Or, once tagged:

go install github.com/oneshot2001/vapix-pp-cli/cmd/vapix-pp-cli@latest

The MCP server lives at ./cmd/vapix-pp-mcp:

go build -o ~/go/bin/vapix-pp-mcp ./cmd/vapix-pp-mcp

Wire vapix-pp-mcp into your agent's MCP config like any stdio server.

Test cameras

This CLI was developed and verified against three personally-owned Axis cameras on a private LAN — not customer or production deployments:

  • AXIS Q6358-LE (192.168.1.33, AXIS OS 12.9) — PTZ thermal, full surface
  • AXIS Q6325-LE (192.168.1.32, AXIS OS 12.9) — PTZ visible
  • AXIS P3285-LVE (192.168.1.19, AXIS OS 12.7, HTTPS-only) — fixed dome

The Q6325-LE quirk (basicdeviceinfo digest loop) and the P3285's HTTPS-only listener both shipped the live test surface and informed the routing in device info and discover.

Authentication

Auth is per-camera HTTP Digest (Basic fallback). Pass credentials via --user/--password flags, the VAPIX_USER/VAPIX_PASSWORD env vars, or a ~/.config/vapix-pp-cli/config.toml registry that maps camera aliases to credentials. The CLI never persists secrets in its SQLite store.

Quick Start

# fingerprint every Axis camera in the subnet — model, firmware, MAC, OS major
vapix-pp-cli discover 192.168.1.0/24 --json


# fingerprint a single camera (uses param.cgi route — Q6325-LE-safe)
vapix-pp-cli device info --host 192.168.1.32


# drive a Q6358-LE to a named preset via PTZ goto
vapix-pp-cli ptz gotoserverpresetname --host 192.168.1.33 --preset Gate


# list every ACAP app installed on the camera with status + license
vapix-pp-cli applications list --host 192.168.1.33 --json


# discover all event topics on a P3285-LVE — feeds straight into events watch
vapix-pp-cli events list-topics --host 192.168.1.19 --json

Unique Features

These capabilities aren't available in any other tool for this API.

Fleet operations

  • discover — Sweep a CIDR range and fingerprint every Axis camera it finds in one parallel shot.

    When an installer drops you on a network with 'somewhere between 4 and 40 Axis cameras', this turns 'go figure out the inventory' into one command.

    vapix-pp-cli discover 192.168.1.0/24 --json
  • sweep param — Run the same param.cgi query against every camera in the local store and return one table.

    'What hostname is each camera reporting?' takes one command instead of an ad-hoc loop you re-write every audit.

    vapix-pp-cli sweep param --group root.Network.HostName --json

Local state that compounds

  • param diff — Diff the current param.cgi tree of a camera against the previous snapshot stored in the local SQLite cache.

    Answers 'did anything change on this camera in the last week?' without trusting whoever last touched the on-camera config.

    vapix-pp-cli param diff --host 192.168.1.33 --since 7d --json
  • preset copy — Read presets from one camera and write them to another using their stored coordinates.

    Replacing or duplicating a PTZ rig stops being a 30-minute click-through and becomes one line.

    vapix-pp-cli preset copy --from Q6358 --to Q6325
  • applications drift — Diff the installed ACAP application set per camera against last sync; flag installs, uninstalls, version bumps.

    Catches 'who installed an unsigned ACAP on the front-door camera' without manually walking each device.

    vapix-pp-cli applications drift --json

Compound operator workflows

  • ptz tour — Walk a sequence of named presets with a configurable dwell at each.

    Manual rounds for an integrator becomes scriptable; useful for demos and for late-night perimeter sweeps.

    vapix-pp-cli ptz tour --host 192.168.1.33 --presets Gate,Lobby,Lot --dwell 8
  • events watch — Tail the MQTT bridge for a topic and shell out to a snapshot command when it fires.

    Captures evidence frames the second a camera detects motion — without standing up a separate event broker.

    vapix-pp-cli events watch --host 192.168.1.33 --topic tns1:VideoSource/MotionAlarm --on-fire 'snapshot.sh {topic} {ts}'
  • doctor — Composite health check — param reachability, PTZ whoami, ACAP app list, system clock skew, current firmware.

    Pre-flight before a demo or an installation handoff in one command.

    vapix-pp-cli doctor --host 192.168.1.33 --json

Reachability mitigation

  • device info — Probes param.cgi first (works on Q6325-LE where basicdeviceinfo.cgi loops on digest 401) then falls back to richer endpoints for newer OS.

    Avoids the silent 401-loop failure mode that has bitten every team that wrote 'a quick Python script' against a Q6325-LE.

    vapix-pp-cli device info --host 192.168.1.32

Usage

Run vapix-pp-cli --help for the full command reference and flag list.

Commands

aoa

AXIS Object Analytics (AOA) and analytics-metadata configuration

  • vapix-pp-cli aoa aoa-config - Get AXIS Object Analytics configuration (scenarios, triggers, classes)
  • vapix-pp-cli aoa aoa-supported - List supported scenario types and capabilities
  • vapix-pp-cli aoa metadata-producers - List RTSP analytics metadata producers and their per-channel state
  • vapix-pp-cli aoa metadata-sample - Request a one-shot sample of metadata from a named producer
  • vapix-pp-cli aoa mqtt-data-sources - AXIS OS 12.2+ — list available analytics-MQTT data sources

applications

AXIS Camera Application Platform (ACAP) — manage installed apps via /axis-cgi/applications/*

  • vapix-pp-cli applications list - List installed ACAP applications: name, version, status, license
  • vapix-pp-cli applications remove - Uninstall an ACAP application. Destructive — use --dry-run first.
  • vapix-pp-cli applications restart - Restart an ACAP application
  • vapix-pp-cli applications start - Start an ACAP application by package name
  • vapix-pp-cli applications stop - Stop a running ACAP application

device

Device identity, capabilities, and lifecycle

  • vapix-pp-cli device info - Fingerprint device — model, firmware, serial, MAC, AXIS OS via param.cgi (works on Q6325-LE where basicdeviceinfo.cgi loops on digest 401)
  • vapix-pp-cli device properties - List root.Properties tree — capability flags, AXIS OS major/minor, supported features
  • vapix-pp-cli device restart - Reboot the device. Use --dry-run first.
  • vapix-pp-cli device systemtime - Get device system time

events

Event subscription and topic discovery

  • vapix-pp-cli events action-configurations - List action configurations (SOAP GetActionConfigurations)
  • vapix-pp-cli events action-rules - List configured action rules (SOAP GetActionRules)
  • vapix-pp-cli events action-templates - List supported action types (SOAP GetActionTemplates)
  • vapix-pp-cli events change-virtual-input - Trigger a virtual input event (SOAP ChangeVirtualInputState) — useful for testing rules
  • vapix-pp-cli events list-topics - List all event topics on this device (SOAP GetEventInstances). Returns ONVIF-shaped topic tree.
  • vapix-pp-cli events recipient-templates - List supported recipient templates
  • vapix-pp-cli events recipients - List configured recipients

media

Snapshots and live image capture

  • vapix-pp-cli media snapshot - Capture a JPEG snapshot. Use --output to write to a file; default is base64.
  • vapix-pp-cli media streamprofiles - List configured stream profiles

mqtt

MQTT client + Event Bridge configuration via /axis-cgi/mqtt/*

  • vapix-pp-cli mqtt activate-client - Activate (start) the MQTT client
  • vapix-pp-cli mqtt client-config - Get MQTT client configuration (broker, credentials, TLS, last will)
  • vapix-pp-cli mqtt client-status - Get MQTT client status (running, broker URL, last error)
  • vapix-pp-cli mqtt deactivate-client - Deactivate (stop) the MQTT client
  • vapix-pp-cli mqtt event-bridge-publish - Get current event publication map (which event topics → MQTT topics)
  • vapix-pp-cli mqtt event-bridge-subscribe - Get current MQTT subscription map (incoming MQTT → device events)

param

Universal parameter tree (param.cgi). The most reliable VAPIX surface — works across every Axis device.

  • vapix-pp-cli param add - Add a new dynamic parameter (motion windows, stream profiles, etc.)
  • vapix-pp-cli param list - List all parameters or a specific group. Returns key=value pairs.
  • vapix-pp-cli param listdefinitions - List parameter definitions (type, range, default) — useful for discovery
  • vapix-pp-cli param remove - Remove a dynamic parameter
  • vapix-pp-cli param update - Update an existing parameter. Use param.update KEY VALUE.

preset

PTZ preset save / rename / delete via /axis-cgi/com/ptzconfig.cgi

  • vapix-pp-cli preset list - List all server presets on this camera
  • vapix-pp-cli preset remove - Remove a named preset
  • vapix-pp-cli preset removeall - Remove every server preset on this camera. Destructive — use --dry-run first.
  • vapix-pp-cli preset rename - Rename a preset by number
  • vapix-pp-cli preset save - Save current PTZ position as a named preset

ptz

Pan / tilt / zoom control via /axis-cgi/com/ptz.cgi

  • vapix-pp-cli ptz areazoom - Area zoom — center on pixel coords + zoom factor
  • vapix-pp-cli ptz autofocus - Enable or disable autofocus
  • vapix-pp-cli ptz autoiris - Enable or disable autoiris
  • vapix-pp-cli ptz auxiliary - Trigger an auxiliary function (e.g. wiper, washer, defogger). Device-specific.
  • vapix-pp-cli ptz center - Center on pixel coordinates within the live image
  • vapix-pp-cli ptz continuouspantiltmove - Continuous pan/tilt move at given speed (-100..100, comma-separated). Set 0,0 to stop.
  • vapix-pp-cli ptz continuouszoommove - Continuous zoom at given speed (-100..100). 0 to stop.
  • vapix-pp-cli ptz gotoserverpresetname - Move to a server-side preset by name
  • vapix-pp-cli ptz gotoserverpresetno - Move to a server-side preset by number
  • vapix-pp-cli ptz info - List supported PTZ commands on this device
  • vapix-pp-cli ptz ircutfilter - Control IR cut filter (auto | on | off)
  • vapix-pp-cli ptz move - Move in a named direction (up/down/left/right/upleft/upright/downleft/downright/home/stop)
  • vapix-pp-cli ptz pan - Absolute pan position (-180..180 degrees)
  • vapix-pp-cli ptz query - Query PTZ status: position, presets, limits
  • vapix-pp-cli ptz tilt - Absolute tilt position
  • vapix-pp-cli ptz whoami - Identify PTZ driver + capabilities. First call to confirm a camera is PTZ-capable.
  • vapix-pp-cli ptz zoom - Absolute zoom position (1..9999, device-dependent)

Output Formats

# Human-readable table (default in terminal, JSON when piped)
vapix-pp-cli applications list

# JSON for scripting and agents
vapix-pp-cli applications list --json

# Filter to specific fields
vapix-pp-cli applications list --json --select id,name,status

# Dry run — show the request without sending
vapix-pp-cli applications list --dry-run

# Agent mode — JSON + compact + no prompts in one flag
vapix-pp-cli applications list --agent

Agent Usage

This CLI is designed for AI agent consumption:

  • Non-interactive - never prompts, every input is a flag
  • Pipeable - --json output to stdout, errors to stderr
  • Filterable - --select id,name returns only fields you need
  • Previewable - --dry-run shows the request without sending
  • Explicit retries - add --idempotent to create retries when a no-op success is acceptable
  • Confirmable - --yes for explicit confirmation of destructive actions
  • Piped input - write commands can accept structured input when their help lists --stdin
  • Offline-friendly - sync/search commands can use the local SQLite store when available
  • Agent-safe by default - no colors or formatting unless --human-friendly is set

Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.

Use with Claude Code

Install the focused skill — it auto-installs the CLI on first invocation:

npx skills add mvanhorn/printing-press-library/cli-skills/pp-vapix -g

Then invoke /pp-vapix <query> in Claude Code. The skill is the most efficient path — Claude Code drives the CLI directly without an MCP server in the middle.

Use as an MCP server in Claude Code (advanced)

If you'd rather register this CLI as an MCP server in Claude Code, install the MCP binary first:

Install the MCP binary from this CLI's published public-library entry or pre-built release.

Then register it:

claude mcp add vapix vapix-pp-mcp

Use with Claude Desktop

This CLI ships an MCPB bundle — Claude Desktop's standard format for one-click MCP extension installs (no JSON config required).

To install:

  1. Download the .mcpb for your platform from the latest release.
  2. Double-click the .mcpb file. Claude Desktop opens and walks you through the install.

Requires Claude Desktop 1.0.0 or later. Pre-built bundles ship for macOS Apple Silicon (darwin-arm64) and Windows (amd64, arm64); for other platforms, use the manual config below.

Manual JSON config (advanced)

If you can't use the MCPB bundle (older Claude Desktop, unsupported platform), install the MCP binary and configure it manually.

Install the MCP binary from this CLI's published public-library entry or pre-built release.

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "vapix": {
      "command": "vapix-pp-mcp"
    }
  }
}

Health Check

vapix-pp-cli doctor

Verifies configuration and connectivity to the API.

Configuration

Config file: ~/.config/vapix-pp-cli/config.toml

Static request headers can be configured under headers; per-command header overrides take precedence.

Troubleshooting

Not found errors (exit code 3)

  • Check the resource ID is correct
  • Run the list command to see available items

API-specific

  • Q6325-LE returns 401 in a loop on basicdeviceinfo.cgi — use vapix-pp-cli device info — it routes through param.cgi by default for exactly this reason
  • ONVIF user works for VAPIX but not for events on AXIS OS 12.x — AXIS OS 12.x uses separate user databases for VAPIX and ONVIF; set up a VAPIX-only user for events
  • auxiliary command (speeddry, wiper:on) returns 'unsupported' — auxiliaries are device-specific; run vapix-pp-cli ptz info first to enumerate what this camera supports
  • snapshot returns base64 blob and floods the terminal — pass --output frame.jpg to write binary to disk — base64 is the default for agent piping

Cookbook

Realistic recipes that use the focused VAPIX subset (param.cgi + PTZ + applications + analytics + events).

1. Discover every Axis camera on the lab subnet

vapix-pp-cli --user root --password pass discover 192.168.1.0/24 --json --select host,model,firmware,axis_os_major

The CIDR sweep tries HTTP first; HTTPS-only cameras (P3285-LVE) fall through to a TLS-skip-verify probe automatically. Non-Axis 200s (routers, NAS web UIs) are filtered out. Hits are upserted into ~/.local/share/vapix-pp-cli/data.db.

2. Drive the Q6358-LE to a preset, then snap a frame

# move
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
  ptz gotoserverpresetname --preset Gate

# snap (give the lens 2s to settle)
sleep 2
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
  media snapshot --resolution 1920x1080 --output gate.jpg

3. Run a guard tour across three presets every night

vapix-pp-cli --host 192.168.1.33 --user root --password pass \
  ptz tour --presets Gate,Lobby,Lot --dwell 8 --repeat 3 --speed 90

Wire it as a cron job. The tour walks each preset, sleeps, walks the next.

4. Subscribe to motion events on the P3285 for 60 seconds

The CLI stages an MQTT bridge handoff in v1 (it prints the mosquitto_sub invocation that hooks the camera's MQTT bridge) — point it at any MQTT client:

vapix-pp-cli --host https://192.168.1.19 --insecure --user root --password pass \
  events watch --topic 'tns1:VideoSource/MotionAlarm' --on-fire 'snapshot.sh' --duration 60

Configure the camera's MQTT bridge first via vapix-pp-cli mqtt event-bridge-publish.

5. Diff a Q6358 parameter tree against last week's snapshot

# 7 days ago you ran:
#   vapix-pp-cli --host 192.168.1.33 --user root --password pass param diff --since 0s
# (any param diff invocation also persists a snapshot; the first run reports "no baseline")

# today:
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
  param diff --group root.PTZ --since 7d --json

Returns added/removed/changed keys. Aimed at "did anything drift since the integrator left the site?" audits.

6. Sweep one query across every cam in the local store

vapix-pp-cli --user root --password pass sweep param --group root.Network.HostName

Hits every camera saved by discover. One table out, no per-camera scripting.

7. Catch unexpected ACAP installs across the fleet

# Run weekly as a cron:
for ip in 192.168.1.32 192.168.1.33 192.168.1.19; do
  vapix-pp-cli --host $ip --user root --password pass applications drift --since 7d --json
done

Each call snapshots the running ACAP set and diffs against the prior week. Catches "who installed an unsigned ACAP on the front-door camera."

8. Composite health check before a demo

vapix-pp-cli --host 192.168.1.33 --user root --password pass doctor --json

Reports auth status, brand, firmware probe, and cache state in one shot.


Sources & Inspiration

This CLI was built by studying these projects and resources:

Generated by CLI Printing Press

OpenAPI

A linted OpenAPI 3.1 + llms.txt generated from spec.yaml and corrected against live devices: https://github.com/oneshot2001/vapix-openapi

About

Agent-native CLI + MCP server for Axis VAPIX. 65 commands (56 endpoint mirrors + 9 transcendence). Live-tested against Q6358-LE / Q6325-LE / P3285-LVE.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages