Skip to main content
Glama
owine

UniFi Protect MCP

by owine

UniFi Protect MCP Server

An MCP (Model Context Protocol) server that exposes UniFi Protect's Integration REST API as tools for Claude Code and other MCP clients. Aligned with UniFi Protect API 7.3.70, with tools covering cameras, lights, sensors, chimes, viewers, sirens, fobs, relays, speakers, bridges, link stations, alarm hubs, arm profiles, live views, files, users, point-of-sale events, NVR status, and WebSocket subscriptions.

Prerequisites

  • Node.js 22.x (22.13 or newer) or 24.x — see engines in package.json

  • A UniFi Protect system with the Integration API enabled

  • An API key generated from your UniFi Protect console (see Choosing an API key)

Related MCP server: UniFi Internal API MCP Server

Setup

Quick start (npx)

Add to Claude Code with a single command — no clone or build needed:

claude mcp add-json unifi-protect '{"command":"npx","args":["-y","@owine/unifi-protect-mcp@latest"],"env":{"UNIFI_PROTECT_HOST":"192.168.1.1","UNIFI_PROTECT_API_KEY":"your-api-key"}}' -s user

Use -s user for global availability across all projects, or -s project for the current project only.

A local console usually has a self-signed certificate, so the first call fails with a certificate error until you trust it: see Self-signed console certificates.

@latest runs the newest release every time the server starts, including a new major version. To take fixes but choose when to make breaking upgrades, pin the major version you have tested instead (@owine/unifi-protect-mcp@<major>).

From source

If you prefer to build locally:

git clone https://github.com/owine/unifi-protect-mcp.git
cd unifi-protect-mcp
corepack enable   # provides pnpm at the version pinned in package.json
pnpm install
pnpm run build

This project uses pnpm — npm install ignores pnpm-lock.yaml and may resolve different dependency versions than CI.

Then add to Claude Code:

claude mcp add-json unifi-protect '{"command":"node","args":["/path/to/unifi-protect-mcp/dist/index.js"],"env":{"UNIFI_PROTECT_HOST":"192.168.1.1","UNIFI_PROTECT_API_KEY":"your-api-key"}}' -s user

Environment Variables

Variable

Required

Default

Description

UNIFI_PROTECT_HOST

Yes

—

IP or hostname of your UniFi Protect console, optionally with :port. A leading https:// and trailing / are stripped; bracket IPv6 addresses

UNIFI_PROTECT_API_KEY

Yes

—

API key from the console's integration settings (see Choosing an API key). Surrounding whitespace is trimmed; a key with a control character inside is refused at startup

UNIFI_PROTECT_CA_CERT

No

—

Absolute path to a PEM file with the console's certificate, to verify a self-signed console without turning verification off (see below). Not allowed with api.ui.com or together with UNIFI_PROTECT_VERIFY_SSL=false

UNIFI_PROTECT_VERIFY_SSL

No

true

Set to false (or 0/no/off, any case) to skip certificate verification for this server's connections to the console. Prefer UNIFI_PROTECT_CA_CERT. Not allowed with api.ui.com. Unrecognized values keep the default

UNIFI_PROTECT_READ_ONLY

No

true

Set to false (or 0/no/off, any case) to enable write tools (default is monitoring-only mode). Unrecognized values keep the default

UNIFI_PROTECT_CONSOLE_ID

No

—

Cloud Connector console ID. Only used when UNIFI_PROTECT_HOST is api.ui.com; ignored (with a warning on stderr) otherwise

The startup line in the MCP host's server log says whether the server is read-only or read-write. A configuration error names the variable at fault, and the server exits.

Self-signed console certificates

UniFi consoles ship with a self-signed certificate, so the first call to a local console usually fails with a certificate error. The safe fix is to trust that one certificate. Save it:

openssl s_client -connect 192.168.1.1:443 </dev/null 2>/dev/null | openssl x509 > ~/.config/unifi-protect-console.pem

Set UNIFI_PROTECT_CA_CERT to the file's absolute path (for example /home/you/.config/unifi-protect-console.pem); MCP hosts do not expand ~ or $HOME in env. The server then accepts exactly that certificate, even though it is issued to a name like unifi.local and you connect by IP. Any other certificate must chain to the file and match the hostname. If the network between you and the console is not trusted, compare the fingerprint (openssl x509 -in <file> -noout -fingerprint -sha256) with the console's. If the console later generates a new certificate, save it again.

Setting UNIFI_PROTECT_VERIFY_SSL=false instead turns certificate checks off for this server's connections to the console, and only those (other TLS connections in the process are unaffected). Anyone who can intercept that traffic can then read the API key, so use it only on a network you trust.

Choosing an API key

  • Use the least-privileged key that works. Create the key from an admin account with no more access than you need. For the default read-only mode, that means an admin with view-only access to Protect; use a full-access admin only with UNIFI_PROTECT_READ_ONLY=false.

  • Prefer a local console key to a Site Manager key. A Site Manager key (Cloud Connector, api.ui.com) reaches every console on the account and travels over the internet.

Manual Configuration

Alternatively, add to your ~/.claude.json under the top-level "mcpServers" key, or to Claude Desktop's claude_desktop_config.json the same way:

{
  "mcpServers": {
    "unifi-protect": {
      "command": "npx",
      "args": ["-y", "@owine/unifi-protect-mcp@latest"],
      "env": {
        "UNIFI_PROTECT_HOST": "192.168.1.1",
        "UNIFI_PROTECT_API_KEY": "your-api-key",
        "UNIFI_PROTECT_CA_CERT": "/absolute/path/to/console.pem"
      }
    }
  }
}

Cloud Connector

To reach a console through Ubiquiti's Cloud Connector instead of over the local network, set UNIFI_PROTECT_HOST=api.ui.com and UNIFI_PROTECT_CONSOLE_ID to the console's ID, and supply a Site Manager API key (unifi.ui.com → Settings → API) as UNIFI_PROTECT_API_KEY. That is a different credential from a local console API key. Requests are routed through /v1/connector/consoles/{id}.

TLS verification stays on: the server refuses to start with UNIFI_PROTECT_VERIFY_SSL=false or UNIFI_PROTECT_CA_CERT for api.ui.com. Ubiquiti's cloud has a publicly trusted certificate, and a pinned certificate would replace the public certificate authorities for this server's connections.

Find your console ID with:

curl -s https://api.ui.com/v1/hosts -H "X-API-KEY: $KEY" | jq -r '.data[].id'

WebSocket subscriptions do not work over Cloud Connector. The connector proxies REST calls but returns HTTP 404 on a WebSocket upgrade, so protect_subscribe_devices and protect_subscribe_events fail fast with an explanatory error. Every other tool, including snapshots and file uploads, works. Connect directly to the console host if you need subscriptions.

Note that /v1/hosts reports protect under controllers for consoles where Protect is merely available, not necessarily installed; only consoles actually running Protect will answer.

Setting UNIFI_PROTECT_CONSOLE_ID against a local host is not fatal: the server logs a warning and talks to that host directly.

Upgrading to 3.0

3.0 puts more actions behind confirmation: physical outputs, disarming, anything that weakens alarm coverage, and live video and two-way audio. It also scopes TLS settings to this server, keeps every result within what one MCP message can carry, and makes cancellation stop the request to Protect.

If you use the server only through an LLM client (Claude Code, Claude Desktop, …), the model reads the new parameters from the tool schemas, so most setups need no change. Check three things:

  • Cloud Connector with verification off no longer starts. Unset UNIFI_PROTECT_VERIFY_SSL when UNIFI_PROTECT_HOST=api.ui.com.

  • Spellings of UNIFI_PROTECT_READ_ONLY / UNIFI_PROTECT_VERIFY_SSL that 2.x ignored now take effect (table below).

  • Expect more approval prompts. Update tools and every confirm-gated tool are now annotated destructive (below).

Read on if you call tools from scripts or saved agent configurations, or keep allow-lists keyed on tool annotations.

Check your environment variables first

2.x treated only the exact string false as false. 3.0 also accepts 0, no and off, in any case, so a value that 2.x silently ignored now takes effect:

Setting

2.x

3.0

UNIFI_PROTECT_READ_ONLY=0 (or no, off, FALSE)

Read-only

⚠️ Write tools enabled

UNIFI_PROTECT_VERIFY_SSL=0 (or no, off, FALSE)

Certificate verified

Verification skipped

UNIFI_PROTECT_HOST=api.ui.com with UNIFI_PROTECT_VERIFY_SSL=false (or 0/no/off)

Verification skipped

⚠️ Startup fails: "TLS verification cannot be disabled for api.ui.com". Unset UNIFI_PROTECT_VERIFY_SSL

UNIFI_PROTECT_VERIFY_SSL=false

Turned verification off for every TLS connection in the process

Applies only to this server's connections to the console. Prefer the new UNIFI_PROTECT_CA_CERT

UNIFI_PROTECT_API_KEY pasted with a trailing newline or spaces

Sent as is; every call failed and the error quoted the key

Trimmed

UNIFI_PROTECT_API_KEY with a control character inside

Same

Startup fails with a message that does not repeat the key

Any other unrecognized value keeps the safe default (read-only, verification on), as before. New: UNIFI_PROTECT_CA_CERT verifies a console's self-signed certificate (see Self-signed console certificates). Configuration errors now name the variable at fault, and the startup log line says whether the server is read-only or read-write.

Tool input changes (breaking)

Tool

2.x

3.0

protect_disable_arm_alarm

No confirmation

Requires confirm: true

protect_activate_relay_output

Omitting state toggled the output

Requires confirm: true and state ("on" / "off")

protect_trigger_alarm_hub_output

Omitting enable toggled the output

Requires confirm: true and enable (true / false)

protect_create_rtsp_stream, protect_create_talkback

No confirmation

Requires confirm: true; the returned URLs are credentials

protect_stop_siren

No confirmation

Requires confirm: true

protect_delete_arm_profile, protect_set_current_arm_profile

No confirmation

Requires confirm: true

protect_update_sensor

No confirmation

Requires confirm: true when settings include alarmSettings, motionSettings, glassBreakSettings, armProfileIds or scheduleMode

protect_update_fob

No confirmation

Requires confirm: true when settings include armControlSettings

protect_update_arm_profile

No confirmation

Requires confirm: true when settings include schedules or automations

Every tool that takes an ID

Any string

Only IDs as list and get tools return them: letters, digits, - and _. An arm profile ID cannot be settings, enable or disable; an alarm webhook ID cannot be . or ..

A call that leaves out state or enable, or passes a malformed ID, fails input validation. A call without confirm: true returns an error result ("This action requires confirmation: …"), so the agent can ask you and call again.

Toggling was removed because it is not safe to retry: a repeated toggle flips a gate or lock back to where it started. To act on the current state, read it first: each entry in outputs from protect_get_relay carries a state, and protect_get_alarm_hub reports alarmHub.output keyed by channel.

// 2.x: toggles output 0
{ "id": "<relay id>", "outputId": 0 }
// 3.0: explicit and safe to retry
{ "id": "<relay id>", "outputId": 0, "state": "on", "confirm": true }

Relaxed: a dryRun: true preview never needs confirm. In 2.x, protect_disable_mic and protect_trigger_alarm_webhook rejected a dry run without confirm: true. Calls that send both still work.

New: every list tool except protect_list_nvrs takes optional limit and offset. A call with neither returns the whole list, as before.

Annotation changes (breaking for allow-lists)

  • protect_update_camera, every protect_update_<device> tool, protect_update_arm_profile and protect_update_liveview are now destructiveHint: true, and so is every tool that takes confirm (protect_stop_siren, protect_set_current_arm_profile, protect_create_rtsp_stream, protect_create_talkback, protect_disable_arm_alarm, protect_activate_relay_output, protect_trigger_alarm_hub_output among them). MCP clients that auto-approve non-destructive tools will now ask before running them, and allow-lists keyed on the annotation need updating.

  • Every tool now has a title and openWorldHint: false; the relay and alarm-hub output tools declare idempotentHint: true.

Stricter validation

  • UNIFI_PROTECT_HOST is parsed as a URL authority. A pasted https://192.168.1.1/ now works, and :443 is dropped. A path, credentials, a non-numeric or out-of-range port, or an unbracketed IPv6 address now fails at startup instead of at the first request. Write IPv6 as [2001:db8::1] or [2001:db8::1]:7443.

  • protect_upload_file rejects base64Data that is not valid base64 (bad characters, length or padding), and empty input, where 2.x uploaded corrupt bytes without an error. A data: URL prefix and line breaks are accepted. A file too large to fit one MCP message is refused with "File too large to send in one MCP message"; in 2.x an oversized request closed the server's stdio transport and the server exited with nothing logged.

  • protect_update_liveview rejects a body whose settings.id differs from id.

Output changes

  • Text results are compact JSON, not indented. structuredContent is unchanged; use it if you parse results.

  • Single-object results and dry-run previews now pass MCP clients' output validation. In 2.x, a top-level field the schema did not list, or any dry-run preview of a tool with an output schema, failed with -32602.

  • A snapshot, response or other result too large for one MCP message is refused with an error saying so. In 2.x it was sent, and the MCP client dropped the connection.

  • The protect_upload_file dry-run preview reports byteLength (decoded size) in place of dataLength (base64 string length).

  • protect_subscribe_devices / protect_subscribe_events stop at a message cap or a size budget, whichever comes first (both stated in each tool's description), and add truncated: true. duration is the time actually spent listening. A listen that fails before any message arrives (refused or unauthorized socket) returns an error result; in 2.x it returned {messages: [], error} as a success. One that fails partway still returns what it collected, with error.

  • A timeout names the call and what to do: PATCH /cameras/…: Protect did not respond within … s, followed by "Retry when the console responds" for reads, or "The change may still have been applied; check before retrying" for writes. Snapshots and uploads time out before the MCP client's own request timeout, so you see this message instead of a bare client timeout.

  • Network and TLS errors name the underlying cause, e.g. fetch failed: connect ECONNREFUSED …, instead of a bare fetch failed.

  • Cancelling a tool call aborts its request to Protect, and a cancelled subscription closes its socket. In 2.x a cancelled relay switch could still land afterwards.

  • The server reports its real package version to MCP clients; 2.x always reported 1.0.0. It also sends server instructions (see Safety Features).

For packagers

undici is a new runtime dependency (scoped TLS and connection keep-alive).

Safety Features

  • Tool annotations. Every tool declares readOnlyHint, destructiveHint and openWorldHint: false (each talks only to your console), plus a readable title, so MCP clients such as Claude Code can decide when to ask you. destructiveHint: true marks every tool that deletes or replaces existing state, which includes every protect_update_* tool, and every tool that takes confirm. Clients that auto-approve non-destructive tools ask before those. The tool tables below mark them DESTRUCTIVE.

  • Server instructions. On connect, the server gives the MCP host a short guide for the model, matched to read-only or read-write mode. It says to treat names and event text from the console as data, not instructions; that RTSPS and talkback URLs are credentials; and, when writes are enabled, to preview with dryRun and ask you before passing confirm.

  • Read-only mode. On by default. Only the read tools (list, get, snapshot, subscriptions) are registered; write tools do not exist for the model, and registering one in read-only mode fails at startup. Set UNIFI_PROTECT_READ_ONLY=false to enable writes. Read-only mode still returns RTSPS URLs from protect_get_rtsp_streams, and those are credentials for live video.

  • Confirmation parameter. Tools that are irreversible, switch physical outputs, trigger the alarm webhook, stop a siren, disarm or weaken alarm coverage, or open live video or two-way audio refuse to act unless the call carries confirm: true. Without it the tool returns an error naming the action, so the agent can ask you first. protect_update_sensor, protect_update_fob and protect_update_arm_profile need it only when the change touches alarm-related settings (each tool's description names them); renames and LED changes do not. confirm is filled in by the model, so it is a prompt for the model to ask you, not a lock; for a human gate, keep your MCP client's approval prompts on for destructive tools.

  • Dry-run support. Every write tool accepts dryRun: true and returns the request it would send (dryRun, action, path, body) without changing anything. A dry run never needs confirm.

  • Request safety. IDs must be IDs returned by list and get tools, and a request path that would resolve outside the Integration API is refused before it is sent. Redirects are refused, so the API key is never forwarded. Cancelling a tool call aborts its request to Protect.

See SECURITY.md for reporting vulnerabilities and operating the server safely.

Structured output

Read tools, and write tools that return the resource, declare an outputSchema, and return structuredContent alongside compact JSON text. Schemas are published as loose objects, so a field a firmware update adds flows through instead of failing validation. A list's items are under result; a paged list also has totalCount and offset. protect_get_snapshot returns an image. A dry run returns {dryRun, action, path, body}. Action endpoints that return no body succeed with an empty result.

Tools

DESTRUCTIVE marks tools annotated destructiveHint: true. Requires confirm: true marks tools that take confirm; every one of them is also DESTRUCTIVE. Pages with limit/offset marks list tools that take them.

System

Tool

Description

protect_get_info

Get system information and version details

protect_list_nvrs

Get the NVR console info (a single object)

Subscriptions

Tool

Description

protect_subscribe_devices

Subscribe via WebSocket to device state updates for a short window (not over Cloud Connector)

protect_subscribe_events

Subscribe via WebSocket to event notifications for a short window (not over Cloud Connector)

Cameras

Tool

Description

protect_list_cameras

List all cameras (pages with limit/offset)

protect_get_camera

Get camera details by ID

protect_update_camera

DESTRUCTIVE: Update camera settings

protect_get_snapshot

Get a JPEG snapshot (returns image)

protect_create_rtsp_stream

DESTRUCTIVE: Create an RTSPS stream session; the returned URLs are credentials for live video (requires confirm: true)

protect_get_rtsp_streams

Get active RTSPS stream sessions (the URLs are credentials for live video)

protect_delete_rtsp_stream

DESTRUCTIVE: Stop and delete an active RTSPS stream

protect_create_talkback

DESTRUCTIVE: Create a talkback (two-way audio) session; the returned URL is a credential (requires confirm: true)

protect_disable_mic

DESTRUCTIVE: Irreversibly disable the camera microphone; only a factory reset restores it (requires confirm: true)

protect_start_ptz_patrol

Start PTZ patrol at a given slot

protect_stop_ptz_patrol

Stop PTZ patrol

protect_goto_ptz_preset

Move PTZ to a preset position

Lights

Tool

Description

protect_list_lights

List all lights (pages with limit/offset)

protect_get_light

Get light details by ID

protect_update_light

DESTRUCTIVE: Update light settings

Sensors

Tool

Description

protect_list_sensors

List all sensors (pages with limit/offset)

protect_get_sensor

Get sensor details by ID

protect_update_sensor

DESTRUCTIVE: Update sensor settings (requires confirm: true to change alarm, motion or glass-break settings, arm profiles or schedule mode)

Chimes

Tool

Description

protect_list_chimes

List all chimes (pages with limit/offset)

protect_get_chime

Get chime details by ID

protect_update_chime

DESTRUCTIVE: Update chime settings

Viewers

Tool

Description

protect_list_viewers

List all viewers (pages with limit/offset)

protect_get_viewer

Get viewer details by ID

protect_update_viewer

DESTRUCTIVE: Update viewer settings

Sirens

Tool

Description

protect_list_sirens

List all sirens (pages with limit/offset)

protect_get_siren

Get siren details by ID

protect_update_siren

DESTRUCTIVE: Update siren settings (name, volume, LED)

protect_play_siren

Activate the siren alarm for a given duration (5/10/20/30s)

protect_stop_siren

DESTRUCTIVE: Stop an active siren; it silences an alarm (requires confirm: true)

protect_test_siren_sound

Test the siren sound for 5 seconds at a given volume

Fobs

Tool

Description

protect_list_fobs

List all key fobs (pages with limit/offset)

protect_get_fob

Get fob details by ID

protect_update_fob

DESTRUCTIVE: Update fob settings (requires confirm: true to change arm control settings)

Relays

Tool

Description

protect_list_relays

List all relays (pages with limit/offset)

protect_get_relay

Get relay details by ID, including each output's state

protect_update_relay

DESTRUCTIVE: Update relay settings

protect_activate_relay_output

DESTRUCTIVE: Turn a relay output channel on or off, with optional pulse duration (requires confirm: true and an explicit state)

Speakers

Tool

Description

protect_list_speakers

List all speakers (pages with limit/offset)

protect_get_speaker

Get speaker details by ID

protect_update_speaker

DESTRUCTIVE: Update speaker settings (volume, mic)

protect_test_speaker_sound

Test the speaker sound at a given volume

Bridges

Tool

Description

protect_list_bridges

List all bridges (pages with limit/offset)

protect_get_bridge

Get bridge details by ID

protect_update_bridge

DESTRUCTIVE: Update bridge settings

Tool

Description

protect_list_link_stations

List all link stations, the non-alarm-hub gateways (pages with limit/offset)

protect_get_link_station

Get link station details by ID

protect_update_link_station

DESTRUCTIVE: Update link station settings

Alarm Hubs

Tool

Description

protect_list_alarm_hubs

List all alarm hubs (pages with limit/offset)

protect_get_alarm_hub

Get alarm hub details by ID

protect_update_alarm_hub

DESTRUCTIVE: Update alarm hub settings

protect_trigger_alarm_hub_output

DESTRUCTIVE: Turn an alarm hub output channel on or off: sirens, lights, locks (requires confirm: true and an explicit enable)

Arm Profiles — local alarm manager

Tool

Description

protect_list_arm_profiles

List all arm profiles (pages with limit/offset)

protect_create_arm_profile

Create a new arm profile

protect_set_current_arm_profile

DESTRUCTIVE: Set the active profile used when arming (requires confirm: true)

protect_update_arm_profile

DESTRUCTIVE: Update an arm profile (requires confirm: true to change schedules or automations)

protect_delete_arm_profile

DESTRUCTIVE: Delete an arm profile by ID (requires confirm: true)

protect_enable_arm_alarm

Arm the alarm using the current profile

protect_disable_arm_alarm

DESTRUCTIVE: Disarm the alarm (requires confirm: true)

Live Views

Tool

Description

protect_list_liveviews

List all live views (pages with limit/offset)

protect_get_liveview

Get live view details by ID

protect_create_liveview

Create a new live view

protect_update_liveview

DESTRUCTIVE: Replace a live view (send the full object from protect_get_liveview)

Alarm & Files

Tool

Description

protect_trigger_alarm_webhook

DESTRUCTIVE: Trigger an alarm webhook, firing its external alarm action (requires confirm: true)

protect_list_files

List device asset files (animations; pages with limit/offset)

protect_upload_file

Upload a device asset file (base64 in, sent as multipart/form-data)

Users

Tool

Description

protect_list_users

List Protect users, filtered by the key's access (pages with limit/offset)

protect_get_user

Get a Protect user by ID

protect_list_ulp_users

List UniFi Identity (ULP) users with enrolled credentials (pages with limit/offset)

protect_get_ulp_user

Get a UniFi Identity user by ID

Point of Sale

Tool

Description

protect_ingest_pos_transaction

Record a POS transaction as a camera event so it can be overlaid on recorded footage

Troubleshooting

Configuration errors go to the MCP host's server log and the server exits. Tool errors reach the agent as results starting with Error:.

Message

Cause and fix

Configuration error: UNIFI_PROTECT_HOST is required / UNIFI_PROTECT_API_KEY is required

Missing from the server's env.

UNIFI_PROTECT_HOST must be a hostname or IP …

A path, credentials or a bad port in the host; bracket IPv6 addresses.

UNIFI_PROTECT_API_KEY contains a control character …

Paste the key again.

cannot read UNIFI_PROTECT_CA_CERT (…)

The path does not exist for the server. Use an absolute path; ~ is not expanded.

UNIFI_PROTECT_CA_CERT must name a PEM file containing a certificate

No BEGIN CERTIFICATE block; run the openssl command again.

…cannot be combined with UNIFI_PROTECT_VERIFY_SSL=false / TLS verification cannot be disabled for api.ui.com / UNIFI_PROTECT_CA_CERT is for local consoles

Unset UNIFI_PROTECT_VERIFY_SSL (or UNIFI_PROTECT_CA_CERT for api.ui.com).

Ignoring UNIFI_PROTECT_CONSOLE_ID (log line)

The console ID only applies with UNIFI_PROTECT_HOST=api.ui.com.

… (read-only: write tools are not registered) (log line) and no write tools

Read-only is the default. Set UNIFI_PROTECT_READ_ONLY=false and restart the host.

fetch failed: … The console's TLS certificate could not be verified …

Save the console's certificate to UNIFI_PROTECT_CA_CERT. If you already did, the console has a new certificate: save it again.

fetch failed: … The certificate for api.ui.com could not be verified …

Something between you and Ubiquiti's cloud is presenting another certificate, such as a TLS-inspecting proxy or firewall.

fetch failed: connect ECONNREFUSED …, ENOTFOUND

Wrong or unreachable host.

HTTP 401 / HTTP 403

Wrong or revoked key, or its admin lacks the rights.

… Protect did not respond within … s

The console is slow. For a write, check whether it was applied before retrying.

… exceeds the …-byte limit / Result too large to send in one MCP message …

The response is too large for one MCP message. Page a list with limit and offset; for a snapshot, drop highQuality.

File too large to send in one MCP message

Upload a smaller file.

This action requires confirmation: …

Expected: the action needs confirm: true, and the agent should ask you first.

Use an ID returned by a list or get tool

The agent passed a name or a malformed ID.

Subscription failed: …

The WebSocket was refused or unauthorized; this is not "no activity".

WebSocket subscriptions are not available over Cloud Connector …

Connect to the console directly for subscriptions.

MCP error -32602 … Input validation error

The call broke the tool's input schema (for example a missing state); the message names the field.

Development

The Node version used for development is pinned in .nvmrc. With fnm installed, fnm use reads it automatically on cd.

pnpm run build         # Compile TypeScript
pnpm start             # Run the server
pnpm run typecheck     # Type-check src/ and tests/ without emitting
pnpm run lint          # ESLint, type-aware
pnpm run lint:fix      # ESLint with auto-fix
pnpm test              # Run all tests (vitest)
pnpm run test:watch    # Run tests in watch mode
pnpm run test:coverage # Run tests with coverage
pnpm run test:package  # Pack, install the tarball and smoke-test it over stdio

Git hooks are managed by lefthook — pnpm exec lefthook install enables them. Pre-commit runs ESLint on staged files, a full typecheck, and a GitGuardian secret scan when ggshield is installed (skipped otherwise), so fnm and pnpm both need to be on your PATH.

Commit conventions

This project uses conventional commits and release-please for automated releases:

  • feat: ... — new feature (minor version bump)

  • fix: ... — bug fix (patch version bump)

  • deps: ... — dependency update (patch version bump; Renovate's type for package bumps)

  • feat!: ... or BREAKING CHANGE: footer — breaking change (major version bump)

  • chore:, docs:, ci:, etc. — no version bump

On push to main, release-please opens a Release PR that bumps the version and updates CHANGELOG.md. Merging that PR publishes to npm automatically. Merge pull requests with a rebase merge, so each commit (and any BREAKING CHANGE footer) reaches the changelog.

To override the version number, add Release-As: x.x.x in the commit body:

git commit --allow-empty -m "chore: release 2.0.0" -m "Release-As: 2.0.0"

License

MIT

Available Tools

38 tools
protect_get_alarm_hubGet alarm hubB
Read-only

Get full details for a specific alarm hub by ID. Returns: id, modelKey ("linkstation"), name, mac, state, type, guid, isAlarmHub, ledSettings (isEnabled), lastEvent, alarmHub (armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. "tampered"), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus), threadState (network: status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAlarm hub ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
alarmHubNoAlarm hub status (object: armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. "tampered", added in 7.3.x), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus)
modelKeyNoResource kind
lastEventNoLast event timestamp in epoch ms (number)
isAlarmHubNoWhether this device is an alarm hub (boolean)
ledSettingsNoLED settings (object: isEnabled)
threadStateNoThread radio state, added in 7.3.x (object: network — status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt)

TDQS

B3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered without the description. The description adds only a restatement of returned fields, with nothing about auth requirements, ID validity/not-found behavior, or any operational constraint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose sentence is front-loaded but is followed by a very long dump of return keys, nested sub-keys and even a docs version tag ('7.3.70 docs'). Since an output schema exists, this enumeration is largely wasted text and bloats the definition well past what is needed to select and call the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with an output schema supplied, the essentials (what it returns, which ID to pass) are covered. The bulk of the description is redundant with structured data rather than filling real gaps like error or not-found behavior, so it is adequate but not complete in the places that would actually help.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single 'id' parameter, which already states it is the 'Alarm hub ID'. The description's 'by ID' adds no format, source, or lookup guidance (such as where to obtain the ID) beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb and resource ('Get full details for a specific alarm hub by ID'), which is unambiguous and clearly distinct from the list-style siblings like protect_list_alarm_hubs. It stops short of naming that sibling explicitly, so an agent must infer the retrieval-vs-enumeration split from the name pattern.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the caller is expected to already hold a hub ID. There is no explicit guidance on when to reach for this tool versus protect_list_alarm_hubs (e.g. 'use the list tool to discover IDs'), and no prerequisites or failure conditions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_bridgeGet bridgeA
Read-only

Get full details for a specific bridge by ID. Returns: id, modelKey, name, mac, state, type, guid, platform, clients (array of MACs), maxClients (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesBridge ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
clientsNoConnected client MACs (array of strings)
modelKeyNoResource kind
platformNoHardware platform, e.g. "mt7621"
maxClientsNoMax client capacity (number)

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a safe, read-only, closed-world read. The description adds little behavioral context beyond enumerating return fields, and since an output schema exists that enumeration is largely redundant. No mention of auth needs, error behavior, or lookup failure semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two front-loaded sentences; the retrieval purpose leads and the field list follows. Slightly wasteful because the return-field enumeration duplicates what the output schema already provides, but overall tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A simple one-param getter with a full output schema and covering read-only annotations needs little more than a clear purpose statement. The description is complete for correct invocation, though it adds no scoping constraints or error guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage and a single required 'id' parameter documented in the schema, the description's 'by ID' adds nothing beyond structured data. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (get) and resource (bridge) with a qualifying scope ('specific bridge by ID'), which implicitly distinguishes it from the sibling protect_list_bridges. It does not name the list alternative explicitly, so it falls just short of the top bar.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied via 'by ID' - the agent can infer this is the single-item counterpart to protect_list_bridges. There is no explicit when-to-use, when-not-to-use, or named alternative, so guidance is adequate but inferential.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_cameraGet cameraA
Read-only

Get details for a specific camera by ID. The Protect Integration API returns the SAME field set as protect_list_cameras entries (id, mac, name, modelKey, state, type, guid, activePatrolSlot, hasPackageCamera, hdrType, isMicEnabled, micVolume, videoMode, featureFlags, lcdMessage, ledSettings, osdSettings, smartDetectSettings) — there is no extended/by-id-only payload (confirmed live on 7.3.70). Recording state, motion events, zones, and channel/RTSP config are NOT exposed by this API surface.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesCamera ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoCamera ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoCamera name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
hdrTypeNoHDR mode, e.g. "auto"
modelKeyNoAlways "camera"
micVolumeNoMicrophone volume 0-100 (number)
videoModeNoVideo mode, e.g. "default"
lcdMessageNo
ledSettingsNo
osdSettingsNo
featureFlagsNo
isMicEnabledNoMicrophone enabled (boolean)
activePatrolSlotNoActive PTZ patrol slot, or null (number|null)
hasPackageCameraNoHas a secondary package camera (boolean)
smartDetectSettingsNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only, non-destructive, closed-world profile, so the bar is lower, and the description still adds real value by enumerating the returned field set and explicitly naming what is NOT exposed (recording state, motion events, zones, channel/RTSP config). That negative-space disclosure prevents wasted calls, though error/timeout behavior is unaddressed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then two sentences that each carry non-obvious information (identical field set, excluded data). The field enumeration is long but functional; the version parenthetical is defensible evidence but slightly incidental.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values need no prose, yet the description still summarizes the payload and its limits. For a single-ID lookup with full annotation coverage, nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is only one parameter and schema description coverage is 100% ('Camera ID' with a pattern constraint), so the schema already does the heavy lifting. The description adds no format or lookup guidance beyond saying 'by ID'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get details for a specific camera by ID') and explicitly differentiates itself from the sibling protect_list_cameras by asserting the by-ID payload is identical to the list entry payload. An agent can tell exactly what this returns without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The note that there is 'no extended/by-id-only payload' implicitly tells the agent this call is not needed for richer data, but it never states when to prefer this over protect_list_cameras or what an invalid/missing ID yields. Usage is implied rather than routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_chimeGet chimeA
Read-only

Get full details for a specific chime by ID. Returns: id, modelKey, name, mac, state, type, guid, cameraIds (array of camera IDs), ringSettings (array of objects: cameraId, volume, ringtoneId, repeatTimes) — verified live 7.3.70.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesChime ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
modelKeyNoResource kind
cameraIdsNoPaired camera IDs (array of strings)
ringSettingsNoPer-camera ring config (array of objects: cameraId, volume, ringtoneId, repeatTimes)

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered without the description. The description contributes the field inventory and a version-verification note, which is beyond the annotations, but it says nothing about error behavior for unknown IDs or pagination (none expected).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose in the first clause, then the return fields. The long field enumeration is somewhat bloated given an output schema exists, but nothing is misleading or wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is sufficient for a single-parameter read tool whose annotations carry the safety profile and whose output schema carries the return shape. The return-field list duplicates the output schema rather than filling a gap, but no information an agent needs to invoke it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one parameter and 100% schema description coverage, the schema already documents the 'id' field and its pattern. The description adds no syntax, format, or sourcing guidance beyond restating that lookup is by ID, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get full details for a specific chime by ID'), which cleanly separates it from the list-style siblings like protect_list_chimes. It does not name a sibling explicitly, but 'by ID' makes the selection unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the phrase 'by ID' signals that a chime identifier is required, which an agent must obtain from protect_list_chimes first. No explicit when-to-use, prerequisite, or when-not guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_fobGet fobB
Read-only

Get full details for a specific fob by ID. Returns: id, modelKey, name, mac, state, type, guid, awayState, buttonLabels, featureFlags (buttons[], hasKeypad), armControlSettings (enabled, armProfileId, nightProfileId), keypadSettings (beepEnabled, beepVolume), wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesFob ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
modelKeyNoResource kind
awayStateNoAway state, e.g. "ONLINE"
buttonLabelsNoButton label preset, e.g. "securityActions"
featureFlagsNoFeature flags (object: buttons[], hasKeypad — hasKeypad added in 7.3.x)
keypadSettingsNoKeypad config, added in 7.3.x (object: beepEnabled, beepVolume). The backlightEnabled/backlightBrightness fields were dropped in 7.3.70.
armControlSettingsNoArm-control config, added in 7.3.x (object: enabled, armProfileId, nightProfileId)
wirelessConnectionStateNoWireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds no behavioral context beyond that — no auth requirements, no behavior on an invalid/unknown ID, no note on whether the response is cached or live — and its one added element, the return-field list, is redundant with the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose sentence is front-loaded and efficient, but the second sentence is a sprawling nested enumeration of return fields that duplicates the output schema and roughly doubles the length without adding selection value. The trailing '(7.3.70 docs)' citation is noise for an invoking agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With read-only annotations, a fully documented single required parameter, and an existing output schema, the description covers what an agent needs to invoke the tool correctly. The main residual gap is the absence of any routing hint to protect_list_fobs for obtaining a valid ID.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter with 100% schema description coverage ('Fob ID' plus a format pattern), so the schema fully documents it. The description adds no syntax, source, or format guidance for the id, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get full details for a specific fob by ID'), which is unambiguous and implies the get-vs-list distinction against protect_list_fobs. However, it never names the sibling or explicitly contrasts single-fetch with enumeration, so an agent must infer the relationship from naming convention alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the 'by ID' phrasing suggests calling this when you already hold a fob ID and need its full record. There is no explicit when-to-use, when-not-to-use, or pointer to protect_list_fobs for discovering IDs, which is the natural precondition for this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_infoGet infoA
Read-only

Get UniFi Protect application information. Returns: applicationVersion (string).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
applicationVersionNoCurrent Protect application version

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds only the return payload (applicationVersion), which is redundant with the existing output schema, so it contributes little beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with no filler; the purpose leads and the return value follows. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with full annotation coverage and an output schema, almost nothing is missing. The only gap is the absence of a note on when the info is useful (e.g., version/compatibility checks), which would help an agent decide to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. The description correctly implies a no-argument invocation and adds nothing that could mislead about inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Get UniFi Protect application information") and scopes it to the application itself rather than a device. It is implicitly distinct from the many list_*/get_* device siblings, but never explicitly says "application-level, not a device" to differentiate it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the tool is the sole application-info tool among device-centric siblings, so an agent can infer it is for app metadata. There is no explicit when-to-use, when-not-to-use, or named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_lightGet lightB
Read-only

Get full details for a specific light by ID. Returns: id, modelKey, name, mac, state, type, guid, lightModeSettings (mode, enableAt), lightDeviceSettings (isIndicatorEnabled, pirDuration, pirSensitivity, ledLevel), isDark, isLightOn, isLightForceEnabled, lastMotion, isPirMotionDetected, camera (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesLight ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
cameraNoPaired camera ID
isDarkNoWhether it is currently dark out (boolean)
modelKeyNoResource kind
isLightOnNoWhether the light is currently on (boolean)
lastMotionNoLast motion timestamp in epoch ms (number)
lightModeSettingsNoActivation settings (object: mode, enableAt)
isLightForceEnabledNoMain LED force-enabled (boolean)
isPirMotionDetectedNoPIR motion currently detected (boolean)
lightDeviceSettingsNoHardware settings (object: isIndicatorEnabled, pirDuration, pirSensitivity, ledLevel)

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered without the description. The description adds nothing behavioral beyond that (no auth scope, error behavior, or freshness semantics), and its enumerated field list largely duplicates the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is correctly front-loaded in the first clause, but the long inline enumeration of return fields and the trailing '(7.3.70 docs)' citation consume most of the text without aiding tool selection. Since an output schema already exists, that field list is redundant rather than informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only fetch with a full output schema and clear annotations, the description covers what an agent needs in order to call the tool correctly. The only missing piece is routing context against the list/get sibling pair.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'id' parameter is documented in the schema with a pattern constraint. The description restates only that lookup is 'by ID' and adds no format, uniqueness, or sourcing detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Get) and resource (light) with clear scope ('full details ... by ID'), distinguishing a single-item fetch from the sibling list tool protect_list_lights by implication. It does not explicitly name that sibling, so an agent must infer the retrieve-one vs enumerate-many split from naming convention.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus protect_list_lights or the broader family of protect_get_* tools, and no stated prerequisite such as needing an ID obtained from a list call. The 'by ID' phrasing only weakly implies the lookup flow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_liveviewGet liveviewA
Read-only

Get details for a specific live view by ID. Returns: id, modelKey, name, isDefault, isGlobal, layout, owner, slots (each slot: cameras string[], cycleMode, cycleInterval). The full slot list is needed when updating because PATCH replaces the slots array.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesLiveview ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoLiveview ID
nameNoLiveview name
ownerNoOwning user ID
slotsNoCamera slots
layoutNoGrid layout / slot count (number)
isGlobalNoWhether shared across all users (boolean)
modelKeyNoAlways "liveview"
isDefaultNoWhether this is the default liveview (boolean)

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: the PATCH-replaces-slots semantics, which affects how an agent orders calls. It omits error/not-found behavior for an invalid ID.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then the return shape, then the PATCH caveat in three tight sentences. The enumerated return fields are somewhat redundant given the tool has an output schema, costing a little efficiency.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, single-parameter tool with an output schema, the description covers the essentials and adds the one non-obvious workflow detail (slots must be fully supplied on PATCH because it replaces the array). No pagination or failure-mode notes, but nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single required parameter with 100% schema description coverage and a documented pattern, so the schema carries the parameter meaning. The description's 'by ID' adds nothing beyond it, which is the expected baseline 3 when schema coverage is complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get details for a specific live view by ID'), which is enough to separate it from the sibling list tool protect_list_liveviews, since 'by ID' implies single-item retrieval. It never names that sibling explicitly, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete usage condition: fetch the full slot list when updating because PATCH replaces the slots array, which tells the agent when this call is required. It does not explicitly contrast with protect_list_liveviews as the alternative for enumerating views, so there is no exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_relayGet relayB
Read-only

Get full details for a specific relay by ID. Returns: id, modelKey, name, mac, state, type, guid, ledSettings (isEnabled), outputs (array of objects: id, name, type, delay, pulseDuration, state, rebootState — id is the outputId for protect_activate_relay_output), inputs (array of objects: id, name, state, actionTrigger, actionType, actionOutputId), wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesRelay ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
inputsNoInput channels (array of objects: id, name, state, actionTrigger, actionType, actionOutputId)
outputsNoOutput channels (array of objects: id, name, type, delay, pulseDuration, state, rebootState). `id` is the outputId for protect_activate_relay_output
modelKeyNoResource kind
ledSettingsNoLED settings (object: isEnabled)
wirelessConnectionStateNoWireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/destructiveHint/openWorldHint, so the safety profile is covered. The description goes beyond that by detailing the returned structure and, notably, linking outputs[].id to protect_activate_relay_output's outputId parameter, which is genuinely useful cross-tool context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, which is good, but the bulk of the text enumerates the full return shape even though an output schema already exists, making much of it redundant. It is dense and structured but not every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only single-parameter tool with a full output schema and complete annotations, the description is more than sufficient and even adds the cross-tool outputId link. Only minor edges (e.g., not-found behavior) are absent, which is acceptable here.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single 'id' parameter, so the schema already documents it fully. The description's 'by ID' adds no format, source, or semantics beyond what the schema provides, warranting the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Get full details for a specific relay by ID'), which an agent can distinguish from the list-style sibling protect_list_relays. However, it never explicitly names or contrasts with that sibling, so differentiation is implicit rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, no prerequisites, and no exclusions or references to alternatives like protect_list_relays or protect_get_info. 'By ID' only weakly implies that an ID must already be known.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_rtsp_streamsGet RTSP streamsA
Read-only

Get active RTSPS stream sessions for a camera. Returns: high, medium, low, package — each an rtsps:// URL, or null (or absent) when no session is active at that quality. Use protect_create_rtsp_stream to start one. Each URL is a bearer credential for live video: do not repeat it unless the user asked for it.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesCamera ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
lowNoRTSPS URL for the low-quality stream
highNoRTSPS URL for the high-quality stream
mediumNoRTSPS URL for the medium-quality stream
packageNoRTSPS URL for the package-camera stream

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety is covered; the description adds real value on top by disclosing the return shape (high/medium/low/package, null-or-absent when inactive) and warning that each URL is a bearer credential for live video that should not be repeated unprompted. That security caveat is behavior an annotation cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: what it does, what it returns, what to do instead, plus the credential caution. Everything is front-loaded and each sentence adds non-redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still explains the quality keys and null-when-inactive semantics, and it covers the sibling hand-off and the security constraint. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is a single 'Camera ID' parameter, so the schema carries the burden; the description only implies the id refers to a camera without adding format or constraint detail. Baseline 3 is appropriate for a one-parameter tool fully documented in schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get active RTSPS stream sessions for a camera') and scopes it precisely to the RTSP-stream concept. The sibling tools are all list/get entity tools, so a stream-session getter is clearly distinct, and the reference to protect_create_rtsp_stream further anchors it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to protect_create_rtsp_stream when it needs to start a session, which is genuine when-to-use guidance. It stops short of stating when not to call this tool (e.g. non-camera devices or no-session cases), so it is clear context rather than full routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_sensorGet sensorC
Read-only

Get full details for a specific sensor by ID. Returns: id, modelKey, name, mac, state, type, guid, mountType, featureFlags (temperature, humidity, light, motion, waterLeak, open, tamper, smoke — each {channelCount}), batteryStatus (percentage, isLow), stats (light, humidity, temperature — each {value, status}), lightSettings / humiditySettings / temperatureSettings (isEnabled, margin, lowThreshold, highThreshold), isOpened, openStatusChangedAt, isMotionDetected, motionDetectedAt, motionSettings / glassBreakSettings (isEnabled, sensitivity, sensitivityWhenArmed), scheduleMode, armProfileIds, hasCustomSensitivityWhenArmed, alarmTriggeredAt, alarmSettings, leakDetectedAt, externalLeakDetectedAt, leakSettings (isInternalEnabled, isExternalEnabled), tamperingDetectedAt, wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesSensor ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
statsNoEnvironmental stats (object: light, humidity, temperature — each { value, status })
isOpenedNoOpen/close contact state (boolean)
modelKeyNoResource kind
mountTypeNoMount type, e.g. "door", "leak", "garage"
featureFlagsNoSensor capability flags, added in 7.3.x (object: temperature, humidity, light, motion, waterLeak, open, tamper, smoke — each { channelCount })
leakSettingsNoLeak detection settings, read-only (object: isInternalEnabled, isExternalEnabled)
scheduleModeNoSchedule mode: "always" | "when_armed"
alarmSettingsNoAlarm settings (object: isEnabled)
armProfileIdsNoArm profile IDs this sensor belongs to (array of strings)
batteryStatusNoBattery status (object: percentage, isLow)
lightSettingsNoLight threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)
leakDetectedAtNoLast leak timestamp in epoch ms (number)
motionSettingsNoMotion detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)
alarmTriggeredAtNoLast alarm timestamp in epoch ms (number)
humiditySettingsNoHumidity threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)
isMotionDetectedNoMotion currently detected (boolean)
motionDetectedAtNoLast motion timestamp in epoch ms (number)
glassBreakSettingsNoGlass-break detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)
openStatusChangedAtNoOpen-status change timestamp in epoch ms (number)
tamperingDetectedAtNoLast tampering timestamp in epoch ms (number)
temperatureSettingsNoTemperature threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)
externalLeakDetectedAtNoLast external-leak timestamp in epoch ms (number)
wirelessConnectionStateNoWireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)
hasCustomSensitivityWhenArmedNoCustom armed sensitivity enabled (boolean)

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds no behavioral context beyond that — no auth requirements, no rate limits, no error or not-found semantics — and instead spends its budget restating return fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence is a well-formed, front-loaded purpose statement, but everything after it is a sprawling enumeration of return fields. Since an output schema exists, that enumeration is largely redundant and dominates the description's length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with a full output schema and safety annotations, the core need is covered by the first sentence. The remaining text re-describes the return payload the output schema already defines, so the description is verbose in the wrong place and silent on genuinely useful details like not-found behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage and a single parameter fully documented as 'Sensor ID' with a pattern, the schema carries the meaning and the baseline is 3. The phrase 'by ID' adds nothing about format or sourcing of the ID beyond what the schema already specifies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb (Get), resource (sensor), and scope (by ID, full details), which distinguishes it from the sibling protect_list_sensors in practice. It never names the sibling or any alternative explicitly, but the get-vs-list distinction is implicit in 'by ID'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus protect_list_sensors or the other protect_get_* siblings, no prerequisite for obtaining a valid sensor ID, and no error behavior for unknown IDs. The description only says what it returns, not when to reach for it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_sirenGet sirenA
Read-only

Get full details for a specific siren by ID. Returns: id, modelKey, name, mac, state, type, guid, volume, ledSettings (isEnabled), sirenStatus (isActive, activatedAt, duration), connectionType, wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesSiren ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
volumeNoSiren volume (number)
modelKeyNoResource kind
ledSettingsNoLED settings (object: isEnabled)
sirenStatusNoCurrent siren status (object: isActive, activatedAt, duration)
connectionTypeNoConnection type, e.g. "lora"
wirelessConnectionStateNoWireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered structurally. The description adds no behavioral context beyond that (no auth requirements, error behavior, or freshness guarantees), leaning instead on enumerating return fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence. The trailing return-field enumeration is long and largely duplicates the existing output schema, but it is compactly expressed and does not obscure the core statement.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with a full output schema and rich annotations, the description covers the essentials. Since an output schema exists, the enumerated return fields are redundant rather than necessary, and the missing piece is routing guidance against sibling getters/lists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter with 100% schema description coverage ('Siren ID', with pattern constraint), so the schema carries the semantics. The description adds nothing about format or constraints beyond restating 'by ID', which is the expected baseline here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get full details for a specific siren by ID'), which cleanly separates it from the list-style sibling protect_list_sirens. It stops short of naming the sibling or scope limits explicitly, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'by ID' implies you already have an identifier, which is the only real usage signal. There is no explicit when-to-use guidance and no mention of alternatives such as protect_list_sirens for discovering IDs, so context is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_snapshotGet snapshotA
Read-only

Get a JPEG snapshot from a camera. Returns a base64-encoded image/jpeg (rendered directly by MCP clients). Use highQuality=true to force a 1080p-or-higher capture; set channel=package to capture from the secondary package camera on doorbells with hasPackageCamera=true. Fails with HTTP 503 when the camera is offline or unreachable. A snapshot too large for one MCP message is refused with an error; try without highQuality.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesCamera ID
channelNoCamera channel to capture. Use "package" for cameras with hasPackageCamera=true (defaults to main)
highQualityNoIf true, force a 1080p-or-higher resolution snapshot

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly/destructive/openWorld; the description goes further by disclosing failure modes (HTTP 503 when the camera is offline or unreachable), an oversize-image refusal, and a concrete remediation ('try without highQuality'). It also notes clients render the image directly, so the agent knows what to expect from a read with no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, all front-loaded: what it returns first, then parameter modifiers, then failure modes and recovery. Every sentence carries operational information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the return contract (base64 JPEG rendered by clients) and covers the error paths an agent must handle. For a read-only snapshot tool with 3 well-documented params, nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter is already documented, so the baseline is 3; the description still adds value by tying highQuality to the 1080p-or-higher guarantee and to the size-refusal behavior, and by restating the package-camera prerequisite. The overlap with the schema keeps it from a full 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get a JPEG snapshot from a camera') plus the concrete return payload ('base64-encoded image/jpeg'). This clearly separates it from siblings like protect_get_rtsp_streams (live stream) and protect_get_camera (metadata) without opening their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear conditions for the optional parameters (highQuality for 1080p+, channel=package only for cameras with hasPackageCamera=true) and a fallback path when the response is too large. It does not, however, state when to prefer a snapshot over alternatives such as the RTSP stream tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_speakerGet speakerC
Read-only

Get full details for a specific speaker by ID. Returns: id, modelKey, name, mac, state, type, guid, volume, micVolume, isMicEnabled, speakerState (status, mode), featureFlags (hasMic) (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesSpeaker ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
volumeNoSpeaker volume (number)
modelKeyNoResource kind
micVolumeNoMicrophone volume (number)
featureFlagsNoFeature flags (object: hasMic)
isMicEnabledNoMicrophone enabled (boolean)
speakerStateNoSpeaker state (object: status, mode)

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=false, and destructiveHint=false. The description only lists return fields, which are already covered by the output schema, and adds no behavioral context such as auth needs, rate limits, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence is front-loaded and efficient. The second sentence enumerates many return fields that are redundant with the existing output schema, adding length without new value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple getter with an output schema and safety annotations, the description covers the operation, the required ID, and the returned fields. It lacks usage routing to sibling tools, but that is a minor gap for an obvious single-item retrieval.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents the sole 'id' parameter as 'Speaker ID'. The description's 'by ID' adds no syntax or format detail beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get full details for a specific speaker by ID'), making the operation clear. It does not differentiate from sibling tools like protect_list_speakers, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides no explicit when-to-use, prerequisites, or alternative tools. 'By ID' is a parameter constraint, not guidance on choosing this tool over protect_list_speakers or other getters.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_ulp_userGet ULP userA
Read-only

Get details for a specific UniFi Identity (ULP) user by ID. Returns: id, modelKey, firstName, lastName, fullName, email, status.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesULP user ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoULP user UUID
emailNoEmail address, added in 7.3.x. Empty string for service accounts (verified live 7.3.70)
statusNoAccount status, e.g. ACTIVE
fullNameNoFull name
lastNameNoLast name
modelKeyNoAlways "ulpUser"
firstNameNoFirst name

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety is covered. The description contributes the returned field list, but says nothing about auth requirements, error behavior for an unknown ID, or pagination concerns — acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, zero filler, with the identity/scope qualifier front-loaded before the return-value enumeration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with full schema coverage, safety annotations, and an output schema, nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single 'id' parameter carries its pattern and description in the schema, so the description's 'by ID' adds no syntax or format detail. Baseline 3 for a fully documented single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Get) and resource (UniFi Identity/ULP user), qualified by ID lookup, which cleanly separates it from protect_list_ulp_users and from the similarly named protect_get_user. An agent can pick this tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by 'by ID' — you call it when you already hold a ULP user ID — but the description never states when to prefer this over protect_list_ulp_users or protect_get_user, nor any prerequisites. Adequate but with an obvious routing gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_userGet userA
Read-only

Get details for a specific Protect user by ID. Returns the same fields as protect_list_users entries: id, modelKey, name, firstName, lastName, email, ucoreUserId.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesUser ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoUser ID
nameNoDisplay name
emailNoEmail address
lastNameNoLast name
modelKeyNoAlways "user"
firstNameNoFirst name
ucoreUserIdNoUniFi Core user UUID

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds only the returned field list, which is largely duplicated by the output schema, and omits error or permission behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, purpose first and return fields second, with no wasted words. The field list is somewhat redundant with the output schema but remains short and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Simple read-by-ID tool with full annotation coverage and an existing output schema, so the description is nearly complete for calling it correctly. The only gap is no explicit disambiguation from protect_get_ulp_user, but the core invocation needs nothing more.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with 'User ID' and a pattern constraint; the description adds only 'by ID', which restates the schema. Baseline 3 is appropriate because the schema fully documents the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Get details), resource (Protect user), and selector (by ID), plus the returned field shape. It does not explicitly differentiate from sibling protect_get_ulp_user, another user-fetching tool, so sibling discrimination is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage when you have a user ID and need details for that single user, and notes field parity with protect_list_users entries. However, it never states when to prefer this over protect_list_users or protect_get_ulp_user, so guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_get_viewerGet viewerA
Read-only

Get full details for a specific viewer by ID. Returns: id, modelKey, name, mac, state, type, guid, liveview, streamLimit (7.3.70 docs).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesViewer ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoDevice ID
macNoMAC address
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoDevice name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
stateNoCONNECTED | DISCONNECTED | ...
liveviewNoAssigned live view ID, or null
modelKeyNoResource kind
streamLimitNoMax concurrent streams (number)

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds no behavioral context beyond that (no auth requirements, no error behavior for an unknown ID); its field list is return-shape information, not behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the purpose and free of filler. The enumerated return fields are slightly wasteful given an output schema exists, but the whole description is brief enough that it doesn't harm readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-by-ID tool with full annotation coverage and an output schema, the description covers what an agent needs to select and invoke it. Nothing essential is missing, though it could note the read-only nature or behavior on an invalid ID.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With a single parameter at 100% schema description coverage ("Viewer ID" plus a pattern constraint), the schema already carries the semantics. The description's "by ID" adds nothing beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Get full details for a specific viewer by ID"), which cleanly separates it from the sibling protect_list_viewers. It does not name the sibling explicitly, but "by ID" versus listing makes the distinction inferable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is the follow-up call after obtaining an ID from protect_list_viewers. There is no explicit when-to-use, when-not-to-use, or named alternative, so it lands at minimum viable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_alarm_hubsList alarm hubsA
Read-only

List all alarm hubs managed by UniFi Protect. Returns array; each alarm hub includes: id, modelKey ("linkstation"), name, mac, state, type, guid, isAlarmHub, ledSettings (isEnabled), lastEvent, alarmHub (armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. "tampered"), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus), threadState (network: status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds genuinely useful behavioral context beyond that: it returns an array, and paged results also carry totalCount and offset. It stops short of describing ordering or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening clause is well front-loaded, but the middle is a sprawling enumeration of every nested field (ledSettings, alarmHub with a dozen sub-keys, threadState, etc.) that largely duplicates the existing output schema. This bulk crowds out the one actionably useful sentence, the pagination guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because an output schema exists, return values need not be restated, and annotations cover safety; the pagination behavior is the piece that genuinely mattered and it is included. Nothing an agent needs to call this correctly is missing, though a pointer to the sibling get tool would round it out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline would be 3, but the description goes beyond the terse schema strings by explaining the paging rationale (large sites) and the side effect of a paged call (totalCount and offset in the response). That gives the two parameters purpose the schema alone does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('alarm hubs managed by UniFi Protect'), and the plural/singular pairing with the sibling protect_get_alarm_hub is immediately clear. An agent can distinguish it from the get-by-id sibling without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives pagination guidance ('On a large site, use limit and offset to page') but never states when to use this tool versus protect_get_alarm_hub or why a listing is preferable to a lookup. Usage is implied by the list-vs-get naming convention rather than made explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_arm_profilesList arm profilesA
Read-only

List all arm profiles (only available when using the local alarm manager — the standalone NVR alarm system, not Protect cloud alerts). Returns array; each profile (7.3.70 docs): id, name, automations[], creator, schedules[], recordEverything, activationDelay (0 | 60000 | 300000 | 600000), createdAt, updatedAt. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, non-destructive, closed-world), so the bar is lower; the description still adds real context about the returned array shape, the effect of paging (totalCount and offset appear), and the discrete activationDelay values. It omits permission/auth requirements and default page size, which keeps it out of the top band.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense paragraph, front-loaded with purpose and scope, then return shape, then paging guidance — a sensible order with no filler sentences. Slightly overstuffed for a two-parameter list tool, and the '(7.3.70 docs)' citation is incidental metadata that does not help invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, availability constraint, return fields, and paging behavior; an output schema exists so return values need not be spelled out (though it does so usefully). The remaining gap is default behavior when no limit is supplied — an agent cannot tell whether the call returns everything or is capped.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so limit/offset are already documented, giving a baseline of 3. The description adds operational meaning beyond the schema by explaining that these are the paging knobs to use on a large site and that using them changes the response shape (adds totalCount/offset).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List all arm profiles') and immediately disambiguates the scope: local alarm manager / standalone NVR, explicitly not Protect cloud alerts. An agent can tell what this returns and which system it applies to without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-not condition (only available with the local alarm manager, not cloud alerts) and directs the agent to use limit/offset for paging on large sites. It does not name an alternative tool, but with no sibling arm-profile tools there is no meaningful alternative to route to.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_bridgesList bridgesA
Read-only

List all bridges managed by UniFi Protect. Returns array; each bridge includes: id, modelKey, name, mac, state, type, guid, platform, clients (array of MACs), maxClients (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description still adds real behavioral context beyond that: the return is an array, and a paged result additionally carries totalCount and offset. It does not cover rate limits or auth requirements, but for a read-only list tool this is solid.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, followed by return shape and then paging advice, so the structure is sound. The full enumeration of every returned field is somewhat long given that an output schema exists and already carries that information, which is the only real inefficiency.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only collection tool, the description, annotations, complete parameter schema and existing output schema together leave no critical gap: the agent knows what it lists, that it is safe, and how to page. Listing return fields is redundant with the output schema rather than filling a hole, so it does not reach a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both limit and offset are already fully documented in the schema. The description adds a modest amount of meaning by explaining when paging is warranted ('on a large site') and what a paged result includes, but this is incremental rather than compensating for a gap, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('List all bridges managed by UniFi Protect'), and the word 'all' signals the unfiltered, collection-level scope that separates it from the sibling protect_get_bridge. It does not explicitly name that sibling, so it falls just short of the top score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives conditional guidance for the parameters ('On a large site, use limit and offset to page'), which is useful, but says nothing about when to prefer this tool over protect_get_bridge or the subscription tools, and offers no exclusions or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_camerasList camerasA
Read-only

List all cameras managed by UniFi Protect. Returns array; each camera includes (Integration API 7.3.70-verified fields): id, mac, name, modelKey, state (CONNECTED/DISCONNECTED), type (hardware model name, e.g. UVC G6 Turret), guid (hardware MODEL GUID — every camera of the same model returns the same value, so it is NOT a per-camera identifier; use id), activePatrolSlot, hasPackageCamera, hdrType, isMicEnabled, micVolume, videoMode, featureFlags (hasHdr, hasMic, hasSpeaker, hasLedStatus, smartDetectTypes[], smartDetectAudioTypes[], videoModes[], supportFullHdSnapshot), lcdMessage (type, resetAt, text), ledSettings (isEnabled, floodLed, welcomeLed), osdSettings (isNameEnabled, isDateEnabled, isLogoEnabled, isDebugEnabled, overlayLocation), smartDetectSettings (objectTypes[], audioTypes[]). The Integration API does NOT expose recording state, motion timestamps, connection/last-seen, firmware, host, or per-channel stream config. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the read-only safety profile; the description adds substantial non-obvious behavior — the API version the fields were verified against, a full field inventory, explicit omissions, and the fact that a paged result additionally returns totalCount and offset. It also warns that guid is a shared model identifier, not a per-camera id, which is exactly the kind of trap an agent would otherwise fall into.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, but the bulk of the text is a long enumeration of every returned field, which duplicates the declared output schema and is not needed for tool selection. The genuinely useful bits (pagination, exclusions, the guid caveat) are buried inside that enumeration rather than given precedence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the field list is over-delivery rather than a necessity; the description still covers what an agent needs to call this correctly — scope, paging, and known data limitations. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both limit and offset, so the baseline is 3. The description adds value by explaining the paging contract — that using limit/offset on a large site yields totalCount and offset in the response — which tells the agent how the parameters behave in combination, not just individually.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'List all cameras managed by UniFi Protect' — and reinforces list semantics by noting it returns an array and supports paging. It never names the sibling it must be distinguished from (protect_get_camera), so an agent must infer the list-vs-single distinction from the wording alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete usage context: 'On a large site, use limit and offset to page.' It also functions as negative guidance by enumerating data the Integration API does NOT expose (recording state, motion timestamps, firmware, host), steering the agent away from wasted calls. It stops short of explicitly routing between this tool and protect_get_camera.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_chimesList chimesA
Read-only

List all chimes managed by UniFi Protect. Returns array; each chime includes: id, modelKey, name, mac, state, type, guid, cameraIds (array of camera IDs), ringSettings (array of objects: cameraId, volume, ringtoneId, repeatTimes) — verified live 7.3.70. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral context beyond that: it states the response is an array, enumerates chime fields, and explains pagination behavior including totalCount and offset on paged results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and then supplies return details followed by pagination guidance. The explicit field enumeration is somewhat redundant given the output schema exists, but the text is dense and every sentence is informative rather than repetitive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter list tool with annotations and an output schema, the description is fully sufficient. It states the scope, return structure, and pagination behavior, so an agent has everything needed to call and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both limit and offset are already documented in the input schema. The description adds meaning by explaining the use case for paging on a large site and noting that paged results return totalCount and offset, which goes beyond the raw schema bounds.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'List all chimes managed by UniFi Protect.' It clearly distinguishes this bulk-listing tool from the sibling protect_get_chime single-resource tool through 'all' and 'List'. No ambiguity about what the tool returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides pagination guidance for large sites, which implies when to use limit and offset, but it does not explicitly say when to use this tool versus protect_get_chime or any other sibling. Usage is inferable from 'List all chimes' rather than directly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_filesList filesA
Read-only

List device asset files (only 'animations' is supported — clips uploadable to G4 Doorbell screens). Returns array; each record (verified live 7.3.70): id, name (server-generated), type, originalName, path, size, createdAt, updatedAt, metadata. An image upload (verified for GIF) later gains a derived .gif preview record, created asynchronously, so a listing taken right after the upload may show only the stored image. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)
fileTypeYesAsset file type (only 'animations' is supported)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, non-destructive, closed-world), yet the description adds real behavioral context: the asynchronous creation of a derived '<name>.gif' preview record, and the warning that a listing taken right after an upload may show only the stored image. The field enumeration ('verified live 7.3.70') is largely redundant given an output schema exists, which keeps this from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with scope and constraint, then the async caveat, then paging guidance — a sensible ordering. It is dense but each clause carries information, except the enumerated record fields, which duplicate the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with an output schema and full parameter coverage, the description supplies exactly the missing context: the single supported file type, the async derived-preview caveat, and how to paginate a large site. Nothing needed to invoke it correctly appears to be absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description nevertheless adds meaning beyond the schema: that limit/offset are the paging mechanism and that a paged result additionally returns totalCount and offset, which is behavior the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List device asset files') and immediately narrows the scope to a single supported type ('only animations is supported — clips uploadable to G4 Doorbell screens'). Sibling list tools all target different resources (cameras, lights, chimes), so naming this resource is sufficient to tell it apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives conditional guidance on paging ('On a large site, use limit and offset to page'), which is useful and actionable. However it never states when to call this tool versus other listings or what the required fileType effectively forces, so usage remains implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_fobsList fobsA
Read-only

List all fobs managed by UniFi Protect. Returns array; each fob includes: id, modelKey, name, mac, state, type, guid, awayState, buttonLabels, featureFlags (buttons[], hasKeypad), armControlSettings (enabled, armProfileId, nightProfileId), keypadSettings (beepEnabled, beepVolume), wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds behavioral context: it lists the returned fob fields in detail and explains that paged results also return totalCount and offset. This extra information goes beyond the annotations and helps an agent understand the response shape and pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the tool's purpose, followed by return field details and a pagination note. It is somewhat lengthy due to the field enumeration, but every part serves to inform the agent. No rambling or redundant sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema and safety annotations, the description is largely complete. It covers purpose, return shape, and pagination. It lacks explicit alternative-tool guidance, but for a simple list operation with structured output, this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful context for limit and offset by explaining they are used to page on large sites and that a paged result returns totalCount and offset. This clarifies the intended use beyond the schema's generic parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'List all fobs managed by UniFi Protect.' This clearly distinguishes it from the singular sibling protect_get_fob by implying a collection, but it does not explicitly name alternatives. An agent can infer the purpose without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers pagination guidance ('On a large site, use limit and offset to page'), which is useful for parameter usage, but it gives no guidance on when to choose this tool over alternatives like protect_get_fob or other list tools. No selection criteria or exclusions are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_lightsList lightsB
Read-only

List all lights managed by UniFi Protect. Returns array; each light includes: id, modelKey, name, mac, state, type, guid, lightModeSettings (mode, enableAt), lightDeviceSettings (isIndicatorEnabled, pirDuration, pirSensitivity, ledLevel), isDark, isLightOn, isLightForceEnabled, lastMotion, isPirMotionDetected, camera (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered without the description. The description does add one genuinely behavioral detail — that a paged result also returns totalCount and offset — but the long field enumeration duplicates the existing output schema rather than adding traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is correctly front-loaded in the first sentence, but the following field-by-field enumeration is a long, low-value block that largely restates what the output schema already provides. The paging note at the end is the only additional sentence that earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering safety and an output schema covering return shape, the description only needs to add operational context — which it does via the paging/totalCount note. Nothing essential for calling the tool correctly is missing, though the list-vs-get routing is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters and their bounds are already documented, making the baseline 3. The description's note that limit/offset are for paging on large sites reinforces intent but adds no syntax or constraint detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope ('List all lights managed by UniFi Protect'), which is unambiguous against the parallel protect_get_light tool. It does not explicitly name or contrast a sibling, so it falls just short of the top mark.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only usage guidance is conditional paging advice ('On a large site, use limit and offset to page'), which is really parameter behavior rather than a when-to-use rule. It never states when to prefer this over protect_get_light, leaving the list-vs-single distinction to be inferred from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_liveviewsList liveviewsA
Read-only

List all live views (camera grid layouts shown on viewers / in the Protect UI). Returns array; each liveview includes (Integration API 7.3.70-verified): id, modelKey, name, isDefault, isGlobal, layout (number, slot count), owner (user ID), slots (array of {cameras: string[], cycleMode, cycleInterval}). NOTE: slots use a cameras string-array, not a single cameraId. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds behavior the annotations do not: the array return shape, the paging behavior on large sites, and the explicit gotcha that slots use a `cameras` string-array rather than a single `cameraId` — a real tripwire for callers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then richer detail, then the caveat and paging note; the ordering is sensible. It is somewhat dense, and the enumerated liveview fields partly duplicate the existing output schema, but nothing is truly wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering the safety profile, a full output schema, and 100% schema description coverage, the description supplies only the extra bits an agent actually needs: the definition of a liveview, the string-array slots gotcha, and paging/totalCount behavior. Nothing required to call or interpret the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so limit/offset are already documented in the schema, but the description adds real semantics: that paging is the mechanism on large sites and that a paged response also carries totalCount and offset. That is genuinely new information about how the parameters behave.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List all live views') and even defines what a live view is (camera grid layouts shown on viewers / in the Protect UI), which disambiguates it from unrelated Protect resources. It does not name or contrast the sibling protect_get_liveview, so the list-vs-single routing is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The paging advice ('On a large site, use limit and offset to page') is conditional usage guidance, but there is no explicit statement of when to use this tool versus protect_get_liveview or the other protect_list_* tools. Usage context is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_nvrsList NVRsA
Read-only

Get the NVR (Network Video Recorder) console info. NOTE: despite the name, the Protect Integration API's /nvrs endpoint returns a SINGLE NVR object, not an array. Returns: id, modelKey, name, type (e.g. UNVR-PRO), guid, mac, doorbellSettings (defaultMessageText, defaultMessageResetTimeoutMs, customMessages[], customImages[] (preview, sprite)), armMode (status, armProfileId, armedAt, willBeArmedAt, breachDetectedAt, breachEventCount, breachTriggerEventId, breachEventId).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoNVR ID
macNoMAC address, added in 7.3.x
guidNoHardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.
nameNoNVR name
typeNoHardware model name, e.g. "UVC G6 Turret", "UP Chime PoE", "UNVR-PRO"
armModeNo
modelKeyNoAlways "nvr"
doorbellSettingsNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only, non-destructive, closed-world safety profile, so the bar is lower. The description adds real context beyond structured fields: the single-object return behavior that contradicts the 'list' naming, which prevents a caller from misparsing the response.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose followed by the important naming caveat. The trailing field enumeration is somewhat redundant given an output schema exists, but the overall text is compact and earns most of its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with an output schema and clear annotations, the description covers everything needed to call it correctly. The return-field list duplicates the output schema rather than adding new information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the rubric the baseline is 4. There is nothing for the description to disambiguate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Get') and resource ('NVR console info'). Critically, it resolves the naming ambiguity against the sibling list/get pattern by noting that despite the 'list' name, the endpoint returns a single NVR object, so an agent knows no separate get_nvr sibling exists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied - it is the only route to NVR info and the note discourages array expectations - but there is no explicit when-to-use, when-not-to-use, or alternative-tool guidance. Adequate but with a clear gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_relaysList relaysA
Read-only

List all relays managed by UniFi Protect. Returns array; each relay includes: id, modelKey, name, mac, state, type, guid, ledSettings (isEnabled), outputs (array of objects: id, name, type, delay, pulseDuration, state, rebootState — id is the outputId for protect_activate_relay_output), inputs (array of objects: id, name, state, actionTrigger, actionType, actionOutputId), wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=false, so the safety profile is fully covered. The description adds the useful cross-reference that an output's id is the outputId for protect_activate_relay_output, but the bulk of the text enumerates return fields rather than behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, but the body is a dense run-on enumerating every nested field of the relay object. Since an output schema already exists, this field-by-field listing largely repeats structured data and hurts readability without adding proportionate value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with a full output schema, annotations, and 100% schema coverage, the description is more than adequate and even documents return structure beyond requirements. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are documented, so the baseline is 3. The description goes beyond the schema by explaining how limit/offset behave together (paging) and that a paged response includes totalCount and offset, which the schema does not state.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List all relays managed by UniFi Protect'), which cleanly separates it from the singular protect_get_relay sibling. The scope ('all relays managed by') is explicit, so an agent knows exactly what universe is returned.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete operational condition ('On a large site, use limit and offset to page') and explains what a paged result returns. It stops short of naming alternatives (protect_get_relay / protect_subscribe_devices), so it is clear context rather than full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_sensorsList sensorsA
Read-only

List all sensors managed by UniFi Protect. Returns array; each sensor includes: id, modelKey, name, mac, state, type, guid, mountType, featureFlags (temperature, humidity, light, motion, waterLeak, open, tamper, smoke — each {channelCount}), batteryStatus (percentage, isLow), stats (light, humidity, temperature — each {value, status}), lightSettings / humiditySettings / temperatureSettings (isEnabled, margin, lowThreshold, highThreshold), isOpened, openStatusChangedAt, isMotionDetected, motionDetectedAt, motionSettings / glassBreakSettings (isEnabled, sensitivity, sensitivityWhenArmed), scheduleMode, armProfileIds, hasCustomSensitivityWhenArmed, alarmTriggeredAt, alarmSettings, leakDetectedAt, externalLeakDetectedAt, leakSettings (isInternalEnabled, isExternalEnabled), tamperingDetectedAt, wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint=false, and destructiveHint=false. The description adds useful behavioral context by explaining pagination behavior and that a paged result returns totalCount and offset, though it does not cover auth or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, but the middle is an extensive enumeration of return fields that is redundant given the existing output schema. This bloats the description and violates the principle that every sentence should earn its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the annotations, the 100%-covered schema, and the existing output schema, the description supplies all necessary context: it identifies the resource, return type, and pagination mechanism. The extra field list is overcomplete but does not leave gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents limit and offset. The description mentions using them to page but adds no syntax or semantic detail beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('sensors managed by UniFi Protect'), clearly distinguishing it from siblings like protect_get_sensor and protect_list_cameras.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides pagination guidance ('On a large site, use limit and offset to page') but does not explain when to choose this tool over protect_get_sensor or other list tools. Usage is implied rather than explicitly contrasted with alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_sirensList sirensA
Read-only

List all sirens managed by UniFi Protect. Returns array; each siren includes: id, modelKey, name, mac, state, type, guid, volume, ledSettings (isEnabled), sirenStatus (isActive, activatedAt, duration), connectionType, wirelessConnectionState (signalState: signalQuality, signalStrength; batteryStatus: percentage, isLow; bridge) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety and side-effect behavior are covered. The description adds pagination behavior (totalCount/offset in paged results), which is genuinely useful, but repeats the return-field inventory that the output schema already provides instead of disclosing anything richer (e.g. whether an empty site returns []).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and paging advice are front-loaded and tight, but the long field-by-field inventory (id, modelKey, name, mac, state ... nested wirelessConnectionState sub-fields) is verbose and largely redundant with the output schema, adding bulk without adding selection value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool's real complexity is pagination, and that is fully addressed; the presence of an output schema means return values need not be enumerated. The only gap is the absence of sibling routing guidance, which the agent would otherwise have to infer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline would be 3, but the description goes further by explaining the behavioral consequence of the two parameters — that a paged result adds totalCount and offset to the response. That is meaning beyond the schema's 'return at most this many items' and 'skip this many items'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List all sirens managed by UniFi Protect'), which cleanly separates it from protect_get_siren. It does not explicitly contrast with siblings or the other protect_list_* tools, so it falls just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives one concrete usage condition — 'On a large site, use limit and offset to page' — which is real guidance, but it never states when to prefer this over protect_get_siren or the other list tools. Usage is implied rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_speakersList speakersB
Read-only

List all speakers managed by UniFi Protect. Returns array; each speaker includes: id, modelKey, name, mac, state, type, guid, volume, micVolume, isMicEnabled, speakerState (status, mode), featureFlags (hasMic) (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=false and destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral context in noting that paged results also return totalCount and offset, but the long field enumeration largely duplicates the existing output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, which is good, but the mid-sentence field dump (id, modelKey, name, mac, ...) plus the '(7.3.70 docs)' fragment is noisy and mostly redundant with the output schema. It earns its place less than the opening and closing sentences do.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the field list is redundant rather than necessary, and annotations cover the safety profile, so the description only needs to establish purpose and paging behavior — which it does. It is complete enough for a simple read-only list tool, though it omits ordering/default behavior for the paged call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit and offset are already documented in the schema; the baseline is 3. The description corroborates their paging purpose ('use limit and offset to page') but adds no defaults, ranges, or syntax beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'List all speakers managed by UniFi Protect.' The list-vs-get distinction against sibling protect_get_speaker is clear from naming, but the description never explicitly differentiates itself from that sibling or from other protect_list_* tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives one concrete usage cue ('On a large site, use limit and offset to page'), which is real guidance. However, there is no when-not guidance and no mention of the alternative protect_get_speaker for fetching a single speaker, so routing guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_ulp_usersList ULP usersA
Read-only

List UniFi Identity (ULP) users — per the API docs, those with enrolled credentials (NFC cards, fingerprints). Returns array; each ULP user includes (Integration API 7.3.70-verified): id, modelKey, firstName, lastName, fullName, email (empty string for service accounts), status (e.g. ACTIVE). Enrolled-credential detail (NFC cards, fingerprints) is NOT exposed by this API surface. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely useful behavioral context beyond that: the scope limitation that enrolled-credential detail (NFC cards, fingerprints) is NOT exposed, and that paged responses also carry totalCount and offset.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and scope definition, then return shape, then paging. Dense but every sentence carries information; the inline field enumeration and API-version parentheticals are slightly heavy but justified for a schema-verified contract.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not enumerate return fields, but it does note the empty-string email for service accounts and the enrolled-credential limitation — the two things an agent would otherwise get wrong. The only real gap is not routing the agent away from protect_list_users.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema documents both parameters fully (100% coverage), so the baseline is 3. The description earns above baseline by explaining the operational purpose of limit/offset (paging a large site) and that paging changes the response envelope to include totalCount and offset.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource and goes further by defining what a ULP user is (UniFi Identity users with enrolled credentials), which implicitly separates this list from protect_list_users. However, it never names that sibling, so an agent choosing between the two lists still has to infer the distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives one concrete usage condition — page with limit/offset on a large site — but offers no when-to-use vs alternatives guidance and does not mention protect_list_users or protect_get_ulp_user. Usage is implied by the definition rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_usersList usersA
Read-only

List all Protect users (filtered by the API key's access permissions). Returns array; each user includes (Integration API 7.3.70-verified): id, modelKey, name, firstName, lastName, email, ucoreUserId. The Integration API does NOT expose roles, permissions, login history, groups, or notification settings. On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish this as a safe read (readOnlyHint=true, destructiveHint=false, openWorldHint=false), but the description goes further by enumerating the returned fields and, more valuably, explicitly listing what the Integration API does NOT expose (roles, permissions, login history, groups, notification settings). It also discloses the paging shape (totalCount, offset returned for paged results), which prevents futile calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, followed by returned fields, exclusions, then paging advice, so a reader can stop early. Most sentences earn their place, though the parenthetical '7.3.70-verified' provenance tag is slightly noise for an agent selecting a tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return shape need not be spelled out, yet the description still summarizes returned fields and explicit exclusions, plus paging semantics. The only meaningful gap is no routing guidance against the closely named sibling protect_list_ulp_users.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both limit and offset are already fully documented, setting the baseline at 3. The description adds value by tying them to a concrete scenario ('on a large site') and explaining what paging changes in the response (totalCount, offset), which the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List all Protect users') and adds the scoping caveat that results are filtered by the API key's access permissions. However, with siblings like protect_list_ulp_users and protect_get_user in the set, it never distinguishes which user population or granularity it covers, leaving that disambiguation to the agent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives one concrete usage cue ('On a large site, use limit and offset to page'), which is real guidance, but there is no when-to-use vs when-not guidance relative to protect_list_ulp_users or protect_get_user. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_list_viewersList viewersA
Read-only

List all viewers managed by UniFi Protect. Returns array; each viewer includes: id, modelKey, name, mac, state, type, guid, liveview, streamLimit (7.3.70 docs). On a large site, use limit and offset to page; a paged result also returns totalCount and offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoReturn at most this many items
offsetNoSkip this many items first (default 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetNoPaged results only: the index of the first item returned
resultYesArray of items returned by the list endpoint
totalCountNoPaged results only: the number of items in the whole list

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint=true, destructiveHint=false, openWorldHint=false), so the bar is lower, and the description adds genuine behavioral context: paged responses also return totalCount and offset. The enumerated return fields are largely redundant with the existing output schema, which slightly dilutes the added value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then return shape, then paging advice in a logical order with no filler sentences. The long field enumeration is the one part that costs more space than it earns, since an output schema already exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return values, yet it still covers purpose and pagination behavior adequately. Nothing critical for calling a ReadOnly list endpoint is missing, though an explicit pointer to protect_get_viewer for single-item lookups would make it fully self-routing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the schema already defines limit and offset individually. The description adds meaning by framing both parameters as a coordinated paging mechanism and disclosing the paged-response fields (totalCount, offset), which the schema does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ("List all viewers managed by UniFi Protect") and scopes it as the collection-level operation, which implicitly separates it from the sibling protect_get_viewer. It never names the single-viewer alternative explicitly, so it stops short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives one concrete usage cue — "On a large site, use limit and offset to page" — which tells the agent when paging matters. However, there is no guidance on when to use this list tool rather than protect_get_viewer for an individual viewer, or on any prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_subscribe_devicesSubscribe devicesA
Read-only

Connect to the device update WebSocket and collect messages for a specified duration (1-30s). Returns {messages, duration, error?, truncated?}; stops early with truncated=true after 200 messages or 100,000 characters of JSON, whichever comes first. A connection that fails before any message arrives returns an error. Each message is an envelope {type, item} where item is a device resource carrying id and modelKey (camera, light, sensor, nvr, …). The 7.3.70 docs show type 'add' with the full device object as item; other message types and whether updates carry only changed fields are not documented — inspect the captured messages. Use to detect device state changes or newly adopted devices. Not available over Cloud Connector (api.ui.com).

ParametersJSON Schema
NameRequiredDescriptionDefault
durationNoSeconds to listen (1-30, default 5)

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoConnection error, if any
durationNoSeconds actually spent listening, to 0.1s (number); shorter than requested when the message cap or an error ends the listen early
messagesNoCaptured WebSocket messages (add/update/remove or event envelopes)
truncatedNotrue when listening stopped early at the message cap (boolean, absent otherwise)

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/destructive/openWorld annotations, the description discloses the truncation limits (200 messages or 100,000 chars), the early-stop flag, the error-on-connect-failure case, the message envelope shape, and even documentation gaps. This is unusually rich behavioral context for a streaming tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core behavior and return shape, and every sentence carries information (return contract, truncation, error mode, message envelope, doc caveat, use, availability). It is dense and long, but little of it is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter WebSocket subscription tool, the description covers the return contract, truncation, error behavior, message format, intended use, and platform availability. Even though an output schema exists, nothing an agent needs to invoke or interpret this call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is a single optional parameter. The description's '(1-30s)' merely restates the schema's minimum/maximum/default, adding no syntax or semantic detail beyond what the schema already provides. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a precise verb+resource: 'Connect to the device update WebSocket and collect messages for a specified duration', and clarifies scope with 'Use to detect device state changes or newly adopted devices'. It is clearly a streaming/subscription tool, but it never names the obvious sibling protect_subscribe_events, so the agent must infer the distinction from the word 'device'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states a concrete use case ('detect device state changes or newly adopted devices') and a hard environment exclusion ('Not available over Cloud Connector (api.ui.com)'). However, it never routes the agent away from polling alternatives such as protect_list_cameras / protect_get_camera, so no explicit alternative is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protect_subscribe_eventsSubscribe eventsA
Read-only

Connect to the Protect event WebSocket and collect messages for a specified duration (1-30s). Returns {messages, duration, error?, truncated?}; stops early with truncated=true after 200 messages or 100,000 characters of JSON, whichever comes first. A connection that fails before any message arrives returns an error. Each message is an envelope {type: 'add' | 'update', item: {id, modelKey: 'event', type (event kind, e.g. 'ring'), start, end (epoch ms), device (ID of the camera/sensor that raised it)}} (7.3.70 docs). The full set of event kinds and any further event fields are not documented — inspect the captured messages. Not available over Cloud Connector (api.ui.com).

ParametersJSON Schema
NameRequiredDescriptionDefault
durationNoSeconds to listen (1-30, default 5)

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoConnection error, if any
durationNoSeconds actually spent listening, to 0.1s (number); shorter than requested when the message cap or an error ends the listen early
messagesNoCaptured WebSocket messages (add/update/remove or event envelopes)
truncatedNotrue when listening stopped early at the message cap (boolean, absent otherwise)

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/openWorld annotations by disclosing truncation caps (200 messages or 100,000 chars), the early-stop behavior with truncated=true, the error-on-no-message failure mode, the exact return shape, and a known documentation gap for event kinds. These are behavioral traits the annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and return contract, then progressively layers truncation, error, message shape, and availability. Dense but every clause carries operational information; no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even though an output schema exists, the description fully covers boundaries, failure modes, payload structure, and deployment constraints. An agent has everything needed to invoke it correctly and interpret the result without further inspection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description repeats the 1-30s bound, but it adds real meaning by tying duration to the truncation caps — clarifying that listening may end early before duration elapses. That interplay is not derivable from the numeric bound alone, so it edges above the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: connect to the Protect event WebSocket and collect messages, with the envelope explicitly defining the payload as modelKey 'event'. The 'events' scope distinguishes it from the many list/get siblings, but it never names protect_subscribe_devices, the closest alternative, so differentiation must be inferred.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied by the WebSocket/events framing and the Cloud Connector exclusion ('Not available over Cloud Connector'), which is genuinely useful routing information. However there is no explicit 'use this instead of protect_subscribe_devices when...' guidance, so the agent must infer when this is preferred over the sibling subscription tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 38 tool updatesv2.15.0
    • Changedprotect_get_alarm_hub4 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / alarmHub / description
        Previous value: -"Alarm hub status (object: armed, battery, connector, cover, output, input, …)"New value: +"Alarm hub status (object: armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. \"tampered\", added in 7.3.x), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus)"
      • removedOutput schema / properties / deviceTamperStatus
        Removed value: -{
        -  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
    • Changedprotect_get_bridge2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_camera22 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • removedOutput schema / properties / featureFlags / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / featureFlags / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "hasHdr": {
        +        "description": "Supports HDR (boolean)"
        +      },
        +      "hasLedStatus": {
        +        "description": "Has a status LED (boolean)"
        +      },
        +      "hasMic": {
        +        "description": "Has a microphone (boolean)"
        +      },
        +      "hasSpeaker": {
        +        "description": "Has a speaker (boolean)"
        +      },
        +      "smartDetectAudioTypes": {
        +        "description": "Supported smart audio-detect types (array of strings)"
        +      },
        +      "smartDetectTypes": {
        +        "description": "Supported smart object-detect types (array of strings)"
        +      },
        +      "supportFullHdSnapshot": {
        +        "description": "Supports full-HD snapshot (boolean)"
        +      },
        +      "videoModes": {
        +        "description": "Supported video modes (array of strings)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / featureFlags / properties
        Removed value: -{
        -  "hasHdr": {
        -    "description": "Supports HDR (boolean)"
        -  },
        -  "hasLedStatus": {
        -    "description": "Has a status LED (boolean)"
        -  },
        -  "hasMic": {
        -    "description": "Has a microphone (boolean)"
        -  },
        -  "hasSpeaker": {
        -    "description": "Has a speaker (boolean)"
        -  },
        -  "smartDetectAudioTypes": {
        -    "description": "Supported smart audio-detect types (array of strings)"
        -  },
        -  "smartDetectTypes": {
        -    "description": "Supported smart object-detect types (array of strings)"
        -  },
        -  "supportFullHdSnapshot": {
        -    "description": "Supports full-HD snapshot (boolean)"
        -  },
        -  "videoModes": {
        -    "description": "Supported video modes (array of strings)"
        -  }
        -}
      • removedOutput schema / properties / featureFlags / type
        Removed value: -"object"
      • removedOutput schema / properties / lcdMessage / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / lcdMessage / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "resetAt": {
        +        "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        +      },
        +      "text": {
        +        "description": "Message text shown on the doorbell LCD",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "type": {
        +        "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\"",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / lcdMessage / properties
        Removed value: -{
        -  "resetAt": {
        -    "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        -  },
        -  "text": {
        -    "description": "Message text shown on the doorbell LCD",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  },
        -  "type": {
        -    "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\"",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / properties / lcdMessage / type
        Removed value: -"object"
      • removedOutput schema / properties / ledSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / ledSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "floodLed": {
        +        "description": "Flood LED enabled (boolean)"
        +      },
        +      "isEnabled": {
        +        "description": "Status LED enabled (boolean)"
        +      },
        +      "welcomeLed": {
        +        "description": "Welcome LED enabled (boolean)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / ledSettings / properties
        Removed value: -{
        -  "floodLed": {
        -    "description": "Flood LED enabled (boolean)"
        -  },
        -  "isEnabled": {
        -    "description": "Status LED enabled (boolean)"
        -  },
        -  "welcomeLed": {
        -    "description": "Welcome LED enabled (boolean)"
        -  }
        -}
      • removedOutput schema / properties / ledSettings / type
        Removed value: -"object"
      • removedOutput schema / properties / osdSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / osdSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "isDateEnabled": {
        +        "description": "Overlay date (boolean)"
        +      },
        +      "isDebugEnabled": {
        +        "description": "Overlay debug info (boolean)"
        +      },
        +      "isLogoEnabled": {
        +        "description": "Overlay logo (boolean)"
        +      },
        +      "isNameEnabled": {
        +        "description": "Overlay camera name (boolean)"
        +      },
        +      "overlayLocation": {
        +        "description": "OSD position, e.g. \"topLeft\"",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / osdSettings / properties
        Removed value: -{
        -  "isDateEnabled": {
        -    "description": "Overlay date (boolean)"
        -  },
        -  "isDebugEnabled": {
        -    "description": "Overlay debug info (boolean)"
        -  },
        -  "isLogoEnabled": {
        -    "description": "Overlay logo (boolean)"
        -  },
        -  "isNameEnabled": {
        -    "description": "Overlay camera name (boolean)"
        -  },
        -  "overlayLocation": {
        -    "description": "OSD position, e.g. \"topLeft\"",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / properties / osdSettings / type
        Removed value: -"object"
      • removedOutput schema / properties / smartDetectSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / smartDetectSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "audioTypes": {
        +        "description": "Enabled audio-detect types (array of strings)"
        +      },
        +      "objectTypes": {
        +        "description": "Enabled object-detect types (array of strings)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / smartDetectSettings / properties
        Removed value: -{
        -  "audioTypes": {
        -    "description": "Enabled audio-detect types (array of strings)"
        -  },
        -  "objectTypes": {
        -    "description": "Enabled object-detect types (array of strings)"
        -  }
        -}
      • removedOutput schema / properties / smartDetectSettings / type
        Removed value: -"object"
    • Changedprotect_get_chime2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_fob6 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / featureFlags / description
        Previous value: -"Feature flags (object: buttons[])"New value: +"Feature flags (object: buttons[], hasKeypad — hasKeypad added in 7.3.x)"
      • removedOutput schema / properties / hasKeypad
        Removed value: -{
        -  "description": "Whether this fob has a keypad, added in 7.3.x (boolean)"
        -}
      • changedOutput schema / properties / keypadSettings / description
        Previous value: -"Keypad config, added in 7.3.x (object: beepEnabled, beepVolume, backlightEnabled, backlightBrightness)"New value: +"Keypad config, added in 7.3.x (object: beepEnabled, beepVolume). The backlightEnabled/backlightBrightness fields were dropped in 7.3.70."
      • changedOutput schema / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
    • Changedprotect_get_info1 field changed
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_light2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_link_station4 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / alarmHub / description
        Previous value: -"Alarm hub status (object: armed, battery, connector, cover, output, input, …)"New value: +"Alarm hub status (object: armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. \"tampered\", added in 7.3.x), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus)"
      • removedOutput schema / properties / deviceTamperStatus
        Removed value: -{
        -  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
    • Changedprotect_get_liveview5 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / slots / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "cameras": {
        +          "description": "Camera IDs shown in this slot (array of strings)"
        +        },
        +        "cycleInterval": {
        +          "description": "Cycle interval in seconds (number)"
        +        },
        +        "cycleMode": {
        +          "description": "Slot cycle mode, e.g. \"time\"",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / slots / items
        Removed value: -{
        -  "additionalProperties": {},
        -  "properties": {
        -    "cameras": {
        -      "description": "Camera IDs shown in this slot (array of strings)"
        -    },
        -    "cycleInterval": {
        -      "description": "Cycle interval in seconds (number)"
        -    },
        -    "cycleMode": {
        -      "description": "Slot cycle mode, e.g. \"time\"",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    }
        -  },
        -  "type": "object"
        -}
      • removedOutput schema / properties / slots / type
        Removed value: -"array"
    • Changedprotect_get_relay5 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / inputs / description
        Previous value: -"Input channels (array of objects)"New value: +"Input channels (array of objects: id, name, state, actionTrigger, actionType, actionOutputId)"
      • changedOutput schema / properties / outputs / description
        Previous value: -"Output channels (array of objects)"New value: +"Output channels (array of objects: id, name, type, delay, pulseDuration, state, rebootState). `id` is the outputId for protect_activate_relay_output"
      • changedOutput schema / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
    • Changedprotect_get_rtsp_streams2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_sensor10 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / glassBreakSettings / description
        Previous value: -"Glass-break detection settings (object)"New value: +"Glass-break detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"
      • changedOutput schema / properties / humiditySettings / description
        Previous value: -"Humidity threshold settings (object)"New value: +"Humidity threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / leakSettings / description
        Previous value: -"Leak detection settings (object)"New value: +"Leak detection settings, read-only (object: isInternalEnabled, isExternalEnabled)"
      • changedOutput schema / properties / lightSettings / description
        Previous value: -"Light threshold settings (object)"New value: +"Light threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / motionSettings / description
        Previous value: -"Motion detection settings (object)"New value: +"Motion detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"
      • changedOutput schema / properties / stats / description
        Previous value: -"Environmental stats (object: light, humidity, temperature)"New value: +"Environmental stats (object: light, humidity, temperature — each { value, status })"
      • changedOutput schema / properties / temperatureSettings / description
        Previous value: -"Temperature threshold settings (object)"New value: +"Temperature threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object: signalState, batteryStatus, bridge)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
    • Changedprotect_get_siren3 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
    • Changedprotect_get_snapshot2 fields changed
      • changedInput schema / properties / highQuality / description
        Previous value: -"If true, request a high-quality snapshot"New value: +"If true, force a 1080p-or-higher resolution snapshot"
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
    • Changedprotect_get_speaker2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_ulp_user3 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / email / description
        Previous value: -"Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.47)"New value: +"Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.70)"
    • Changedprotect_get_user2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_get_viewer2 fields changed
      • addedInput schema / properties / id / pattern
        Added value: +"^[A-Za-z0-9_-]{1,64}$"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
    • Changedprotect_list_alarm_hubs8 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / alarmHub / description
        Previous value: -"Alarm hub status (object: armed, battery, connector, cover, output, input, …)"New value: +"Alarm hub status (object: armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. \"tampered\", added in 7.3.x), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus)"
      • removedOutput schema / properties / result / items / properties / deviceTamperStatus
        Removed value: -{
        -  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_arm_profiles6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_bridges6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_cameras26 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • removedOutput schema / properties / result / items / properties / featureFlags / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / result / items / properties / featureFlags / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "hasHdr": {
        +        "description": "Supports HDR (boolean)"
        +      },
        +      "hasLedStatus": {
        +        "description": "Has a status LED (boolean)"
        +      },
        +      "hasMic": {
        +        "description": "Has a microphone (boolean)"
        +      },
        +      "hasSpeaker": {
        +        "description": "Has a speaker (boolean)"
        +      },
        +      "smartDetectAudioTypes": {
        +        "description": "Supported smart audio-detect types (array of strings)"
        +      },
        +      "smartDetectTypes": {
        +        "description": "Supported smart object-detect types (array of strings)"
        +      },
        +      "supportFullHdSnapshot": {
        +        "description": "Supports full-HD snapshot (boolean)"
        +      },
        +      "videoModes": {
        +        "description": "Supported video modes (array of strings)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / featureFlags / properties
        Removed value: -{
        -  "hasHdr": {
        -    "description": "Supports HDR (boolean)"
        -  },
        -  "hasLedStatus": {
        -    "description": "Has a status LED (boolean)"
        -  },
        -  "hasMic": {
        -    "description": "Has a microphone (boolean)"
        -  },
        -  "hasSpeaker": {
        -    "description": "Has a speaker (boolean)"
        -  },
        -  "smartDetectAudioTypes": {
        -    "description": "Supported smart audio-detect types (array of strings)"
        -  },
        -  "smartDetectTypes": {
        -    "description": "Supported smart object-detect types (array of strings)"
        -  },
        -  "supportFullHdSnapshot": {
        -    "description": "Supports full-HD snapshot (boolean)"
        -  },
        -  "videoModes": {
        -    "description": "Supported video modes (array of strings)"
        -  }
        -}
      • removedOutput schema / properties / result / items / properties / featureFlags / type
        Removed value: -"object"
      • removedOutput schema / properties / result / items / properties / lcdMessage / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / result / items / properties / lcdMessage / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "resetAt": {
        +        "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        +      },
        +      "text": {
        +        "description": "Message text shown on the doorbell LCD",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "type": {
        +        "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\"",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / lcdMessage / properties
        Removed value: -{
        -  "resetAt": {
        -    "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        -  },
        -  "text": {
        -    "description": "Message text shown on the doorbell LCD",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  },
        -  "type": {
        -    "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\"",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / properties / result / items / properties / lcdMessage / type
        Removed value: -"object"
      • removedOutput schema / properties / result / items / properties / ledSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / result / items / properties / ledSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "floodLed": {
        +        "description": "Flood LED enabled (boolean)"
        +      },
        +      "isEnabled": {
        +        "description": "Status LED enabled (boolean)"
        +      },
        +      "welcomeLed": {
        +        "description": "Welcome LED enabled (boolean)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / ledSettings / properties
        Removed value: -{
        -  "floodLed": {
        -    "description": "Flood LED enabled (boolean)"
        -  },
        -  "isEnabled": {
        -    "description": "Status LED enabled (boolean)"
        -  },
        -  "welcomeLed": {
        -    "description": "Welcome LED enabled (boolean)"
        -  }
        -}
      • removedOutput schema / properties / result / items / properties / ledSettings / type
        Removed value: -"object"
      • removedOutput schema / properties / result / items / properties / osdSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / result / items / properties / osdSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "isDateEnabled": {
        +        "description": "Overlay date (boolean)"
        +      },
        +      "isDebugEnabled": {
        +        "description": "Overlay debug info (boolean)"
        +      },
        +      "isLogoEnabled": {
        +        "description": "Overlay logo (boolean)"
        +      },
        +      "isNameEnabled": {
        +        "description": "Overlay camera name (boolean)"
        +      },
        +      "overlayLocation": {
        +        "description": "OSD position, e.g. \"topLeft\"",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / osdSettings / properties
        Removed value: -{
        -  "isDateEnabled": {
        -    "description": "Overlay date (boolean)"
        -  },
        -  "isDebugEnabled": {
        -    "description": "Overlay debug info (boolean)"
        -  },
        -  "isLogoEnabled": {
        -    "description": "Overlay logo (boolean)"
        -  },
        -  "isNameEnabled": {
        -    "description": "Overlay camera name (boolean)"
        -  },
        -  "overlayLocation": {
        -    "description": "OSD position, e.g. \"topLeft\"",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / properties / result / items / properties / osdSettings / type
        Removed value: -"object"
      • removedOutput schema / properties / result / items / properties / smartDetectSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / result / items / properties / smartDetectSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "audioTypes": {
        +        "description": "Enabled audio-detect types (array of strings)"
        +      },
        +      "objectTypes": {
        +        "description": "Enabled object-detect types (array of strings)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / smartDetectSettings / properties
        Removed value: -{
        -  "audioTypes": {
        -    "description": "Enabled audio-detect types (array of strings)"
        -  },
        -  "objectTypes": {
        -    "description": "Enabled object-detect types (array of strings)"
        -  }
        -}
      • removedOutput schema / properties / result / items / properties / smartDetectSettings / type
        Removed value: -"object"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_chimes6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_files13 fields changed
      • addedInput schema / properties / fileType / const
        Added value: +"animations"
      • changedInput schema / properties / fileType / description
        Previous value: -"File type to list (only 'animations' is currently supported)"New value: +"Asset file type (only 'animations' is supported)"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / result / items / properties / createdAt
        Added value: +{
        +  "description": "Creation time (ISO 8601)",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / id
        Added value: +{
        +  "description": "File ID (same value as name)",
        +  "type": "string"
        +}
      • addedOutput schema / properties / result / items / properties / metadata
        Added value: +{
        +  "description": "Asset metadata (object, empty in observed records)"
        +}
      • changedOutput schema / properties / result / items / properties / originalName / description
        Previous value: -"Original uploaded file name"New value: +"Uploaded file name; Protect appends the stored extension, e.g. \"welcome.gif.png\""
      • addedOutput schema / properties / result / items / properties / size
        Added value: +{
        +  "description": "File size in bytes (number)"
        +}
      • addedOutput schema / properties / result / items / properties / updatedAt
        Added value: +{
        +  "description": "Last update time (ISO 8601)",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_fobs10 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / featureFlags / description
        Previous value: -"Feature flags (object: buttons[])"New value: +"Feature flags (object: buttons[], hasKeypad — hasKeypad added in 7.3.x)"
      • removedOutput schema / properties / result / items / properties / hasKeypad
        Removed value: -{
        -  "description": "Whether this fob has a keypad, added in 7.3.x (boolean)"
        -}
      • changedOutput schema / properties / result / items / properties / keypadSettings / description
        Previous value: -"Keypad config, added in 7.3.x (object: beepEnabled, beepVolume, backlightEnabled, backlightBrightness)"New value: +"Keypad config, added in 7.3.x (object: beepEnabled, beepVolume). The backlightEnabled/backlightBrightness fields were dropped in 7.3.70."
      • changedOutput schema / properties / result / items / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_lights6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_link_stations8 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / alarmHub / description
        Previous value: -"Alarm hub status (object: armed, battery, connector, cover, output, input, …)"New value: +"Alarm hub status (object: armed, battery, buckboost, connector, cover, deviceTamperStatus (e.g. \"tampered\", added in 7.3.x), currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, powerMeter, output and input (maps keyed by channel), inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, auxiliaryPowerTerminalStatus)"
      • removedOutput schema / properties / result / items / properties / deviceTamperStatus
        Removed value: -{
        -  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        -  "type": [
        -    "string",
        -    "null"
        -  ]
        -}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_liveviews9 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / result / items / properties / slots / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "cameras": {
        +          "description": "Camera IDs shown in this slot (array of strings)"
        +        },
        +        "cycleInterval": {
        +          "description": "Cycle interval in seconds (number)"
        +        },
        +        "cycleMode": {
        +          "description": "Slot cycle mode, e.g. \"time\"",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / result / items / properties / slots / items
        Removed value: -{
        -  "additionalProperties": {},
        -  "properties": {
        -    "cameras": {
        -      "description": "Camera IDs shown in this slot (array of strings)"
        -    },
        -    "cycleInterval": {
        -      "description": "Cycle interval in seconds (number)"
        -    },
        -    "cycleMode": {
        -      "description": "Slot cycle mode, e.g. \"time\"",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    }
        -  },
        -  "type": "object"
        -}
      • removedOutput schema / properties / result / items / properties / slots / type
        Removed value: -"array"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_nvrs9 fields changed
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • removedOutput schema / properties / armMode / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / armMode / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "armProfileId": {
        +        "description": "Active arm profile ID (present when arming/armed)",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "armedAt": {
        +        "description": "Unix epoch ms when armed, or null (number|null)"
        +      },
        +      "breachDetectedAt": {
        +        "description": "Unix epoch ms of last breach, or null"
        +      },
        +      "breachEventCount": {
        +        "description": "Count of breach events (number)"
        +      },
        +      "breachEventId": {
        +        "description": "Breach event ID, or null (string|null)"
        +      },
        +      "breachTriggerEventId": {
        +        "description": "Triggering event ID, or null (string|null)"
        +      },
        +      "status": {
        +        "description": "disabled | arming | armed | ...",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "willBeArmedAt": {
        +        "description": "Scheduled arm time, or null (number|null)"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / armMode / properties
        Removed value: -{
        -  "armProfileId": {
        -    "description": "Active arm profile ID (present when arming/armed)",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  },
        -  "armedAt": {
        -    "description": "Unix epoch ms when armed, or null (number|null)"
        -  },
        -  "breachDetectedAt": {
        -    "description": "Unix epoch ms of last breach, or null"
        -  },
        -  "breachEventCount": {
        -    "description": "Count of breach events (number)"
        -  },
        -  "breachEventId": {
        -    "description": "Breach event ID, or null (string|null)"
        -  },
        -  "breachTriggerEventId": {
        -    "description": "Triggering event ID, or null (string|null)"
        -  },
        -  "status": {
        -    "description": "disabled | arming | armed | ...",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  },
        -  "willBeArmedAt": {
        -    "description": "Scheduled arm time, or null (number|null)"
        -  }
        -}
      • removedOutput schema / properties / armMode / type
        Removed value: -"object"
      • removedOutput schema / properties / doorbellSettings / additionalProperties
        Removed value: -{}
      • addedOutput schema / properties / doorbellSettings / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": {},
        +    "properties": {
        +      "customImages": {
        +        "description": "Configured custom LCD images (array of objects: preview, sprite)"
        +      },
        +      "customMessages": {
        +        "description": "Configured custom LCD messages (array of strings)"
        +      },
        +      "defaultMessageResetTimeoutMs": {
        +        "description": "Reset timeout in ms (number)"
        +      },
        +      "defaultMessageText": {
        +        "description": "Default doorbell LCD message",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / doorbellSettings / properties
        Removed value: -{
        -  "customImages": {
        -    "description": "Configured custom LCD images (array)"
        -  },
        -  "customMessages": {
        -    "description": "Configured custom LCD messages (array of strings)"
        -  },
        -  "defaultMessageResetTimeoutMs": {
        -    "description": "Reset timeout in ms (number)"
        -  },
        -  "defaultMessageText": {
        -    "description": "Default doorbell LCD message",
        -    "type": [
        -      "string",
        -      "null"
        -    ]
        -  }
        -}
      • removedOutput schema / properties / doorbellSettings / type
        Removed value: -"object"
    • Changedprotect_list_relays9 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / inputs / description
        Previous value: -"Input channels (array of objects)"New value: +"Input channels (array of objects: id, name, state, actionTrigger, actionType, actionOutputId)"
      • changedOutput schema / properties / result / items / properties / outputs / description
        Previous value: -"Output channels (array of objects)"New value: +"Output channels (array of objects: id, name, type, delay, pulseDuration, state, rebootState). `id` is the outputId for protect_activate_relay_output"
      • changedOutput schema / properties / result / items / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_sensors14 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / glassBreakSettings / description
        Previous value: -"Glass-break detection settings (object)"New value: +"Glass-break detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"
      • changedOutput schema / properties / result / items / properties / humiditySettings / description
        Previous value: -"Humidity threshold settings (object)"New value: +"Humidity threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / result / items / properties / leakSettings / description
        Previous value: -"Leak detection settings (object)"New value: +"Leak detection settings, read-only (object: isInternalEnabled, isExternalEnabled)"
      • changedOutput schema / properties / result / items / properties / lightSettings / description
        Previous value: -"Light threshold settings (object)"New value: +"Light threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / result / items / properties / motionSettings / description
        Previous value: -"Motion detection settings (object)"New value: +"Motion detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"
      • changedOutput schema / properties / result / items / properties / stats / description
        Previous value: -"Environmental stats (object: light, humidity, temperature)"New value: +"Environmental stats (object: light, humidity, temperature — each { value, status })"
      • changedOutput schema / properties / result / items / properties / temperatureSettings / description
        Previous value: -"Temperature threshold settings (object)"New value: +"Temperature threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"
      • changedOutput schema / properties / result / items / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object: signalState, batteryStatus, bridge)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_sirens7 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / wirelessConnectionState / description
        Previous value: -"Wireless link state (object)"New value: +"Wireless link state (object: signalState { signalQuality, signalStrength }, batteryStatus { percentage, isLow }, bridge)"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_speakers6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_ulp_users7 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / result / items / properties / email / description
        Previous value: -"Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.47)"New value: +"Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.70)"
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_users6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_list_viewers6 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Return at most this many items",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Skip this many items first (default 0)",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • addedOutput schema / properties / offset
        Added value: +{
        +  "description": "Paged results only: the index of the first item returned",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Paged results only: the number of items in the whole list",
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedprotect_subscribe_devices3 fields changed
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / duration / description
        Previous value: -"Actual listen duration in seconds (number)"New value: +"Seconds actually spent listening, to 0.1s (number); shorter than requested when the message cap or an error ends the listen early"
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "description": "true when listening stopped early at the message cap (boolean, absent otherwise)"
        +}
    • Changedprotect_subscribe_events3 fields changed
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • changedOutput schema / properties / duration / description
        Previous value: -"Actual listen duration in seconds (number)"New value: +"Seconds actually spent listening, to 0.1s (number); shorter than requested when the message cap or an error ends the listen early"
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "description": "true when listening stopped early at the message cap (boolean, absent otherwise)"
        +}
  2. 27 tool updatesv2.13.0
    • Changedprotect_get_alarm_hub4 fields changed
      • addedOutput schema / properties / deviceTamperStatus
        Added value: +{
        +  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / threadState
        Added value: +{
        +  "description": "Thread radio state, added in 7.3.x (object: network — status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt)"
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_bridge2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_camera2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_chime2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_fob5 fields changed
      • addedOutput schema / properties / armControlSettings
        Added value: +{
        +  "description": "Arm-control config, added in 7.3.x (object: enabled, armProfileId, nightProfileId)"
        +}
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / hasKeypad
        Added value: +{
        +  "description": "Whether this fob has a keypad, added in 7.3.x (boolean)"
        +}
      • addedOutput schema / properties / keypadSettings
        Added value: +{
        +  "description": "Keypad config, added in 7.3.x (object: beepEnabled, beepVolume, backlightEnabled, backlightBrightness)"
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_light2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_link_station4 fields changed
      • addedOutput schema / properties / deviceTamperStatus
        Added value: +{
        +  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / threadState
        Added value: +{
        +  "description": "Thread radio state, added in 7.3.x (object: network — status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt)"
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_relay2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_sensor3 fields changed
      • addedOutput schema / properties / featureFlags
        Added value: +{
        +  "description": "Sensor capability flags, added in 7.3.x (object: temperature, humidity, light, motion, waterLeak, open, tamper, smoke — each { channelCount })"
        +}
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_siren2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_speaker2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_ulp_user1 field changed
      • addedOutput schema / properties / email
        Added value: +{
        +  "description": "Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.47)",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_get_viewer2 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_alarm_hubs4 fields changed
      • addedOutput schema / properties / result / items / properties / deviceTamperStatus
        Added value: +{
        +  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / threadState
        Added value: +{
        +  "description": "Thread radio state, added in 7.3.x (object: network — status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt)"
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_bridges2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_cameras2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_chimes2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_fobs5 fields changed
      • addedOutput schema / properties / result / items / properties / armControlSettings
        Added value: +{
        +  "description": "Arm-control config, added in 7.3.x (object: enabled, armProfileId, nightProfileId)"
        +}
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / hasKeypad
        Added value: +{
        +  "description": "Whether this fob has a keypad, added in 7.3.x (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / keypadSettings
        Added value: +{
        +  "description": "Keypad config, added in 7.3.x (object: beepEnabled, beepVolume, backlightEnabled, backlightBrightness)"
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_lights2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_link_stations4 fields changed
      • addedOutput schema / properties / result / items / properties / deviceTamperStatus
        Added value: +{
        +  "description": "Tamper status, added in 7.3.x, e.g. \"tampered\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / threadState
        Added value: +{
        +  "description": "Thread radio state, added in 7.3.x (object: network — status, role, networkName, channel, panId, extendedPanId, joinedDeviceCount, errorReason, lastUpdatedAt)"
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_nvrs3 fields changed
      • addedOutput schema / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / mac
        Added value: +{
        +  "description": "MAC address, added in 7.3.x",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_relays2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_sensors3 fields changed
      • addedOutput schema / properties / result / items / properties / featureFlags
        Added value: +{
        +  "description": "Sensor capability flags, added in 7.3.x (object: temperature, humidity, light, motion, waterLeak, open, tamper, smoke — each { channelCount })"
        +}
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_sirens2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_speakers2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_ulp_users1 field changed
      • addedOutput schema / properties / result / items / properties / email
        Added value: +{
        +  "description": "Email address, added in 7.3.x. Empty string for service accounts (verified live 7.3.47)",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedprotect_list_viewers2 fields changed
      • addedOutput schema / properties / result / items / properties / guid
        Added value: +{
        +  "description": "Hardware MODEL GUID, shared by every unit of the same model. NOT a per-device identifier — use `id` to identify a device.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "description": "Hardware model name, e.g. \"UVC G6 Turret\", \"UP Chime PoE\", \"UNVR-PRO\"",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
  3. 37 tool updatesv2.11.5
    • Changedprotect_get_alarm_hub8 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_bridge10 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / platform / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / platform / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_camera18 fields changed
      • removedOutput schema / properties / hdrType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / hdrType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / lcdMessage / properties / text / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / lcdMessage / properties / text / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / lcdMessage / properties / type / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / lcdMessage / properties / type / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / osdSettings / properties / overlayLocation / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / osdSettings / properties / overlayLocation / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / videoMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / videoMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_chime8 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_fob12 fields changed
      • removedOutput schema / properties / awayState / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / awayState / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / buttonLabels / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / buttonLabels / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_info2 fields changed
      • removedOutput schema / properties / applicationVersion / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / applicationVersion / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_light10 fields changed
      • removedOutput schema / properties / camera / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / camera / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_link_station8 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_liveview8 fields changed
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / owner / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / owner / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / slots / items / properties / cycleMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / slots / items / properties / cycleMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_relay8 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_rtsp_streams8 fields changed
      • removedOutput schema / properties / high / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / high / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / low / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / low / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / medium / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / medium / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / package / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / package / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_sensor12 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mountType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mountType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / scheduleMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / scheduleMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_siren10 fields changed
      • removedOutput schema / properties / connectionType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / connectionType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_speaker8 fields changed
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_ulp_user10 fields changed
      • removedOutput schema / properties / firstName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / firstName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / fullName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / fullName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / lastName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / lastName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / status / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / status / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_user12 fields changed
      • removedOutput schema / properties / email / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / email / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / firstName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / firstName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / lastName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / lastName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / ucoreUserId / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / ucoreUserId / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_get_viewer10 fields changed
      • removedOutput schema / properties / liveview / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / liveview / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_alarm_hubs8 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_arm_profiles4 fields changed
      • removedOutput schema / properties / result / items / properties / creator / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / creator / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_bridges10 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / platform / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / platform / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_cameras18 fields changed
      • removedOutput schema / properties / result / items / properties / hdrType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / hdrType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / lcdMessage / properties / text / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / lcdMessage / properties / text / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / lcdMessage / properties / type / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / lcdMessage / properties / type / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / osdSettings / properties / overlayLocation / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / osdSettings / properties / overlayLocation / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / videoMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / videoMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_chimes8 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_files8 fields changed
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / originalName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / originalName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / path / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / path / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / type / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / type / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_fobs12 fields changed
      • removedOutput schema / properties / result / items / properties / awayState / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / awayState / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / buttonLabels / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / buttonLabels / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_lights10 fields changed
      • removedOutput schema / properties / result / items / properties / camera / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / camera / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_link_stations8 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_liveviews8 fields changed
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / owner / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / owner / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / slots / items / properties / cycleMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / slots / items / properties / cycleMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_nvrs10 fields changed
      • removedOutput schema / properties / armMode / properties / armProfileId / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / armMode / properties / armProfileId / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / armMode / properties / status / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / armMode / properties / status / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / doorbellSettings / properties / defaultMessageText / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / doorbellSettings / properties / defaultMessageText / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_relays8 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_sensors12 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mountType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mountType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / scheduleMode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / scheduleMode / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_sirens10 fields changed
      • removedOutput schema / properties / result / items / properties / connectionType / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / connectionType / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_speakers8 fields changed
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_ulp_users10 fields changed
      • removedOutput schema / properties / result / items / properties / firstName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / firstName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / fullName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / fullName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / lastName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / lastName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / status / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / status / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_users12 fields changed
      • removedOutput schema / properties / result / items / properties / email / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / email / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / firstName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / firstName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / lastName / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / lastName / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / ucoreUserId / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / ucoreUserId / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_list_viewers10 fields changed
      • removedOutput schema / properties / result / items / properties / liveview / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / liveview / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / mac / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / mac / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / modelKey / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / modelKey / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / result / items / properties / state / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / result / items / properties / state / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_subscribe_devices2 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedprotect_subscribe_events2 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
  4. 11 tool updatesv2.10.0
    • Addedprotect_get_fob
    • Addedprotect_get_info
    • Addedprotect_get_link_station
    • Addedprotect_get_rtsp_streams
    • Addedprotect_list_arm_profiles
    • Addedprotect_list_chimes
    • Addedprotect_list_fobs
    • Addedprotect_list_link_stations
    • Addedprotect_list_nvrs
    • Addedprotect_list_speakers
    • Addedprotect_list_viewers
  5. 11 tool updatesv2.9.0
    • Removedprotect_get_fob
    • Removedprotect_get_info
    • Removedprotect_get_link_station
    • Removedprotect_get_rtsp_streams
    • Removedprotect_list_arm_profiles
    • Removedprotect_list_chimes
    • Removedprotect_list_fobs
    • Removedprotect_list_link_stations
    • Removedprotect_list_nvrs
    • Removedprotect_list_speakers
    • Removedprotect_list_viewers
  6. 28 tool updatesv2.7.5
    • Changedprotect_get_alarm_hub4 fields changed
      • addedOutput schema / properties / alarmHub
        Added value: +{
        +  "description": "Alarm hub status (object: armed, battery, connector, cover, output, input, …)"
        +}
      • addedOutput schema / properties / isAlarmHub
        Added value: +{
        +  "description": "Whether this device is an alarm hub (boolean)"
        +}
      • addedOutput schema / properties / lastEvent
        Added value: +{
        +  "description": "Last event timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
    • Changedprotect_get_bridge3 fields changed
      • addedOutput schema / properties / clients
        Added value: +{
        +  "description": "Connected client MACs (array of strings)"
        +}
      • addedOutput schema / properties / maxClients
        Added value: +{
        +  "description": "Max client capacity (number)"
        +}
      • addedOutput schema / properties / platform
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Hardware platform, e.g. \"mt7621\""
        +}
    • Changedprotect_get_camera4 fields changed
      • addedOutput schema / properties / lcdMessage / additionalProperties
        Added value: +{}
      • removedOutput schema / properties / lcdMessage / description
        Removed value: -"Doorbell LCD message (object; often empty {})"
      • addedOutput schema / properties / lcdMessage / properties
        Added value: +{
        +  "resetAt": {
        +    "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        +  },
        +  "text": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "description": "Message text shown on the doorbell LCD"
        +  },
        +  "type": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\""
        +  }
        +}
      • addedOutput schema / properties / lcdMessage / type
        Added value: +"object"
    • Changedprotect_get_chime2 fields changed
      • addedOutput schema / properties / cameraIds
        Added value: +{
        +  "description": "Paired camera IDs (array of strings)"
        +}
      • addedOutput schema / properties / ringSettings
        Added value: +{
        +  "description": "Per-camera ring config (array of objects: cameraId, volume, ringtoneId, repeatTimes)"
        +}
    • Changedprotect_get_fob4 fields changed
      • addedOutput schema / properties / awayState
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Away state, e.g. \"ONLINE\""
        +}
      • addedOutput schema / properties / buttonLabels
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Button label preset, e.g. \"securityActions\""
        +}
      • addedOutput schema / properties / featureFlags
        Added value: +{
        +  "description": "Feature flags (object: buttons[])"
        +}
      • addedOutput schema / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_get_light8 fields changed
      • addedOutput schema / properties / camera
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Paired camera ID"
        +}
      • addedOutput schema / properties / isDark
        Added value: +{
        +  "description": "Whether it is currently dark out (boolean)"
        +}
      • addedOutput schema / properties / isLightForceEnabled
        Added value: +{
        +  "description": "Main LED force-enabled (boolean)"
        +}
      • addedOutput schema / properties / isLightOn
        Added value: +{
        +  "description": "Whether the light is currently on (boolean)"
        +}
      • addedOutput schema / properties / isPirMotionDetected
        Added value: +{
        +  "description": "PIR motion currently detected (boolean)"
        +}
      • addedOutput schema / properties / lastMotion
        Added value: +{
        +  "description": "Last motion timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / lightDeviceSettings
        Added value: +{
        +  "description": "Hardware settings (object: isIndicatorEnabled, pirDuration, pirSensitivity, ledLevel)"
        +}
      • addedOutput schema / properties / lightModeSettings
        Added value: +{
        +  "description": "Activation settings (object: mode, enableAt)"
        +}
    • Changedprotect_get_link_station4 fields changed
      • addedOutput schema / properties / alarmHub
        Added value: +{
        +  "description": "Alarm hub status (object: armed, battery, connector, cover, output, input, …)"
        +}
      • addedOutput schema / properties / isAlarmHub
        Added value: +{
        +  "description": "Whether this device is an alarm hub (boolean)"
        +}
      • addedOutput schema / properties / lastEvent
        Added value: +{
        +  "description": "Last event timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
    • Changedprotect_get_relay4 fields changed
      • addedOutput schema / properties / inputs
        Added value: +{
        +  "description": "Input channels (array of objects)"
        +}
      • addedOutput schema / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / outputs
        Added value: +{
        +  "description": "Output channels (array of objects)"
        +}
      • addedOutput schema / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_get_sensor22 fields changed
      • addedOutput schema / properties / alarmSettings
        Added value: +{
        +  "description": "Alarm settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / alarmTriggeredAt
        Added value: +{
        +  "description": "Last alarm timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / armProfileIds
        Added value: +{
        +  "description": "Arm profile IDs this sensor belongs to (array of strings)"
        +}
      • addedOutput schema / properties / batteryStatus
        Added value: +{
        +  "description": "Battery status (object: percentage, isLow)"
        +}
      • addedOutput schema / properties / externalLeakDetectedAt
        Added value: +{
        +  "description": "Last external-leak timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / glassBreakSettings
        Added value: +{
        +  "description": "Glass-break detection settings (object)"
        +}
      • addedOutput schema / properties / hasCustomSensitivityWhenArmed
        Added value: +{
        +  "description": "Custom armed sensitivity enabled (boolean)"
        +}
      • addedOutput schema / properties / humiditySettings
        Added value: +{
        +  "description": "Humidity threshold settings (object)"
        +}
      • addedOutput schema / properties / isMotionDetected
        Added value: +{
        +  "description": "Motion currently detected (boolean)"
        +}
      • addedOutput schema / properties / isOpened
        Added value: +{
        +  "description": "Open/close contact state (boolean)"
        +}
      • addedOutput schema / properties / leakDetectedAt
        Added value: +{
        +  "description": "Last leak timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / leakSettings
        Added value: +{
        +  "description": "Leak detection settings (object)"
        +}
      • addedOutput schema / properties / lightSettings
        Added value: +{
        +  "description": "Light threshold settings (object)"
        +}
      • addedOutput schema / properties / motionDetectedAt
        Added value: +{
        +  "description": "Last motion timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / motionSettings
        Added value: +{
        +  "description": "Motion detection settings (object)"
        +}
      • addedOutput schema / properties / mountType
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Mount type, e.g. \"door\", \"leak\", \"garage\""
        +}
      • addedOutput schema / properties / openStatusChangedAt
        Added value: +{
        +  "description": "Open-status change timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / scheduleMode
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Schedule mode: \"always\" | \"when_armed\""
        +}
      • addedOutput schema / properties / stats
        Added value: +{
        +  "description": "Environmental stats (object: light, humidity, temperature)"
        +}
      • addedOutput schema / properties / tamperingDetectedAt
        Added value: +{
        +  "description": "Last tampering timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / temperatureSettings
        Added value: +{
        +  "description": "Temperature threshold settings (object)"
        +}
      • addedOutput schema / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object: signalState, batteryStatus, bridge)"
        +}
    • Changedprotect_get_siren5 fields changed
      • addedOutput schema / properties / connectionType
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Connection type, e.g. \"lora\""
        +}
      • addedOutput schema / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / sirenStatus
        Added value: +{
        +  "description": "Current siren status (object: isActive, activatedAt, duration)"
        +}
      • addedOutput schema / properties / volume
        Added value: +{
        +  "description": "Siren volume (number)"
        +}
      • addedOutput schema / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_get_snapshot1 field changed
      • addedInput schema / properties / channel
        Added value: +{
        +  "description": "Camera channel to capture. Use \"package\" for cameras with hasPackageCamera=true (defaults to main)",
        +  "enum": [
        +    "main",
        +    "package"
        +  ],
        +  "type": "string"
        +}
    • Changedprotect_get_speaker5 fields changed
      • addedOutput schema / properties / featureFlags
        Added value: +{
        +  "description": "Feature flags (object: hasMic)"
        +}
      • addedOutput schema / properties / isMicEnabled
        Added value: +{
        +  "description": "Microphone enabled (boolean)"
        +}
      • addedOutput schema / properties / micVolume
        Added value: +{
        +  "description": "Microphone volume (number)"
        +}
      • addedOutput schema / properties / speakerState
        Added value: +{
        +  "description": "Speaker state (object: status, mode)"
        +}
      • addedOutput schema / properties / volume
        Added value: +{
        +  "description": "Speaker volume (number)"
        +}
    • Changedprotect_get_viewer2 fields changed
      • addedOutput schema / properties / liveview
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Assigned live view ID, or null"
        +}
      • addedOutput schema / properties / streamLimit
        Added value: +{
        +  "description": "Max concurrent streams (number)"
        +}
    • Changedprotect_list_alarm_hubs4 fields changed
      • addedOutput schema / properties / result / items / properties / alarmHub
        Added value: +{
        +  "description": "Alarm hub status (object: armed, battery, connector, cover, output, input, …)"
        +}
      • addedOutput schema / properties / result / items / properties / isAlarmHub
        Added value: +{
        +  "description": "Whether this device is an alarm hub (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / lastEvent
        Added value: +{
        +  "description": "Last event timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
    • Changedprotect_list_arm_profiles8 fields changed
      • addedOutput schema / properties / result / items / properties / activationDelay
        Added value: +{
        +  "description": "Activation delay in ms: 0 | 60000 | 300000 | 600000 (number)"
        +}
      • addedOutput schema / properties / result / items / properties / automations
        Added value: +{
        +  "description": "Associated automation IDs (array of strings)"
        +}
      • addedOutput schema / properties / result / items / properties / createdAt
        Added value: +{
        +  "description": "Creation timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / creator
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "ID of the user who created the profile"
        +}
      • removedOutput schema / properties / result / items / properties / modelKey
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "description": "Resource kind"
        -}
      • addedOutput schema / properties / result / items / properties / recordEverything
        Added value: +{
        +  "description": "Record everything while active (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / schedules
        Added value: +{
        +  "description": "Arm schedules (array of objects)"
        +}
      • addedOutput schema / properties / result / items / properties / updatedAt
        Added value: +{
        +  "description": "Last update timestamp in epoch ms (number)"
        +}
    • Changedprotect_list_bridges3 fields changed
      • addedOutput schema / properties / result / items / properties / clients
        Added value: +{
        +  "description": "Connected client MACs (array of strings)"
        +}
      • addedOutput schema / properties / result / items / properties / maxClients
        Added value: +{
        +  "description": "Max client capacity (number)"
        +}
      • addedOutput schema / properties / result / items / properties / platform
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Hardware platform, e.g. \"mt7621\""
        +}
    • Changedprotect_list_cameras4 fields changed
      • addedOutput schema / properties / result / items / properties / lcdMessage / additionalProperties
        Added value: +{}
      • removedOutput schema / properties / result / items / properties / lcdMessage / description
        Removed value: -"Doorbell LCD message (object; often empty {})"
      • addedOutput schema / properties / result / items / properties / lcdMessage / properties
        Added value: +{
        +  "resetAt": {
        +    "description": "Auto-reset timestamp in epoch ms, or null (number|null)"
        +  },
        +  "text": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "description": "Message text shown on the doorbell LCD"
        +  },
        +  "type": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "description": "Message type, e.g. \"CUSTOM_MESSAGE\", \"LEAVE_PACKAGE_AT_DOOR\", \"DO_NOT_DISTURB\""
        +  }
        +}
      • addedOutput schema / properties / result / items / properties / lcdMessage / type
        Added value: +"object"
    • Changedprotect_list_chimes2 fields changed
      • addedOutput schema / properties / result / items / properties / cameraIds
        Added value: +{
        +  "description": "Paired camera IDs (array of strings)"
        +}
      • addedOutput schema / properties / result / items / properties / ringSettings
        Added value: +{
        +  "description": "Per-camera ring config (array of objects: cameraId, volume, ringtoneId, repeatTimes)"
        +}
    • Changedprotect_list_files6 fields changed
      • removedOutput schema / properties / result / items / properties / id
        Removed value: -{
        -  "description": "File ID",
        -  "type": "string"
        -}
      • removedOutput schema / properties / result / items / properties / modelKey
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "description": "Resource kind"
        -}
      • changedOutput schema / properties / result / items / properties / name / description
        Previous value: -"File name"New value: +"Stored file name (server-generated)"
      • addedOutput schema / properties / result / items / properties / originalName
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Original uploaded file name"
        +}
      • addedOutput schema / properties / result / items / properties / path
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Server-side storage path"
        +}
      • addedOutput schema / properties / result / items / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Asset file type, e.g. \"animations\""
        +}
    • Changedprotect_list_fobs4 fields changed
      • addedOutput schema / properties / result / items / properties / awayState
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Away state, e.g. \"ONLINE\""
        +}
      • addedOutput schema / properties / result / items / properties / buttonLabels
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Button label preset, e.g. \"securityActions\""
        +}
      • addedOutput schema / properties / result / items / properties / featureFlags
        Added value: +{
        +  "description": "Feature flags (object: buttons[])"
        +}
      • addedOutput schema / properties / result / items / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_list_lights8 fields changed
      • addedOutput schema / properties / result / items / properties / camera
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Paired camera ID"
        +}
      • addedOutput schema / properties / result / items / properties / isDark
        Added value: +{
        +  "description": "Whether it is currently dark out (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / isLightForceEnabled
        Added value: +{
        +  "description": "Main LED force-enabled (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / isLightOn
        Added value: +{
        +  "description": "Whether the light is currently on (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / isPirMotionDetected
        Added value: +{
        +  "description": "PIR motion currently detected (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / lastMotion
        Added value: +{
        +  "description": "Last motion timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / lightDeviceSettings
        Added value: +{
        +  "description": "Hardware settings (object: isIndicatorEnabled, pirDuration, pirSensitivity, ledLevel)"
        +}
      • addedOutput schema / properties / result / items / properties / lightModeSettings
        Added value: +{
        +  "description": "Activation settings (object: mode, enableAt)"
        +}
    • Changedprotect_list_link_stations4 fields changed
      • addedOutput schema / properties / result / items / properties / alarmHub
        Added value: +{
        +  "description": "Alarm hub status (object: armed, battery, connector, cover, output, input, …)"
        +}
      • addedOutput schema / properties / result / items / properties / isAlarmHub
        Added value: +{
        +  "description": "Whether this device is an alarm hub (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / lastEvent
        Added value: +{
        +  "description": "Last event timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
    • Changedprotect_list_nvrs2 fields changed
      • addedOutput schema / properties / armMode / properties / armProfileId
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Active arm profile ID (present when arming/armed)"
        +}
      • changedOutput schema / properties / armMode / properties / status / description
        Previous value: -"disabled | armed | ..."New value: +"disabled | arming | armed | ..."
    • Changedprotect_list_relays4 fields changed
      • addedOutput schema / properties / result / items / properties / inputs
        Added value: +{
        +  "description": "Input channels (array of objects)"
        +}
      • addedOutput schema / properties / result / items / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / result / items / properties / outputs
        Added value: +{
        +  "description": "Output channels (array of objects)"
        +}
      • addedOutput schema / properties / result / items / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_list_sensors22 fields changed
      • addedOutput schema / properties / result / items / properties / alarmSettings
        Added value: +{
        +  "description": "Alarm settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / result / items / properties / alarmTriggeredAt
        Added value: +{
        +  "description": "Last alarm timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / armProfileIds
        Added value: +{
        +  "description": "Arm profile IDs this sensor belongs to (array of strings)"
        +}
      • addedOutput schema / properties / result / items / properties / batteryStatus
        Added value: +{
        +  "description": "Battery status (object: percentage, isLow)"
        +}
      • addedOutput schema / properties / result / items / properties / externalLeakDetectedAt
        Added value: +{
        +  "description": "Last external-leak timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / glassBreakSettings
        Added value: +{
        +  "description": "Glass-break detection settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / hasCustomSensitivityWhenArmed
        Added value: +{
        +  "description": "Custom armed sensitivity enabled (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / humiditySettings
        Added value: +{
        +  "description": "Humidity threshold settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / isMotionDetected
        Added value: +{
        +  "description": "Motion currently detected (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / isOpened
        Added value: +{
        +  "description": "Open/close contact state (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / leakDetectedAt
        Added value: +{
        +  "description": "Last leak timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / leakSettings
        Added value: +{
        +  "description": "Leak detection settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / lightSettings
        Added value: +{
        +  "description": "Light threshold settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / motionDetectedAt
        Added value: +{
        +  "description": "Last motion timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / motionSettings
        Added value: +{
        +  "description": "Motion detection settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / mountType
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Mount type, e.g. \"door\", \"leak\", \"garage\""
        +}
      • addedOutput schema / properties / result / items / properties / openStatusChangedAt
        Added value: +{
        +  "description": "Open-status change timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / scheduleMode
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Schedule mode: \"always\" | \"when_armed\""
        +}
      • addedOutput schema / properties / result / items / properties / stats
        Added value: +{
        +  "description": "Environmental stats (object: light, humidity, temperature)"
        +}
      • addedOutput schema / properties / result / items / properties / tamperingDetectedAt
        Added value: +{
        +  "description": "Last tampering timestamp in epoch ms (number)"
        +}
      • addedOutput schema / properties / result / items / properties / temperatureSettings
        Added value: +{
        +  "description": "Temperature threshold settings (object)"
        +}
      • addedOutput schema / properties / result / items / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object: signalState, batteryStatus, bridge)"
        +}
    • Changedprotect_list_sirens5 fields changed
      • addedOutput schema / properties / result / items / properties / connectionType
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Connection type, e.g. \"lora\""
        +}
      • addedOutput schema / properties / result / items / properties / ledSettings
        Added value: +{
        +  "description": "LED settings (object: isEnabled)"
        +}
      • addedOutput schema / properties / result / items / properties / sirenStatus
        Added value: +{
        +  "description": "Current siren status (object: isActive, activatedAt, duration)"
        +}
      • addedOutput schema / properties / result / items / properties / volume
        Added value: +{
        +  "description": "Siren volume (number)"
        +}
      • addedOutput schema / properties / result / items / properties / wirelessConnectionState
        Added value: +{
        +  "description": "Wireless link state (object)"
        +}
    • Changedprotect_list_speakers5 fields changed
      • addedOutput schema / properties / result / items / properties / featureFlags
        Added value: +{
        +  "description": "Feature flags (object: hasMic)"
        +}
      • addedOutput schema / properties / result / items / properties / isMicEnabled
        Added value: +{
        +  "description": "Microphone enabled (boolean)"
        +}
      • addedOutput schema / properties / result / items / properties / micVolume
        Added value: +{
        +  "description": "Microphone volume (number)"
        +}
      • addedOutput schema / properties / result / items / properties / speakerState
        Added value: +{
        +  "description": "Speaker state (object: status, mode)"
        +}
      • addedOutput schema / properties / result / items / properties / volume
        Added value: +{
        +  "description": "Speaker volume (number)"
        +}
    • Changedprotect_list_viewers2 fields changed
      • addedOutput schema / properties / result / items / properties / liveview
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Assigned live view ID, or null"
        +}
      • addedOutput schema / properties / result / items / properties / streamLimit
        Added value: +{
        +  "description": "Max concurrent streams (number)"
        +}
  7. 38 tool updatesv2.7.4
    • First observedprotect_get_alarm_hub
    • First observedprotect_get_bridge
    • First observedprotect_get_camera
    • First observedprotect_get_chime
    • First observedprotect_get_fob
    • First observedprotect_get_info
    • First observedprotect_get_light
    • First observedprotect_get_link_station
    • First observedprotect_get_liveview
    • First observedprotect_get_relay
    • First observedprotect_get_rtsp_streams
    • First observedprotect_get_sensor
    • First observedprotect_get_siren
    • First observedprotect_get_snapshot
    • First observedprotect_get_speaker
    • First observedprotect_get_ulp_user
    • First observedprotect_get_user
    • First observedprotect_get_viewer
    • First observedprotect_list_alarm_hubs
    • First observedprotect_list_arm_profiles
    • First observedprotect_list_bridges
    • First observedprotect_list_cameras
    • First observedprotect_list_chimes
    • First observedprotect_list_files
    • First observedprotect_list_fobs
    • First observedprotect_list_lights
    • First observedprotect_list_link_stations
    • First observedprotect_list_liveviews
    • First observedprotect_list_nvrs
    • First observedprotect_list_relays
    • First observedprotect_list_sensors
    • First observedprotect_list_sirens
    • First observedprotect_list_speakers
    • First observedprotect_list_ulp_users
    • First observedprotect_list_users
    • First observedprotect_list_viewers
    • First observedprotect_subscribe_devices
    • First observedprotect_subscribe_events

TDQS

B3.4/5.0

Scored across 38 tools

Disambiguation4/5

Most tools are cleanly separated: every device family has a distinct list_* vs get_* pair distinguished by verb, and snapshot/rtsp/subscribe are clearly unique. The only real overlap is protect_list_link_stations vs protect_list_alarm_hubs, which return the same modelKey ('linkstation') and nearly identical field sets, though the descriptions explicitly disambiguate.

Naming Consistency5/5

Every tool uses the same protect_ prefix followed by a consistent verb_noun pattern (list_*, get_*, subscribe_*), with no camelCase or mixed-style deviations. Naming is highly predictable across all 38 tools.

Tool Count3/5

38 tools is heavy, driven by 13 device families each carrying both a list_* and a get_* variant. The get_* tools add little since their descriptions admit they return the same field set as the list entries, so several tools are near-redundant even if the underlying domain is large.

Completeness2/5

The surface is read-only (list/get/snapshot/rtsp), with no create/update/delete/arm operations even though descriptions reference a PATCH for liveviews. Worse, two referenced tools are absent from the set (protect_create_rtsp_stream and protect_activate_relay_output), which will cause agent failures when followed.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    Exposes the Firewalla MSP API as tools for Claude Code and other MCP clients, enabling natural-language management of Firewalla boxes, alarms, rules, devices, flows, target lists, and trends with full read/write capabilities.
    19
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables read-only querying of a UniFi fleet via the Site Manager API and per-console connector proxy, allowing users to list hosts, sites, devices, ISP metrics, and live network clients through Claude.
    -