Internet Watchdog — MCP Integration Guide

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.

VersionDateNotes
1.02026-02-11Initial release


Overview

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.

Transport

POST http://<device-ip>/api/v1/mcp
Content-Type: application/json

Standard JSON-RPC 2.0 over HTTP. No authentication. LAN-only.

VS Code Configuration

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.

Tools at a Glance

#ToolInputDescription
1get_internet_statusCurrent connectivity state and timestamps
2get_uptime_statsLifetime uptime percentage and outage counts
3trigger_rebootManually reboot the router
4get_event_historyRecent outages, reboots, and state changes
5set_enabledenabledEnable or disable monitoring
6force_pingImmediate connectivity check with per-target results
7get_watchdog_configRead all configuration parameters
8set_watchdog_configpartial configUpdate configuration parameters
9reset_statsZero all cumulative statistics

Response format

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_status

Returns the current connectivity state, monitoring status, and timestamps of recent events.

Input

None.

JSON-RPC request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_internet_status",
    "arguments": {}
  }
}

Response

{
  "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
}

Fields

FieldTypeDescription
statestring"monitoring", "grace_period", "rebooting", "post_reboot_grace", "cooldown", "max_retries_exceeded", or "disabled"
internet_upbooleanWhether the last ping round succeeded
enabledbooleanMaster enable/disable switch
relaybooleantrue = closed (power on), false = open (power off)
consecutive_failsintegerCurrent streak of failed ping rounds
reboot_countintegerReboots in the current failure cycle
last_checkstring | nullISO 8601 UTC of most recent ping check
last_outagestring | nullISO 8601 UTC of most recent outage
last_rebootstring | nullISO 8601 UTC of most recent router reboot

Example prompt

"Is the internet working right now?"


get_uptime_stats

Returns cumulative lifetime statistics — useful for understanding long-term reliability.

Input

None.

Response

{
  "total_reboots": 3,
  "total_outages": 3,
  "total_monitoring_hours": 720.5,
  "total_downtime_hours": 1.2,
  "uptime_percent": 99.83
}

Fields

FieldTypeDescription
total_rebootsintegerLifetime router reboots (persisted in NVS)
total_outagesintegerLifetime outages detected
total_monitoring_hoursfloatTotal hours the watchdog has been monitoring
total_downtime_hoursfloatTotal hours of detected downtime
uptime_percentfloat100 × (1 − downtime / monitoring_time). Returns 100.0 if no monitoring time.

Example prompt

"What's my internet uptime this month?"


trigger_reboot

Manually power-cycle the router. Opens the relay (power off), waits power_off_duration_s, then closes it (power on).

Input

None.

Response (success)

{
  "status": "rebooting"
}

Error response

{
  "error": "Already rebooting"
}

Returned if the device is currently in rebooting or post_reboot_grace state.

Side effects

Example prompt

"Reboot my router"


get_event_history

Returns the event ring buffer — up to 16 most recent events, ordered oldest first.

Input

None.

Response

[
  {
    "event": "device_online",
    "timestamp_ms": 1500,
    "reboot_count": 0
  },
  {
    "event": "outage_detected",
    "timestamp_ms": 185000,
    "reboot_count": 0
  }
]

Fields (per event)

FieldTypeDescription
eventstringEvent type (see table below)
timestamp_msintegerMilliseconds since device boot
reboot_countintegerReboots at time of event

Event types

EventDescription
device_onlineDevice booted
outage_detectedConnectivity lost (threshold reached)
reboot_startedRouter power-cycle initiated
internet_restoredConnectivity recovered
max_retries_exceededAll retry attempts exhausted
scheduled_rebootDaily scheduled reboot triggered
manual_rebootUser-initiated reboot
enabledMonitoring turned on
disabledMonitoring turned off

Example prompt

"Show me the recent outage history"


set_enabled

Enable or disable watchdog monitoring.

Input schema

{
  "type": "object",
  "properties": {
    "enabled": {
      "type": "boolean",
      "description": "Enable or disable monitoring"
    }
  },
  "required": ["enabled"]
}

JSON-RPC request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "set_enabled",
    "arguments": { "enabled": false }
  }
}

Response (success)

{
  "enabled": false,
  "state": "disabled"
}

Error response

{
  "error": "Missing boolean 'enabled' parameter"
}

Side effects

Example prompt

"Disable the watchdog temporarily"


force_ping

Force an immediate connectivity check against all configured targets. Returns per-target results with round-trip times.

Input

None.

Response

{
  "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 }
  ]
}

Fields

FieldTypeDescription
internet_upbooleantrue if at least one target responded
targets[].ipstringIPv4 address pinged
targets[].successbooleanWhether this target responded
targets[].rtt_msintegerRound-trip time in ms (0 if failed)

Side effects

Example prompt

"Ping the internet and show me the results"


get_watchdog_config

Read all current configuration parameters.

Input

None.

Response

{
  "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"]
}

Fields

FieldTypeDefaultRangeDescription
enabledbooleantrueMaster monitoring switch
ping_interval_sinteger6030–300Seconds between ping rounds
fail_thresholdinteger32–10Consecutive failures before outage
grace_before_reboot_sinteger1200–600Wait before power cycle
power_off_duration_sinteger3010–120Router off duration
post_reboot_grace_sinteger300120–900Max wait for internet after reboot (exits early on success)
max_retriesinteger31–10Max power-cycle attempts
retry_cooldown_mininteger3010–120Minutes between retries
scheduled_rebootstring | nullnull"HH:MM" or nullDaily reboot time
ping_targetsstring[]["8.8.8.8","1.1.1.1","208.67.222.222"]1–4 IPsPing targets

Example prompt

"What are the current watchdog settings?"


set_watchdog_config

Update one or more configuration parameters. Only fields present in arguments are changed. Changes are persisted to NVS immediately.

Input schema

{
  "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.

JSON-RPC request examples

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"] }
  }
}

Response (success)

{
  "changes_applied": 1,
  "state": "monitoring"
}

Error responses

Error messageCondition
"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

Example prompt

"Change the ping interval to 2 minutes and add Cloudflare DNS as a target"


reset_stats

Reset all cumulative statistics to zero — lifetime reboots, outages, monitoring time, and timestamps.

Input

None.

Response

{
  "status": "stats_reset"
}

What gets reset

StatReset to
total_reboots0
total_outages0
total_monitoring_hours0
total_downtime_hours0
uptime_percent100.0
last_checknull
last_outagenull
last_rebootnull

Side effects

Example prompt

"Reset the uptime statistics"


Common Notes

Error handling

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.

Tool discovery

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.

Timestamps

ISO 8601 UTC format: "2026-02-11T15:30:00Z". Returns null if the system clock hasn't synced (epoch before 2025-01-01).

Concurrency

Tool calls are processed sequentially. force_ping blocks while ICMP pings execute (up to 3 seconds per target).

MCP Resource

One resource is registered but not yet implemented:

URINameMIME Type
watchdog://statuswatchdog_statusapplication/json