Skip to content

Commit c68afef

Browse files
Sbussisoclaude
andcommitted
fix(mcp): correct UTC drift in recording-policy tool descriptions + list missing tools
Two real wire-check findings: 1. get_camera_recording_policy and set_camera_recording_policy still said "HH:MM, UTC" / "HH:MM 24-hour UTC" in their tool descriptions. Per-org timezone shipped in v0.1.43 — windows are interpreted in the org's configured timezone, not UTC. An AI agent reading the old description would convert wall-clock "8 AM Pacific" to "16:00" and write the wrong window. Both now say "interpreted in the org's configured timezone (NOT UTC) — pass exactly what the user said, do not convert." Also surfaced the modes_conflict invariant in the set description so the AI knows the error shape ahead of time. 2. McpPage public-facing TOOLS list was missing five tools that are actually live: list_incidents, get_incident, get_incident_snapshot, get_incident_clip (read), and attach_clip (write). Backed-into the list during the wire check after grepping every @mcp.tool(name=...) registration against the array. Wire check verified end-to-end against prod: 23 registered tools, all in the gating frozensets, 16 live-tested with real responses (view_camera returned a JPEG, get_incident_snapshot returned the previously stored evidence image, set_camera_recording_policy correctly 422'd on the mutual-exclusion path with {error:"modes_conflict"}). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 50f33fd commit c68afef

2 files changed

Lines changed: 16 additions & 6 deletions

File tree

backend/app/mcp/server.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,12 @@ def get_node(
750750
description=(
751751
"Return the recording policy for a specific camera: whether 24/7 "
752752
"continuous recording is on, whether scheduled recording is on, and "
753-
"the scheduled start/end times (HH:MM, UTC). Per-camera since "
754-
"v0.1.43 — replaces the previous org-level get_recording_settings. "
755-
"Use when the user asks 'is the garage cam recording right now?' "
756-
"or before filing an incident if it's relevant whether the moment "
757-
"was being recorded to disk on the CloudNode."
753+
"the scheduled start/end times (HH:MM, interpreted in the org's "
754+
"configured timezone — NOT UTC). Per-camera since v0.1.43 — "
755+
"replaces the previous org-level get_recording_settings. Use when "
756+
"the user asks 'is the garage cam recording right now?' or before "
757+
"filing an incident if it's relevant whether the moment was being "
758+
"recorded to disk on the CloudNode."
758759
),
759760
annotations={"readOnlyHint": True},
760761
)
@@ -783,7 +784,11 @@ def get_camera_recording_policy(camera_id: str) -> dict:
783784
"(or set to null) is left unchanged — pass only what you want to "
784785
"update. Use when the user asks 'turn on recording for the garage "
785786
"cam' or 'set scheduled recording on the front door cam from 18:00 "
786-
"to 06:00'. Times are HH:MM 24-hour UTC. Returns the new effective "
787+
"to 06:00'. Times are HH:MM 24-hour, interpreted in the org's "
788+
"configured timezone (NOT UTC) — pass exactly what the user said, "
789+
"do not convert. Mutual-exclusion invariant: continuous_24_7 and "
790+
"scheduled_recording can't both be true; the call returns "
791+
"{error: 'modes_conflict'} if you try. Returns the new effective "
787792
"policy. Per-camera since v0.1.43."
788793
),
789794
)

frontend/src/pages/McpPage.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@ const TOOLS = [
2626
{ name: "get_stream_logs", desc: "View stream access history" },
2727
{ name: "get_stream_stats", desc: "Get aggregated stream statistics" },
2828
{ name: "get_system_status", desc: "System overview: cameras, nodes, plan" },
29+
{ name: "list_incidents", desc: "List past incident reports (filter by status, severity, or camera)" },
30+
{ name: "get_incident", desc: "Read one incident in full — report body and evidence list" },
31+
{ name: "get_incident_snapshot", desc: "Fetch a snapshot JPEG previously attached to an incident" },
32+
{ name: "get_incident_clip", desc: "Metadata about a video clip previously attached to an incident" },
2933
{ name: "create_incident", desc: "Open a new AI-authored incident report", write: true },
3034
{ name: "add_observation", desc: "Append a text observation to an incident", write: true },
3135
{ name: "attach_snapshot", desc: "Capture a snapshot and attach it as evidence", write: true },
36+
{ name: "attach_clip", desc: "Save a clip from the recent live buffer as evidence", write: true },
3237
{ name: "update_incident", desc: "Change an incident's status, severity, or summary", write: true },
3338
{ name: "finalize_incident", desc: "Write the long-form incident report", write: true },
3439
{ name: "set_camera_recording_policy", desc: "Toggle a camera between continuous / scheduled / off (mutually exclusive)", write: true },

0 commit comments

Comments
 (0)