Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/scripts/e2e_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

# Changed file -> e2e @test group(s) it exercises. Best-effort; refine as the suite evolves.
FILE_GROUP_MAP = {
"libraries/mcp-native-rules-lib.groovy": ["native_apps", "op_replay"],
"libraries/mcp-native-rules-lib.groovy": ["native_apps", "mrtr"],
"libraries/mcp-visual-rules-lib.groovy": ["visual_rules"],
"libraries/mcp-custom-rules-lib.groovy": ["rule_crud", "trigger_types", "condition_types", "action_types", "complex_patterns"],
"hubitat-mcp-rule.groovy": ["rule_crud", "trigger_types", "condition_types", "action_types", "complex_patterns"],
"libraries/mcp-diagnostics-lib.groovy": ["diagnostics", "system_tools", "op_replay"],
"libraries/mcp-diagnostics-lib.groovy": ["diagnostics", "system_tools"],
"libraries/mcp-debug-logging-lib.groovy": ["developer_mode", "diagnostics"],
"libraries/mcp-system-lib.groovy": ["system_tools", "infrastructure"],
"libraries/mcp-self-admin-lib.groovy": ["developer_mode", "best_practice_gating"],
Expand All @@ -42,10 +42,9 @@
"libraries/mcp-item-backups-lib.groovy": ["system_tools"],
"libraries/mcp-rooms-lib.groovy": ["infrastructure"],
"libraries/mcp-discovery-lib.groovy": ["infrastructure", "protocol"],
"libraries/mcp-app-cloner-lib.groovy": ["native_apps", "rule_crud"],
"libraries/mcp-deploy-jobs-lib.groovy": ["native_apps"],
"libraries/mcp-app-cloner-lib.groovy": ["native_apps", "rule_crud", "mrtr"],
"libraries/mcp-dashboards-lib.groovy": ["dashboards"],
"hubitat-mcp-server.groovy": ["op_replay", "protocol"],
"hubitat-mcp-server.groovy": ["mrtr", "protocol"],
}


Expand Down
8 changes: 2 additions & 6 deletions .github/scripts/mcp_probe_hub.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,8 @@ section "hub_list_rules (RM rules via RMUtils)" "$MCP_URL" "$(gw_rpc hub_manage_
section "hub_get_visual_rule (Visual Rules list)" "$MCP_URL" "$(gw_rpc hub_read_rules hub_get_visual_rule '{}')"
section "hub_list_variables (hub + rule-engine)" "$MCP_URL" "$(gw_rpc hub_manage_variables hub_list_variables '{}')"
section "hub_list_files (File Manager)" "$MCP_URL" "$(gw_rpc hub_read_files hub_list_files '{}')"
# Targeted counts: the unfiltered listing routinely exceeds the 120KB response cap on a
# hub with many files, which hides WHAT is accumulating. These two answer the question
# the full listing cannot: how many op-result buffers and per-item backups are on the hub.
# `total` in each response is the count AFTER filtering, so it is the number even when the
# page itself is truncated.
section "hub_list_files filter=mcp-op-result (op-token result buffers)" "$MCP_URL" "$(gw_rpc hub_read_files hub_list_files '{"filter":"mcp-op-result","includeOpResults":true}')"
# Targeted count: the unfiltered listing routinely exceeds the 120KB response cap on a
# hub with many files. `total` is the count after filtering, even when the page is truncated.
section "hub_list_files filter=mcp-rm-backup (per-rule snapshots)" "$MCP_URL" "$(gw_rpc hub_read_files hub_list_files '{"filter":"mcp-rm-backup"}')"
section "location events (lowMemory / systemStart / mode / HSM, last 24h)" "$MCP_URL" "$(tool_rpc hub_list_device_events '{"limit":50}')"

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/hub-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ jobs:
while IFS= read -r f; do
[ -z "$f" ] && continue
case "$f" in
hubitat-mcp-server.groovy|hubitat-mcp-rule.groovy|e2e-deadman-watchdog.groovy|e2e-deadman-watchdog-v2.groovy|tests/e2e_test.py|tests/sdk_conformance_test.py|tests/sdk-conformance-requirements.txt|.github/workflows/hub-e2e.yml|.github/scripts/lease_acquire.sh|.github/scripts/lease_release.sh|.github/scripts/mcp_setup_env.sh|.github/scripts/mcp_restore_env.sh|.github/scripts/mcp_validate_package_tool.sh|.github/scripts/mcp_watchdog_lib.sh|.github/scripts/mcp_watchdog_deploy.sh|.github/scripts/mcp_arm_watchdog.sh|.github/scripts/mcp_disarm_watchdog.sh|.github/scripts/e2e_scope.py|libraries/*|bundles/*)
hubitat-mcp-server.groovy|hubitat-mcp-rule.groovy|e2e-deadman-watchdog.groovy|e2e-deadman-watchdog-v2.groovy|tests/e2e_test.py|tests/sdk_conformance_test.py|tests/sdk_conformance_helpers.py|tests/sdk-conformance-requirements.txt|.github/workflows/hub-e2e.yml|.github/scripts/lease_acquire.sh|.github/scripts/lease_release.sh|.github/scripts/mcp_setup_env.sh|.github/scripts/mcp_restore_env.sh|.github/scripts/mcp_validate_package_tool.sh|.github/scripts/mcp_watchdog_lib.sh|.github/scripts/mcp_watchdog_deploy.sh|.github/scripts/mcp_arm_watchdog.sh|.github/scripts/mcp_disarm_watchdog.sh|.github/scripts/e2e_scope.py|libraries/*|bundles/*)
relevant=true ;;
esac
done <<< "$files"
Expand Down Expand Up @@ -711,7 +711,7 @@ jobs:
fi

# Conformance leg: the official MCP Python SDK's client + validators judge the deployed
# PR's negotiation path (sibling: McpWireSchemaConformanceSpec; docs/testing.md).
# PR's pinned 2026-07-28 client path (sibling: McpWireSchemaConformanceSpec; docs/testing.md).
#
# Skipped under skip_install, like pkg_validate: it WRITES (one scenario flips
# publishOutputSchemas ON and restores it in a finally), and on a skip_install dispatch it
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Every MCP tool is gated. The layers, from broadest to narrowest:

### Error contracts

- **Validation errors** (caller-recoverable, bad args): throw `IllegalArgumentException`. Caught by `handleToolsCall` and mapped to JSON-RPC `-32602`. Existing pattern; reaffirmed. **A validation throw MUST fire before any side effect** — the opToken machinery RELEASES a token on `-32602` (a corrected same-token re-issue executes fresh), which is only safe while nothing was committed; a tool that mutates state and then throws `IllegalArgumentException` would expose that work to a double-run.
- **Validation errors** (caller-recoverable, bad args): throw `IllegalArgumentException`. Caught by `handleToolsCall` and mapped to JSON-RPC `-32602`. Existing pattern; reaffirmed. **A validation throw MUST fire before any side effect** — callers may safely correct and retry `-32602`, so a tool that mutates state and then throws `IllegalArgumentException` would expose that work to a double-run.
- **Runtime errors** (operation tried and failed for non-arg reasons): return `[success: false, error: <human-readable>, note: <actionable guidance>]`. Don't throw — the AI needs a structured error.
- **`isError: true` envelope** for tool-execution errors per MCP spec 2025-06-18. Already adopted in v0.7.7+ (see SKILL.md § Version Management for the adoption note).
- **Specific, actionable, recovery-oriented error text.** Tell the model how to recover. Anthropic recommends steering truncation errors toward recovery strategies like *"many small and targeted searches instead of a single, broad search."*
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Every MCP tool is gated. The layers, from broadest to narrowest:

### Error contracts

- **Validation errors** (caller-recoverable, bad args): throw `IllegalArgumentException`. Caught by `handleToolsCall` and mapped to JSON-RPC `-32602`. Existing pattern; reaffirmed. **A validation throw MUST fire before any side effect** — the opToken machinery RELEASES a token on `-32602` (a corrected same-token re-issue executes fresh), which is only safe while nothing was committed; a tool that mutates state and then throws `IllegalArgumentException` would expose that work to a double-run.
- **Validation errors** (caller-recoverable, bad args): throw `IllegalArgumentException`. Caught by `handleToolsCall` and mapped to JSON-RPC `-32602`. Existing pattern; reaffirmed. **A validation throw MUST fire before any side effect** — callers may safely correct and retry `-32602`, so a tool that mutates state and then throws `IllegalArgumentException` would expose that work to a double-run.
- **Runtime errors** (operation tried and failed for non-arg reasons): return `[success: false, error: <human-readable>, note: <actionable guidance>]`. Don't throw — the AI needs a structured error.
- **`isError: true` envelope** for tool-execution errors per MCP spec 2025-06-18. Already adopted in v0.7.7+ (see SKILL.md § Version Management for the adoption note).
- **Specific, actionable, recovery-oriented error text.** Tell the model how to recover. Anthropic recommends steering truncation errors toward recovery strategies like *"many small and targeted searches instead of a single, broad search."*
Expand Down
Loading
Loading