loading…
Search for a command to run...
loading…
Enables AI agents to control Digital Loggers (DLI) Web Power Switches for hardware discovery, status querying, and power operations. It features a safety-first
Enables AI agents to control Digital Loggers (DLI) Web Power Switches for hardware discovery, status querying, and power operations. It features a safety-first architecture with configurable access levels to protect critical infrastructure from unauthorized or accidental power loss.
This project implements a Model Context Protocol (MCP) server that allows an AI agent to control Digital Loggers (DLI) Web Power Switches. The system provides tools for discovering hardware, querying outlet status, and performing power operations (On/Off/Cycle).
Crucial Constraint: This system interacts with physical hardware. Strict safety protocols are enforced to prevent accidental power loss to critical infrastructure.
server.py: The main entry point. Contains the FastMCP server implementation, tool definitions, and hardware interaction logic using the power-switch-pro library.switches_config.json: The source of truth for device configuration. Defines IP addresses, authentication, outlet aliases, and safety types (standard, critical, prohibited).requirements.txt: Python dependencies (power-switch-pro).tests/: Unit tests for the server logic.This server is designed for responsiveness and safety:
asyncio to handle multiple operations efficiently.get_inventory tool fetches status from all configured switches concurrently, significantly reducing latency in systems with multiple devices.Install this server from PyPI using pip:
pip install dli-mcp-server
Once installed, register the server with the Gemini CLI (or Antigravity) using the mcp add command. This ensures the server starts automatically.
gemini mcp add dli-mcp-server dli-mcp-server -e DLI_MCP_CONFIG="/path/to/your/config.json"
Parameters:
dli-mcp-server is the name you assign to this server instance.dli-mcp-server is the command that runs the server (made available by pip install).-e DLI_MCP_CONFIG="...": (Optional) Sets the environment variable for the configuration file path. If omitted, it defaults to switches_config.json in the current directory.-s user or -s project: (Optional) Sets the configuration scope. Defaults to project.The server.py script can be used directly from the command line to control the power switches.
inventoryLists all switches and their outlet statuses.
python server.py inventory
power_actionPerforms a power action (on, off, cycle) on a specific outlet.
python server.py power_action <switch_id> <outlet_id> <action> [--confirmation YES]
switch_id: Alias or IP address of the switch.outlet_id: Index or name of the outlet.action: on, off, or cycle.--confirmation: Required for critical outlets.group_power_actionPerforms a power action on a group of outlets.
python server.py group_power_action <group_id> <action>
sync_config_from_hardwareSynchronizes outlet names from the hardware.
python server.py sync_config_from_hardware <switch_id>
list_outletsLists all outlets on a given switch.
python server.py list_outlets <switch_id>
add_switchAdds a new DLI power switch to the configuration. If the configuration file does not exist, it will be automatically created.
python server.py add_switch <ip_address> <username> <password>
ip_address: IP address of the new switch.username: Username for the new switch.password: Password for the new switch.remove_switchRemoves a DLI power switch from the configuration.
python server.py remove_switch <switch_id>
switch_id: Alias or IP address of the switch to remove.update_outletUpdates the definition of an outlet.
python server.py update_outlet <switch_id> <outlet_id> [--name <new_name>] [--description <new_description>] [--type <new_type>]
switch_id: Alias or IP address of the switch.outlet_id: Index or name of the outlet (e.g., "Modem" or "1").--name: New name for the outlet.--description: New description for the outlet.--type: New type for the outlet (standard, critical, or prohibited).| Type | Agent Permission | Behavior |
|---|---|---|
standard |
Full Access | Can be turned On, Off, or Cycled immediately. |
critical |
Restricted | "Off" or "Cycle" actions require explicit user confirmation (confirmation="YES"). |
prohibited |
No Access | NEVER modify this outlet. The server will raise a PermissionError. |
get_inventory()power_action(switch_id, outlet_id, action, confirmation="NO")switch_id: The Alias (e.g., "garage_rack") or IP.outlet_id: The Name (e.g., "Modem") or Index (e.g., "1").action: "on", "off", or "cycle".confirmation: Must be set to "YES" only if the user has explicitly approved a dangerous action on a critical outlet.group_power_action(target, action)prohibited, the entire operation aborts immediately.sync_config_from_hardware(switch_id)switches_config.json file with the actual outlet names found on the device.critical/prohibited) or descriptions.add_switch(ip_address, username, password)ip_address: IP address of the new switch.username: Username for the new switch.password: Password for the new switch.remove_switch(switch_id)switch_id: Alias or IP address of the switch to remove.list_outlets(switch_id)switch_id: The Alias or IP address of the switch.update_outlet(switch_id, outlet_id, new_name=None, new_description=None, new_type=None)switch_id: The Alias or IP address of the switch.outlet_id: The Name or Index (e.g., "Modem" or "1").new_name (optional): The new name for the outlet. This is written to both the config file and the hardware.new_description (optional): The new description for the outlet. This is only written to the config file.new_type (optional): The new type for the outlet (standard, critical, or prohibited). This is only written to the config file.get_inventory.power_action returns a "SAFETY LOCK" message, stop and ask the user: "This is a critical device. Are you sure you want to turn it off?". Only proceed if they say "Yes".alias and name (e.g., "garage_rack", "Modem") over IP addresses and indices when communicating with the user.The project includes a suite of unit tests to ensure the server logic is correct. The tests are located in the tests/ directory.
To run the tests, first install the testing dependencies:
pip install -r tests/requirements.txt
Then, use the following command to run the tests:
python tests/test_server.py
The tests are designed to run without a physical DLI power switch. They use mocking to simulate the hardware and its behavior.
The project uses GitHub Actions for continuous integration. Tests are automatically executed on every push and pull request to the main branch. The workflow runs on:
This ensures cross-platform compatibility and stability across supported Python versions.
To check the test coverage, you can use the coverage package (which is included in tests/requirements.txt).
Run the tests with coverage and generate a report:
coverage run tests/test_server.py
coverage report -m
The project aims for a high test coverage to ensure reliability.
You can easily register this MCP server with the Gemini CLI (or Antigravity) using the mcp add command. This ensures the server starts automatically.
Windows:
gemini mcp add dli-mcp-server python "C:\Path\To\dli-mcp-server\server.py" -e DLI_MCP_CONFIG="C:\Path\To\your\config.json" -s user
Linux / macOS:
gemini mcp add dli-mcp-server python "/path/to/dli-mcp-server/server.py" -e DLI_MCP_CONFIG="/path/to/your/config.json" -s user
Parameters:
dli-mcp-server: The name you assign to the server.python "...": The command to start the server. Ensure you provide the full absolute path to server.py.-e DLI_MCP_CONFIG="...": (Optional) Sets the environment variable for the configuration file path. If omitted, it defaults to switches_config.json in the server's directory.-s user: Saves the configuration to your user settings (global), making it available across all projects.-s project (Default): Saves the configuration to the current project's .gemini/settings.json. Use this if you want the server configuration to be specific to the current workspace.By default, the server uses the switches_config.json file in the same directory. You can override this by setting the DLI_MCP_CONFIG environment variable to the path of your configuration file.
Example:
export DLI_MCP_CONFIG=/path/to/your/custom_config.json
python server.py inventory
This is particularly useful for testing with different configurations without modifying the main switches_config.json file.
User: "Turn off the Router."
Agent Action:
get_inventory (internal) -> sees Router is critical.power_action("garage_rack", "Router", "off").User: "Yes, do it."
Agent Action:
power_action("garage_rack", "Router", "off", confirmation="YES").This MCP server was developed using Gemini CLI and Gemini 3.0 models.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"dli-power-switch-mcp-server": {
"command": "npx",
"args": []
}
}
}