PF-WATCHDOG-001 MCP tools for AI assistant integration.
Transport: HTTP JSON-RPC at POST http://<device-ip>/api/v1/mcp.
For platform base tools (device info, relay, power, telemetry, config), see the Platform MCP Guide.
| Version | Date | Notes |
|---|---|---|
| 1.0 | 2026-02-11 | Initial release |
The Internet Watchdog registers 9 product-specific MCP tools on the device's MCP server. These are additive to the platform's base tools (get_device_info, get_status, get_relay, set_relay, etc.).
MCP (Model Context Protocol) allows AI assistants like Claude, ChatGPT, or GitHub Copilot to directly interact with the device — reading status, changing configuration, and triggering actions through natural language.
POST http://<device-ip>/api/v1/mcp
Content-Type: application/json
Standard JSON-RPC 2.0 over HTTP. No authentication. LAN-only.
Add to .vscode/mcp.json:
{
"servers": {
"watchdog": {
"type": "http",
"url": "http://<device-ip>/api/v1/mcp"
}
}
}
The AI assistant can then call watchdog tools directly.
| # | Tool | Input | Description |
|---|---|---|---|
| 1 | get_internet_status | — | Current connectivity state and timestamps |
| 2 | get_uptime_stats | — | Lifetime uptime percentage and outage counts |
| 3 | trigger_reboot | — | Manually reboot the router |
| 4 | get_event_history | — | Recent outages, reboots, and state changes |
| 5 | set_enabled | enabled | Enable or disable monitoring |
| 6 | force_ping | — | Immediate connectivity check with per-target results |
| 7 | get_watchdog_config | — | Read all configuration parameters |
| 8 | set_watchdog_config | partial config | Update configuration parameters |
| 9 | reset_stats | — | Zero all cumulative statistics |
All tool responses are returned as MCP content:
{
"content": [
{
"type": "text",
"text": "<JSON string>"
}
]
}
The text field contains a serialized JSON object. Examples below show the parsed inner JSON for clarity.
get_internet_statusReturns the current connectivity state, monitoring status, and timestamps of recent events.
None.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_internet_status",
"arguments": {}
}
}
{
"state": "monitoring",
"internet_up": true,
"enabled": true,
"relay": true,
"consecutive_fails": 0,
"reboot_count": 0,
"last_check": "2026-02-11T15:30:00Z",
"last_outage": null,
"last_reboot": null
}
| Field | Type | Description |
|---|---|---|
state | string | "monitoring", "grace_period", "rebooting", "post_reboot_grace", "cooldown", "max_retries_exceeded", or "disabled" |
internet_up | boolean | Whether the last ping round succeeded |
enabled | boolean | Master enable/disable switch |
relay | boolean | true = closed (power on), false = open (power off) |
consecutive_fails | integer | Current streak of failed ping rounds |
reboot_count | integer | Reboots in the current failure cycle |
last_check | string | null | ISO 8601 UTC of most recent ping check |
last_outage | string | null | ISO 8601 UTC of most recent outage |
last_reboot | string | null | ISO 8601 UTC of most recent router reboot |
"Is the internet working right now?"
get_uptime_statsReturns cumulative lifetime statistics — useful for understanding long-term reliability.
None.
{
"total_reboots": 3,
"total_outages": 3,
"total_monitoring_hours": 720.5,
"total_downtime_hours": 1.2,
"uptime_percent": 99.83
}
| Field | Type | Description |
|---|---|---|
total_reboots | integer | Lifetime router reboots (persisted in NVS) |
total_outages | integer | Lifetime outages detected |
total_monitoring_hours | float | Total hours the watchdog has been monitoring |
total_downtime_hours | float | Total hours of detected downtime |
uptime_percent | float | 100 × (1 − downtime / monitoring_time). Returns 100.0 if no monitoring time. |
"What's my internet uptime this month?"
trigger_rebootManually power-cycle the router. Opens the relay (power off), waits power_off_duration_s, then closes it (power on).
None.
{
"status": "rebooting"
}
{
"error": "Already rebooting"
}
Returned if the device is currently in rebooting or post_reboot_grace state.
manual_reboot event to history.last_reboot timestamp."Reboot my router"
get_event_historyReturns the event ring buffer — up to 16 most recent events, ordered oldest first.
None.
[
{
"event": "device_online",
"timestamp_ms": 1500,
"reboot_count": 0
},
{
"event": "outage_detected",
"timestamp_ms": 185000,
"reboot_count": 0
}
]
| Field | Type | Description |
|---|---|---|
event | string | Event type (see table below) |
timestamp_ms | integer | Milliseconds since device boot |
reboot_count | integer | Reboots at time of event |
| Event | Description |
|---|---|
device_online | Device booted |
outage_detected | Connectivity lost (threshold reached) |
reboot_started | Router power-cycle initiated |
internet_restored | Connectivity recovered |
max_retries_exceeded | All retry attempts exhausted |
scheduled_reboot | Daily scheduled reboot triggered |
manual_reboot | User-initiated reboot |
enabled | Monitoring turned on |
disabled | Monitoring turned off |
"Show me the recent outage history"
set_enabledEnable or disable watchdog monitoring.
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable or disable monitoring"
}
},
"required": ["enabled"]
}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_enabled",
"arguments": { "enabled": false }
}
}
{
"enabled": false,
"state": "disabled"
}
{
"error": "Missing boolean 'enabled' parameter"
}
monitoring state, resets consecutive_fails and reboot_count, pushes enabled event.disabled state, turns relay on (ensures router stays powered), pushes disabled event."Disable the watchdog temporarily"
force_pingForce an immediate connectivity check against all configured targets. Returns per-target results with round-trip times.
None.
{
"internet_up": true,
"targets": [
{ "ip": "8.8.8.8", "success": true, "rtt_ms": 12 },
{ "ip": "1.1.1.1", "success": true, "rtt_ms": 8 },
{ "ip": "208.67.222.222", "success": false, "rtt_ms": 0 }
]
}
| Field | Type | Description |
|---|---|---|
internet_up | boolean | true if at least one target responded |
targets[].ip | string | IPv4 address pinged |
targets[].success | boolean | Whether this target responded |
targets[].rtt_ms | integer | Round-trip time in ms (0 if failed) |
internet_up state and last_check timestamp.consecutive_fails or trigger state transitions."Ping the internet and show me the results"
get_watchdog_configRead all current configuration parameters.
None.
{
"enabled": true,
"ping_interval_s": 60,
"fail_threshold": 3,
"grace_before_reboot_s": 120,
"power_off_duration_s": 30,
"post_reboot_grace_s": 300,
"max_retries": 3,
"retry_cooldown_min": 30,
"scheduled_reboot": null,
"ping_targets": ["8.8.8.8", "1.1.1.1", "208.67.222.222"]
}
| Field | Type | Default | Range | Description |
|---|---|---|---|---|
enabled | boolean | true | — | Master monitoring switch |
ping_interval_s | integer | 60 | 30–300 | Seconds between ping rounds |
fail_threshold | integer | 3 | 2–10 | Consecutive failures before outage |
grace_before_reboot_s | integer | 120 | 0–600 | Wait before power cycle |
power_off_duration_s | integer | 30 | 10–120 | Router off duration |
post_reboot_grace_s | integer | 300 | 120–900 | Max wait for internet after reboot (exits early on success) |
max_retries | integer | 3 | 1–10 | Max power-cycle attempts |
retry_cooldown_min | integer | 30 | 10–120 | Minutes between retries |
scheduled_reboot | string | null | null | "HH:MM" or null | Daily reboot time |
ping_targets | string[] | ["8.8.8.8","1.1.1.1","208.67.222.222"] | 1–4 IPs | Ping targets |
"What are the current watchdog settings?"
set_watchdog_configUpdate one or more configuration parameters. Only fields present in arguments are changed. Changes are persisted to NVS immediately.
{
"type": "object",
"properties": {
"enabled": { "type": "boolean", "description": "Enable or disable monitoring" },
"ping_interval_s": { "type": "integer", "description": "Seconds between ping rounds", "minimum": 30, "maximum": 300 },
"fail_threshold": { "type": "integer", "description": "Consecutive failures before action", "minimum": 2, "maximum": 10 },
"grace_before_reboot_s": { "type": "integer", "description": "Wait seconds before power cycle", "minimum": 0, "maximum": 600 },
"power_off_duration_s": { "type": "integer", "description": "Seconds router stays off", "minimum": 10, "maximum": 120 },
"post_reboot_grace_s": { "type": "integer", "description": "Seconds to wait after reboot", "minimum": 120, "maximum": 900 },
"max_retries": { "type": "integer", "description": "Max reboots before giving up", "minimum": 1, "maximum": 10 },
"retry_cooldown_min": { "type": "integer", "description": "Minutes between retry attempts", "minimum": 10, "maximum": 120 },
"scheduled_reboot": { "type": "string", "description": "Daily reboot time as HH:MM (24h), or null to disable" },
"ping_targets": { "type": "array", "description": "Array of IPv4 addresses to ping, or null to reset to defaults", "items": { "type": "string" } }
},
"required": []
}
No fields are required — pass only what you want to change.
Change ping interval:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_watchdog_config",
"arguments": { "ping_interval_s": 120 }
}
}
Set daily reboot at 4 AM:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_watchdog_config",
"arguments": { "scheduled_reboot": "04:00" }
}
}
Update ping targets:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_watchdog_config",
"arguments": { "ping_targets": ["8.8.8.8", "1.1.1.1"] }
}
}
{
"changes_applied": 1,
"state": "monitoring"
}
| Error message | Condition |
|---|---|
"No parameters provided" | Empty or null arguments |
"<field> must be <min>–<max>" | Numeric value out of range |
"ping_targets must be an array" | Wrong type |
"ping_targets must have 1-4 entries" | Too many or zero targets |
"ping_targets entries must be non-empty strings" | Non-string element |
"ping_targets entry too long" | Entry exceeds 40 chars |
"ping_targets entry is not a valid IPv4 address" | Invalid IP |
"scheduled_reboot must be \"HH:MM\" or null" | Wrong type |
"scheduled_reboot must be \"HH:MM\" (00:00–23:59)" | Invalid time |
"Change the ping interval to 2 minutes and add Cloudflare DNS as a target"
reset_statsReset all cumulative statistics to zero — lifetime reboots, outages, monitoring time, and timestamps.
None.
{
"status": "stats_reset"
}
| Stat | Reset to |
|---|---|
total_reboots | 0 |
total_outages | 0 |
total_monitoring_hours | 0 |
total_downtime_hours | 0 |
uptime_percent | 100.0 |
last_check | null |
last_outage | null |
last_reboot | null |
"Reset the uptime statistics"
Error responses are returned as normal MCP content (not JSON-RPC errors):
{
"content": [
{
"type": "text",
"text": "{\"error\":\"Already rebooting\"}"
}
]
}
The AI assistant should check for an error field in the parsed response.
AI assistants discover available tools via the standard MCP tools/list method:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
This returns all tools (platform base + watchdog product) with their names, descriptions, and input schemas.
ISO 8601 UTC format: "2026-02-11T15:30:00Z". Returns null if the system clock hasn't synced (epoch before 2025-01-01).
Tool calls are processed sequentially. force_ping blocks while ICMP pings execute (up to 3 seconds per target).
One resource is registered but not yet implemented:
| URI | Name | MIME Type |
|---|---|---|
watchdog://status | watchdog_status | application/json |