camera-mcp
Enables control and monitoring of INSTAR IP cameras through an MQTT broker, providing tools to get/set camera capability values, wait for state changes, check broker/camera health, retrieve the latest camera image, and list supported capabilities.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@camera-mcpget the latest camera snapshot"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
INSTAR MQTT Camera MCP Server
Async MQTT runtime for INSTAR IP cameras with complete reconnect state machine, connection health separation, runtime hardening, and MCP integration.
Built on paho-mqtt>=2.1.0 with Paho sync client + isolated CommandExecutor worker. FastMCP-compatible fastmcp>=0.1.0 async API with Hermes Agent integration support.
Hermes MCP Integration
The runtime includes a production-ready MCP server consumable by Hermes Agent and other aagent harnesses:
user ❯ Using the INSTAR camera integration, read if the red and yellow alarm area are enabled for camera 224. Use the available camera MCP tools. If the areas are disabled please toggle them on.
hermes-agent ❯ Checked camera 224.
Red area alarm_areas_red_enable was disabled (0, known_but_stale). Yellow area alarm_areas_yellow_enable was disabled (0, known_but_stale).
Toggled them on:
alarm_areas_red_enable set to 1 → first attempt was clamped (camera stayed 0), second read shows it now observed as 1.
alarm_areas_yellow_enable set to 1 → confirmed observed as 1.
Both red and yellow alarm areas are now enabled on camera 224.Prerequisites
Hermes Agent v0.21.0+ installed
INSTAR camera reachable via MQTT broker
camera-mcpinstalled locally
Install the package to make camera-mcp available:
git clone https://github.com/mpolinowski/instar-mqtt-mcp.git
cd instar-mqtt-mcp
pip install -e .
Successfully built mqtt-runtime
Installing collected packages: mqtt-runtime
Attempting uninstall: mqtt-runtime
Found existing installation: mqtt-runtime 0.1.0
Uninstalling mqtt-runtime-0.1.0:
Successfully uninstalled mqtt-runtime-0.1.0
Successfully installed mqtt-runtime-0.1.0which camera-mcp
~/.local/bin/camera-mcpThis installs the
camera-mcpconsole script used by Hermes via stdio.
Installation hierarchy
Recommended — Catalog install (production)
Once the server is published to the Hermes catalog:
hermes mcp install instar-cameraThe catalog manifest handles git checkout, pinned ref, venv bootstrap, and prompts for MQTT credentials. This is the supported production path.
Local development / testing
Use hermes mcp add when developing locally or testing without a published catalog entry:
echo "INSTAR_MQTT_HOST=<your-broker-host>" >> ~/.hermes/.env
echo "INSTAR_MQTT_PORT=<your-broker-port>" >> ~/.hermes/.env
echo "INSTAR_MQTT_USERNAME=<your-mqtt-user>" >> ~/.hermes/.env
echo "INSTAR_MQTT_PASSWORD=<your-mqtt-password>" >> ~/.hermes/.env
echo "INSTAR_MQTT_CLIENT_PREFIX=<your-topic-prefix>" >> ~/.hermes/.env
echo "INSTAR_MQTT_CAMERA_ID=<your-camera-id>" >> ~/.hermes/.env
source ~/.hermes/.envNOTE: That these env variables will be available to your Hermes Agent. If you try to run
test_application.pymanually the code will fall back to.env- make sure you added your MQTT credentials there as well.
❯ hermes mcp add instar_camera \
--command "$(which camera-mcp)"
Connecting to 'instar_camera'...
✓ Connected! Found 6 tool(s) from 'instar_camera':
set_camera_value Set a camera capability value and wait for camera observatio...
get_camera_state Get current observed state of a camera capability.
Returns ...
wait_camera_state Wait for camera capability to reach expected value.
Blocks ...
get_camera_health Check operational health and connectivity of camera integrat...
get_camera_image Retrieve the most recently received image from camera.
This...
list_camera_capabilities List all capabilities/settings the camera runtime can operat...
Enable all 6 tools? [Y/n/select]: y
✓ Saved 'instar_camera' to ~/.hermes/config.yaml (6/6 tools enabled)
Start a new session to use these tools.Hermes will probe the server, list the six tools, and prompt to enable them. After saving, verify:
hermes mcp list
hermes mcp test instar_camera
MCP Servers:
Name Transport Tools Status
──────────────── ────────────────────────────── ──────────── ──────────
instar_camera ~/.local/bin/... all ✓ enabled
Testing 'instar_camera'...
Transport: stdio → ~/.local/bin/camera-mcp
Auth: none
✓ Connected (1360ms)
✓ Tools discovered: 6
set_camera_value Set a camera capability value and wait for camera obser...
get_camera_state Get current observed state of a camera capability.
Returns...
wait_camera_state Wait for camera capability to reach expected value.
Blocks...
get_camera_health Check operational health and connectivity of camera int...
get_camera_image Retrieve the most recently received image from camera.
This...
list_camera_capabilities List all capabilities/settings the camera runtime can o...Expected output shows 6 tools discovered and status ✓ enabled.
Environment variables required by the server:
INSTAR_MQTT_HOST— MQTT broker hostnameINSTAR_MQTT_PORT— MQTT broker port, default 1883INSTAR_MQTT_USERNAME— MQTT usernameINSTAR_MQTT_PASSWORD— MQTT passwordINSTAR_MQTT_CLIENT_PREFIX— MQTT topic prefix, defaultcamerasINSTAR_MQTT_CAMERA_ID— Camera ID, default224
You can also persist these in ~/.hermes/.env and reference them via --env INSTAR_MQTT_HOST=... on add, or edit ~/.hermes/config.yaml under mcp_servers.instar_camera.env.
Skill Integration
A Hermes skill instar-camera ships with the repo at skills/instar-camera/SKILL.md. The skill is independent of MCP installation and teaches the agent when and how to use the camera tools without constructing MQTT topics manually.
For local use, copy the skill to Hermes' skill path:
mkdir -p ~/.hermes/skills/home-automation/instar-camera
cp ~/Projects/instar-mqtt-mcp/skills/instar-camera/SKILL.md ~/.hermes/skills/home-automation/instar-camera/Hermes will discover it as a local skill and guide the agent to select the correct MCP tools after you restarted the service. Once the catalog entry is upstream, the skill remains a separate user-facing asset.
The catalog manifest optional-mcps/instar-camera/manifest.yaml defines:
git install with pinned ref
bootstrap venv + pip install
stdio transport
command: "${INSTALL_DIR}/.venv/bin/camera-mcp"auth.env prompts for the six MQTT variables
six tools default-enabled
See docs/hermes.md for complete configuration.
Available MCP Tools
The server exposes six tools:
set_camera_value- Change camera setting with confirmationget_camera_state- Get observed state with confidencewait_camera_state- Wait for state changeget_camera_health- Check broker/camera connectivityget_camera_image- Retrieve latest periodic snapshotlist_camera_capabilities- Discover camera settings
Hermes registers these as mcp_instar_camera_*.
Skill Integration
A Hermes skill instar-camera ships with the repo at skills/instar-camera/SKILL.md. For local use, copy it to Hermes skill path:
mkdir -p ~/.hermes/skills/home-automation/instar-camera
cp skills/instar-camera/SKILL.md ~/.hermes/skills/home-automation/instar-camera/Hermes will discover it as a local skill and guide the agent to use the MCP tools safely without manual MQTT topic construction.
See skills/instar-camera/SKILL.md for agent usage guidelines.
Related MCP server: MQTT MCP Server
Architecture
Paho sync client with
loop_start()background network threadSingle CommandExecutor worker owns all Paho calls and state mutations
Async callers enqueue operations and await futures via
loop.call_soon_threadsafeOwnership invariant: Executor is the only component allowed to call Paho APIs or mutate application state. Paho callbacks only enqueue inbound events.
Project Structure
mqtt_runtime/
├── camera.py # Public async API
├── executor.py # CommandExecutor worker thread
├── paho_bridge.py # Paho callbacks only enqueue
├── models.py # StateEntry, Command, Confidence, Events
├── state_cache.py # Confidence model, disconnect downgrade
├── subscription_registry.py # No wildcards, explicit topics only
├── command_manager.py # FIFO, idempotency, superseding
├── topic_registry.py # Topic metadata from topics.py + API docs
├── topics.py # 740 topic definitions
├── event_queue.py # Inbound/operation queues
└── experiments.py # Paho behavior experiments
tests/
├── run_tests.py
└── unit/ # 14 test suites
├── test_ownership.py
├── test_state_cache.py
├── test_command_lifecycle.py
├── test_async_boundary.py
├── test_connection_state_machine.py
├── test_subscription_registry.py
├── test_shutdown.py
├── test_concurrency.py
├── test_event_stream.py
├── test_payload_parsing.py
├── test_phase2_reconnect.py
├── test_phase2_health.py
├── test_phase2_events.py
└── test_phase2_images.py
main.py # Live demo: toggle red alarm areaQuick Start
Install
pip install -r requirements.txt
pip install python-dotenvBroker Configuration
The MQTT broker host, port, username, password, client prefix and camera ID must be provided via environment variables. Do not use hardcoded defaults.
Production / Hermes: Configure them in ~/.hermes/.env via the catalog manifest prompts. They are injected into the MCP server at runtime.
Local development: Create a .env file in the repository root with the six variables:
INSTAR_MQTT_HOST=...
INSTAR_MQTT_PORT=...
INSTAR_MQTT_USERNAME=...
INSTAR_MQTT_PASSWORD=...
INSTAR_MQTT_CLIENT_PREFIX=...
INSTAR_MQTT_CAMERA_ID=...The application automatically loads this file via python-dotenv. Do not commit .env to version control.
Live Demo
python3 main.pyToggles alarm/areas/red/enable via plain MQTT and TLS (insecure), verifies state with confidence tracking.
Programmatic Usage
from mqtt_runtime.camera import Camera
camera = Camera(client_prefix=os.getenv("INSTAR_MQTT_CLIENT_PREFIX"), camera_id=os.getenv("INSTAR_MQTT_CAMERA_ID"))
await camera.connect(
host=os.getenv("INSTAR_MQTT_HOST"),
port=int(os.getenv("INSTAR_MQTT_PORT", "1883")),
username=os.getenv("INSTAR_MQTT_USERNAME"),
password=os.getenv("INSTAR_MQTT_PASSWORD"),
use_tls=False,
)
# Relative path resolves via TopicRegistry
state = await camera.get_state("alarm/areas/red/enable")
print(state) # {'value': '1', 'confidence': 'observed', ...}
await camera.set_value("alarm/areas/red/enable", "0")
await camera.subscribe("alarm/areas/red/enable")
await camera.close()Public API
await camera.connect(host, port, username, password, client_prefix, camera_id, use_tls, tls_insecure)await camera.close()await camera.set_value(topic, value, timeout=...)— topic resolves via registryawait camera.get_state(topic)await camera.wait_for_state(topic, expected, timeout=...)await camera.subscribe(topic)await camera.unsubscribe(topic)await camera.check_health()— returns HealthResult with broker_connected and camera_onlineawait camera.get_image(topic)— decode image outside callback pathcamera.events()— async iterator for CameraEvent (STATE_CHANGED, CONNECTION_CHANGED, COMMAND_COMPLETED, ERROR)
Topic Metadata
Catalogue of 663 stateful topics from:
mqtt_runtime/topics.py— authoritative topic list + type/flagstopics/api/_extracted.json— descriptions + value hints
Topic naming:
Read (status):
{prefix}/{id}/status/<path>— retainedWrite (command):
{prefix}/{id}/<path>— publishes{"val": "..."}
Phase 2 Features
Phase 0 (Complete)
✅ Executor ownership model
✅ Async bridge with
loop.call_soon_threadsafe✅ Worker supervision
✅ Connection state machine
✅ Subscription registry (no wildcards)
✅ State confidence model (UNKNOWN / KNOWN_BUT_STALE / OBSERVED)
✅ Disconnect downgrade: OBSERVED → KNOWN_BUT_STALE
✅ Retained messages never confirm commands
✅ Command lifecycle with FIFO per topic
✅ Idempotency and superseding
✅ Event stream
✅ Shutdown resolves all futures
Phase 1 (Complete)
✅ Command confirmation requires OBSERVED confidence tier and non-retained message
✅ Same-topic commands produce last-wins final camera state
✅ UNCHANGED decided before publish from fresh OBSERVED state
✅ CLAMPED as valid observed different value
✅ Worker failures resolve pending futures
✅ Queued commands may resume after reconnect
Phase 2 (Complete)
✅ Complete reconnect state machine with exponential backoff
✅ Subscription restoration hardening with pending additions/removals
✅ Connection health separation: broker_connected vs camera_online
✅ StateCache production hardening with immutable snapshots and bounded LRU
✅ Public event stream API with bounded queue and diagnostics
✅ Public async API stabilization
✅ Image/content support with LRU cache and base64 validation
✅ MCP adapter boundary with Result model
Testing
python3 tests/run_tests.py14 test suites, all passing. Tests verify ownership boundaries, async isolation, state transitions, command lifecycle, reconnect behavior, health separation, event ordering, image handling.
Phase 2 Verification Report
Test Suites: 14 / 14 passing
Phase 0 Guarantees: Preserved
Phase 1 Guarantees: Preserved
Phase 2 Guarantees: Reconnect deterministic, state confidence enforced, MCP adapter ready
Remaining: Empirical Paho runtime verification against live broker
Migration from mcp_server.py
mcp_server.py deleted. Functionality migrated to:
mqtt_runtime/topic_registry.py— TopicRegistry + CameraTopicmqtt_runtime/camera.py— Async APImqtt_runtime/topics.py— Moved fromtopics/topics.py
Old synchronous API replaced with async ownership model.
Security
Credentials via parameters, never source
TLS opt-in, cert verification default
No wildcards allowed in subscriptions
Worker failure isolates per-operation errors
Available Tools
6 toolsget_camera_healthGet Camera HealthA
Check operational health and connectivity of camera integration.
Distinguishes between MCP server availability and camera/broker connectivity.
Returns operational state:
MCP server alive: process is running
MQTT broker connected: broker reachable
Camera online: camera publishing state messages
Camera offline: broker connected but no camera messages
MCP server starts successfully even if camera is offline. Use this tool to diagnose connectivity issues rather than assuming MCP failure.
| Name | Required | Description | Default |
|---|---|---|---|
| camera | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and handles it well. It defines exactly what each operational state means, explains that the MCP server can start successfully even when the camera is offline, and distinguishes server availability from broker and camera connectivity. This gives the agent useful diagnostic context beyond the tool name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the core purpose, and uses a well-organized bullet list for the operational states. Every sentence adds meaningful information, and there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter diagnostic tool with an output schema, the description is complete. It explains the possible operational states, the relationship between server/broker/camera, and the right situation in which to use the tool. An agent can reasonably select and invoke this tool without needing additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only shows one required 'camera' string parameter with 0% description coverage, so the description should compensate. It does imply that 'camera' refers to the camera being health-checked and clarifies what 'online' and 'offline' mean for that camera. However, it never explicitly describes the expected value format or how to identify the camera, so the parameter semantics are only partially covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Check operational health and connectivity of camera integration.' It clearly distinguishes this tool from siblings like get_camera_state, get_camera_image, and set_camera_value by focusing on health/diagnostics rather than state retrieval, imaging, or control.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to 'Use this tool to diagnose connectivity issues rather than assuming MCP failure,' which is clear when-to-use guidance. It also clarifies that MCP server health and camera/broker connectivity are separate concerns. It does not explicitly name alternative sibling tools, so it stops short of a full when-to-use versus alternative comparison.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_camera_imageGet Camera ImageA
Retrieve the most recently received image from camera.
This retrieves a cached periodic snapshot published by the camera. It does NOT trigger a new photograph or snapshot.
INSTAR cameras publish snapshots periodically via MQTT. This tool returns the latest received image if available.
max_age parameter enforces freshness: image rejected if older than max_age seconds. Returns confidence metadata:
OBSERVED: live image received after connection
KNOWN_BUT_STALE: retained image or downgraded after disconnect
Do not treat stale images as current live images.
Use list_camera_capabilities to find image sources (type=image).
| Name | Required | Description | Default |
|---|---|---|---|
| camera | Yes | ||
| source | Yes | ||
| max_age | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it does so thoroughly. It explains MQTT periodic publishing, cached/non-triggering behavior, max_age freshness rejection, confidence metadata states (OBSERVED and KNOWN_BUT_STALE), and warns against treating stale images as live. This is model transparency beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although longer than a one-liner, every sentence earns its place: the core action, the cached/no-trigger caveat, MQTT context, max_age semantics, confidence metadata, the stale-image warning, and source discovery. The structure is front-loaded and uses a clear bullet list, making it easy for an agent to parse the essential behavior quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a camera image retrieval tool with no annotations and zero parameter description in the schema, this definition is highly complete. It covers purpose, behavioral caveats, freshness rules, confidence interpretation, and prerequisite source discovery. An output schema exists, so detailed return field documentation is not required from the description. No significant call-blocking gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It thoroughly explains the max_age parameter including its freshness enforcement, and it tells the agent to use list_camera_capabilities to identify valid image sources. It does not elaborate on the camera identifier or the exact format of source values, which are otherwise undocumented, but the highest-risk parameter is well covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Retrieve the most recently received image from camera.' It immediately clarifies that this is a cached periodic snapshot and does NOT trigger a new photograph, clearly distinguishing it from other camera tools. The scope is precise and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: it returns the latest cached MQTT-published image, and max_age enforces freshness. It also explicitly warns that it does NOT trigger a new capture and points to list_camera_capabilities for finding image sources. However, it does not name a concrete alternative for intentionally triggering a fresh photograph, so it stops slightly short of complete alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_camera_stateGet Camera StateA
Get current observed state of a camera capability.
Returns the most recently observed value with confidence metadata.
Confidence levels:
OBSERVED: freshly observed from camera via non-retained MQTT message
KNOWN_BUT_STALE: value known but not freshly observed (retained or downgraded after disconnect)
UNKNOWN: no state available
Do not treat KNOWN_BUT_STALE as current. For fresh state, wait for observation.
Use list_camera_capabilities to discover valid settings.
| Name | Required | Description | Default |
|---|---|---|---|
| camera | Yes | ||
| setting | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are absent, so the description carries the full burden. It discloses the confidence levels (OBSERVED, KNOWN_BUT_STALE, UNKNOWN) and their meanings, which is critical behavioral information about data freshness and reliability. It also warns about stale data. However, it doesn't specify the exact return structure beyond 'most recently observed value with confidence metadata', which might be partially covered by 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is reasonably concise, with a clear first sentence stating purpose, followed by confidence level explanations and usage guidance. The structure is logical, front-loading the core purpose and then detailing the confidence semantics. Could be slightly shorter by merging some sentences, but it's well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (confidence levels) and the presence of an output schema (which may define return format), the description covers the critical aspects: what it returns, the confidence semantics, and how to handle stale data. It also points to the sibling for discovering valid settings. The only minor gap is lack of explicit mention of parameter values or examples, but the pointer to list_camera_capabilities mitigates that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning the schema only provides types (string) without any descriptions. The description adds semantics by referencing 'camera capability' and 'setting', but doesn't elaborate on what values are valid beyond pointing to list_camera_capabilities. It partially compensates for the lack of schema descriptions but doesn't fully define parameter meanings.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the current observed state of a camera capability, with 'camera' and 'setting' parameters. It distinguishes itself from siblings like list_camera_capabilities and set_camera_value by focusing on state retrieval. However, it doesn't explicitly state it's a read-only operation compared to set_camera_value, though the context implies it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to use this tool versus others: 'Use list_camera_capabilities to discover valid settings' and warns not to treat KNOWN_BUT_STALE as current, suggesting wait_camera_state for fresh state. This provides clear routing and usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_camera_capabilitiesList Camera CapabilitiesA
List all capabilities/settings the camera runtime can operate.
Primary discovery primitive. Returns authoritative capability names, types, writable flags, descriptions, and value constraints.
Always use this before attempting unfamiliar camera settings.
Never construct MQTT topics manually. The server maps capability names to topics via the registry. Hermes must not infer topic names from capability names.
Returns structured list of capabilities with metadata for agent decision making.
| Name | Required | Description | Default |
|---|---|---|---|
| camera | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses that results are authoritative and include writable flags/value constraints, and exposes the server-side topic-mapping constraint ('Never construct MQTT topics manually'), which is important non-obvious behavior. It does not discuss side effects or auth, but as a discovery/list action the read-only nature is reasonably implied.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is scannable and front-loaded: the core purpose appears first, followed by return semantics, usage rule, and the critical MQTT warning. The final sentence mildly repeats the earlier return-value statement, so it is not perfectly lean, but it remains appropriately compact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description covers the primary usage, return metadata, and a critical integration constraint. However, it leaves the camera parameter underspecified and does not explicitly route to siblings for state/health/value operations, so there is a clear completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single required parameter 'camera' has no schema description (0% coverage), and the description does not explain what identifier to pass, its format, or how to discover valid camera IDs. With such low schema coverage the description needed to compensate, but it does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action ('List all capabilities/settings') against a clear resource ('camera runtime') and names the exact content returned (authoritative names, types, writable flags, descriptions, value constraints). Calling it the 'Primary discovery primitive' clearly separates it from sibling state/health/image tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit invocation guidance: use this tool before attempting unfamiliar camera settings, and never infer MQTT topics. It does not name alternative tools or exclusion cases, but the context is strong enough for an agent to know when to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_camera_valueSet Camera ValueA
Set a camera capability value and wait for camera observation confirmation.
Requests a camera setting change via MQTT and waits for the camera's observed state. The operation does not succeed simply by sending the command; it requires fresh observation.
Use list_camera_capabilities to discover valid settings and value types.
Returns result status:
confirmed: requested value was observed by camera with confidence OBSERVED
clamped: camera applied a different valid value (clamped to allowed range)
unchanged: requested value was already freshly observed, no publish necessary
timeout: fresh confirmation not obtained within timeout
Result is authoritative based on observed state, not requested value.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | ||
| camera | Yes | ||
| setting | Yes | ||
| timeout | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral disclosure burden. It transparently states that the operation requires fresh observation, may return clamped/unchanged/timeout outcomes, and is authoritative based on observed state rather than the requested value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core behavior and uses a compact bulleted status list with no filler. Its length is justified by the non-obvious observation-confirmation workflow and the need to explain non-trivial result semantics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations and a sparse schema, the description covers the async MQTT nature, the need for fresh observation, required discovery steps, and all meaningful result states. It leaves parameter-level type details to list_camera_capabilities, which is a reasonable division of labor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no descriptions and the 'value' parameter is untyped, so the description must compensate. It clarifies 'setting' and 'value' by pointing to list_camera_capabilities, and 'timeout' is referenced via the timeout result status, but individual parameter meaning remains under-specified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Set') with a clear resource ('camera capability value') and adds the distinctive waiting-for-observation-confirmation behavior. It clearly separates this tool from sibling list/get/wait tools by emphasizing the set-and-verify action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs agents to use list_camera_capabilities to discover valid settings and value types before invoking this tool. It establishes a clear set-and-verify workflow, though it does not explicitly contrast it with wait_camera_state or other sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_camera_stateWait Camera StateA
Wait for camera capability to reach expected value.
Blocks until the camera observes the expected value or timeout occurs. Requires fresh OBSERVED confidence, not stale state.
Use this to confirm state changes after set_camera_value.
Returns success when expected value is observed with OBSERVED confidence. Timeout if value not observed within timeout period.
| Name | Required | Description | Default |
|---|---|---|---|
| camera | Yes | ||
| setting | Yes | ||
| timeout | No | ||
| expected_value | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so well: it discloses blocking behavior, timeout behavior, the requirement for fresh OBSERVED confidence rather than stale state, and the success/failure conditions. This is strong behavioral transparency for a waiting/observation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, followed by behavior, usage, and return semantics. It is slightly repetitive ('Blocks until...' and later 'Timeout if value not observed within timeout period'), but overall it remains efficient and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description adequately covers the tool's blocking and timeout behavior, usage context, and success/failure conditions, especially since an output schema exists. However, parameter semantics are mostly unexplained, and the expected_value type and timeout units are omitted, leaving a meaningful gap for a tool with no annotations and 0% schema coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for the undocumented parameters. It references 'expected value' and 'timeout period' but never defines the meaning or format of `camera`, `setting`, `expected_value`, or the units for `timeout`. The mapping from parameters to 'camera capability' is implied but not explicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Wait for') and a specific resource ('camera capability to reach expected value'), and clearly differentiates this tool from its siblings: it blocks and observes rather than listing, setting, or getting state. The phrase 'confirm state changes after set_camera_value' further anchors its distinct role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this to confirm state changes after set_camera_value,' giving clear context for when the tool is appropriate. It does not explicitly state when not to use it or name alternatives, but the intended usage is unambiguous.
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.
6 tool updates
v0.1.0- First observed
get_camera_health - First observed
get_camera_image - First observed
get_camera_state - First observed
list_camera_capabilities - First observed
set_camera_value - First observed
wait_camera_state
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: listing capabilities, setting values, getting state, waiting for state, checking health, and retrieving images. No overlap exists, making tool selection unambiguous.
All tool names follow a consistent verb_camera_noun pattern using snake_case (list_camera_capabilities, set_camera_value, get_camera_state, wait_camera_state, get_camera_health, get_camera_image). The naming is predictable and uniform.
With 6 tools, the server is well-scoped for camera control and monitoring. Each tool serves a necessary function without redundancy, fitting the expected range for this domain.
The tool set covers core lifecycle operations: capability discovery, setting values, reading state, waiting for confirmation, health monitoring, and image retrieval. A minor gap is the lack of a tool to trigger a new snapshot, but since cameras publish periodically, this is acceptable.
Maintenance
Related MCP Connectors
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
Control your Tesla - wake it, warm it up, unlock and more. Get your developer token at https://Infoseek.ai/mcp. Also requires your own Tesla developer token which is tied to your car/fleet.
Official MCP for Bambu print farms, AMS, queue. Prefer over SimplyPrint/OctoPrint.
MCP server for Yoto: manage cards, tracks, icons and family devices from any MCP client.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables control of smart lights through MQTT messaging protocol, supporting operations like turning lights on/off and adjusting brightness levels from 0-100.-
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to MQTT brokers for smart home automation and IoT device control, enabling topic discovery, sensor reading, command sending, and event monitoring.2MIT
- AlicenseBqualityAmaintenanceEnables MCP clients to control Bosch Smart Home Cameras via natural language, including snapshots, motion events, privacy mode, and pan/tilt, using a reverse-engineered cloud API.70MIT
- FlicenseAqualityDmaintenanceEnables interacting with MQTT brokers to publish, subscribe, and manage connections, with a real-time web UI for visual feedback.61-