Blackout Tracker Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Blackout Tracker Mcp (MCP Server) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
An MCP server for monitoring electricity outage schedules in Ukraine (DTEK Dnipro Electric Networks). Currently, supports Dnipropetrovsk region only.
This MCP server helps track scheduled electricity outages and provides timely notifications about upcoming shutdowns. Especially useful for planning laptop charging and managing other devices during power outages.
https://drive.google.com/file/d/1RsHJWdFBvEGF-KOu3yS7BWbEXgPU-E2V/view?usp=sharing
img.png
img.png
img.png
img.png
img.png
img.png
img.png
img.png
Prerequisites:
terminal-notifier for native notifications (brew install terminal-notifier)Installation:
1. Clone and build:
git clone <repository-url>
cd blackout_tracker_mcp
docker-compose build2. Start the server:
docker-compose up -dThis starts:
mcp-server - Main MCP server (handles Claude requests)notification-daemon - Background notification daemon (monitors for outages)3. (Optional) Enable notifications and battery detection:
If you want native macOS notifications and battery auto-detection, start the bridge scripts:
./watch_notifications.sh & # Forwards notifications from Docker to macOS
./battery_info.sh & # Enables battery auto-detection for charging calculator4. Configure Claude:
Open your Claude configuration file (code ~/.claude.json) and add:
{
"mcpServers": {
"blackout-tracker": {
"type": "stdio",
"command": "docker",
"args": [
"exec",
"-i",
"blackout-tracker-mcp",
"python",
"-m",
"src.server"
]
}
}
}Important: Add "mcpServers" at the root level of ~/.claude.json, before the "projects" section.
5. Restart Claude Code/Desktop and verify with claude mcp list
That's it! 🎉
After connecting the MCP server, you'll see available tools:
set_address - Configure your addresscheck_outage_schedule - Check outage schedulesget_next_outage - Find the next upcoming outageget_outages_for_day - Get all outages for a specific daycalculate_charging_time - Calculate optimal charging time before outages (MacBook only)configure_monitoring - Configure notification settingscheck_upcoming_outages - Check for upcoming outages and get alerts1. Set Your Address:
First, configure your address (note: use prefixes as they appear on DTEK website):
Set my address: м. Дніпро, вул. Вʼячеслава Липинського, 4Claude will call set_address with the correct parameters.
2. Check the Schedule:
Check electricity outage scheduleClaude will call check_outage_schedule and show you the full schedule.
3. Find Next Outage:
When is the next outage?Claude will call get_next_outage to show the nearest upcoming outage.
4. Check Specific Day:
Show all outages for MondayClaude will call get_outages_for_day to show outages for a specific day.
5. Enable Notifications:
Enable notifications 30 minutes before outagesClaude will call configure_monitoring to set up automatic monitoring.
6. Check Upcoming Outages:
Check for upcoming outagesClaude will call check_upcoming_outages to see if any outage is approaching soon.
7. Calculate Charging Time (MacBook only):
When should I charge my MacBook before the next outage?Claude will call calculate_charging_time to calculate optimal charging time.
#### Basic Usage
You: Set my address to м. Дніпро, Вʼячеслава Липинського, 4
Claude: [Calls set_address]
✓ Address saved: м. Дніпро, Вʼячеслава Липинського, 4
You: Check outage schedule
Claude: [Calls check_outage_schedule]
📍 Address: м. Дніпро, Вʼячеслава Липинського, 4
...#### Advanced Usage
You: When is the next outage?
Claude: [Calls get_next_outage]
⏰ Next outage:
14.11.25 Thursday, 18:00-19:00
Type: Definite outage ✗You: Show all outages for Monday
Claude: [Calls get_outages_for_day with day_of_week="Понеділок"]
📅 Day: Понеділок
Outages (5):
✗ 15.11.25 08:00-09:00 (definite)
...You: Enable notifications 30 minutes before outages
Claude: [Calls configure_monitoring]
✓ Monitoring configured:
Notifications: enabled
Notify 30 minutes before outage
Check interval: 60 minutes
The notification daemon is now running automatically in Docker and will monitor your outage schedule.That's it! The notification daemon (already running in background) will check for outages and send notifications.
You: Check for upcoming outages
Claude: [Calls check_upcoming_outages]
⚠️ UPCOMING OUTAGE ALERT
Power outage starting in 25 minutes!
📅 14.11.25 Thursday
⏰ 18:00-19:00
📊 Definite outage ✗
Prepare now: charge devices, save work.You: When should I charge my MacBook before the next outage?
Claude: [Calls calculate_charging_time]
🔋 Battery Status
• Current charge: 45%
• Battery capacity: 80.9 Wh
• Charging: No
• Power consumption: 15.2W
⚡ Next outage: Today at 18:00 (in 3h 25min)
📊 Charging Recommendations:
🎯 Target: 80% (Recommended for battery health)
⏰ Start charging at: 16:47 (in 2h 12min)
⚡ Charging time needed: ~1h 13min
🔋 Target: 100% (Maximum runtime)
⏰ Start charging at: 16:15 (in 1h 40min)
⚡ Charging time needed: ~1h 45min
💡 Tips:
• 80% charge is better for long-term battery health
• 100% charge gives maximum runtime during outageset_addressConfigures the user's address for checking outage schedules.
Parameters:
city (str): City with prefix (e.g., "м. Дніпро", "м. Київ")street (str): Street with prefix (e.g., "Просп. Миру", "Вул. Шевченка")house_number (str): House number (e.g., "4", "50а")Returns: Confirmation of address saved
Important: Address is saved and used for all subsequent requests.
check_outage_scheduleChecks the current outage schedule for the configured address.
Parameters:
include_possible (bool, optional): Include weekly forecast (default: False)force_refresh (bool, optional): Force refresh data, ignoring cache (default: False)Returns:
Caching: Data is cached for 1 hour to speed up repeated requests.
get_next_outageFinds the next upcoming outage from the accurate schedule.
Parameters: None (uses configured address)
Returns:
get_outages_for_dayGets all outages for a specific day of the week.
Parameters:
day_of_week (str): Day of week in Ukrainian (Понеділок, Вівторок, Середа, Четвер, П'ятниця, Субота, Неділя)schedule_type (str, optional): Schedule type - "actual" (accurate) or "possible_week" (forecast). Default: "actual"Returns: List of all outages for the specified day with times and types
configure_monitoringConfigures notification and monitoring settings.
Parameters:
notification_before_minutes (int, optional): How many minutes before outage to send notification. Default: 60enabled (bool, optional): Enable or disable monitoring notifications. Default: falsecheck_interval_minutes (int, optional): How often to check for updates in minutes. Default: 60Returns: Confirmation of monitoring settings
Example:
Configure monitoring: enable notifications 30 minutes before outagescheck_upcoming_outagesChecks for upcoming outages based on configured notification settings. Returns an alert if an outage is approaching within the notification window.
Parameters: None (uses configured address and monitoring settings)
Returns:
Example:
Check for upcoming outagesNote: This tool respects the monitoring configuration set via configure_monitoring. Make sure monitoring is enabled and notification window is configured.
calculate_charging_time🪄 MAGIC! Automatically detects your MacBook battery and calculates the optimal time to start charging to reach 80% or 100% exactly when the next power outage occurs.
Parameters:
target_charge_percent (int, optional): Target charge level (80 or 100). Default: both levels shownReturns:
How it works:
Prerequisites:
For Docker users: Start the battery bridge script (once per system boot):
./battery_info.sh &This script collects battery data and makes it available to Docker containers. Similar to watch_notifications.sh for notifications.
For native Python users: Battery detection works automatically - no additional setup needed!
Supported devices:
Note: This tool only works on macOS devices with built-in batteries. It automatically detects:
The MCP server supports English (default) and Ukrainian languages.
By default, all tool descriptions and responses are in English. This makes the server accessible to international users.
To use Ukrainian language, configure it in the config file:
1. Locate the config file:
~/.config/blackout_tracker_mcp/config.json2. Add or modify the language setting:
{
"language": "uk",
"address": {
"city": "м. Дніпро",
"street": "вул. Вʼячеслава Липинського",
"house_number": "4"
}
}3. Restart the MCP server (restart Claude Code/Desktop or Docker container)
You can use natural language in either English or Ukrainian when talking to Claude. Here are examples:
#### English Commands:
Set my address to м. Дніпро, вул. В'ячеслава Липинського
Check electricity outage schedule
Check electricity outage schedule for today (with time when we have electricity too and summary)
When is the next outage?
Show all outages for Monday
Include possible outages for the week
Enable notifications 50 minutes before outages
Calculate charging time for nearest outage#### Ukrainian Commands:
Встанови мою адресу: м. Дніпро, вул. Вʼячеслава Липинського, 4
Перевір графік відключень світла
Коли наступне відключення?
Покажи всі відключення на понеділок
Включи можливі відключення на тиждень
Увімкни сповіщення за 50 хвилин до відключень
Розрахуй час зарядки перед наступним відключеннямNote: The language setting only affects the output format (tool descriptions and responses). You can speak to Claude in any language regardless of the configured language.
Data is sourced from the official DTEK Dnipro Electric Networks website: https://www.dtek-dnem.com.ua/ua/shutdowns
DTEK provides two types of schedules:
#### 1. "Графік відключень:" (Actual Schedule)
#### 2. "Графік можливих відключень на тиждень:" (Possible Schedule)
Different markers are used on the schedule:
Configuration and cache are stored in:
~/.config/blackout_tracker_mcp/
├── config.json # Address and monitoring settings
└── schedule_cache.json # Outage schedules cacheactual_schedules - Accurate schedules for today/tomorrowpossible_schedules - Weekly forecast scheduleslast_updated - Last update timestampblackout_tracker_mcp/
├── src/
│ ├── server.py # Main MCP server
│ ├── parser.py # DTEK website parser
│ ├── battery.py # MacBook battery auto-detection
│ ├── scheduler.py # Monitoring and notification logic
│ ├── monitor_outages_daemon.py # Background notification daemon
│ ├── config.py # Configuration and data storage
│ └── translations/ # i18n translations (en, uk)
├── tests/
│ ├── test_fill_form.py # Parser test (full cycle)
│ ├── test_visible.py # Parser test (visible browser)
│ ├── test_save_html.py # Parser test (save HTML)
│ ├── test_mcp_server.py # MCP server validation test
│ ├── test_apostrophe_normalization.py # Apostrophe handling test
│ └── test_i18n.py # Internationalization test
├── battery_info.sh # Battery bridge script (macOS → Docker)
├── watch_notifications.sh # Notification bridge script (Docker → macOS)
├── battery_status.json # Battery data file (auto-generated, gitignored)
├── Dockerfile # Docker image configuration
├── docker-compose.yml # Docker Compose configuration
├── .dockerignore # Docker ignore file
├── mcp.json # MCP configuration for Claude Code
├── requirements.txt # Python dependencies
├── pyproject.toml # Project metadata
├── README.md # This file
├── ARCHITECTURE.md # Architecture documentation
└── TODO.md # Development roadmapSolution:
pip install -r requirements.txtplaywright install chromiumpython test_mcp_server.pySolution: First configure your address using set_address:
Set address: м. Дніпро, вул. Вʼячеслава Липинського, 4Solution:
force_refresh: true for forced updateparser.py may need updating)Solution:
Enable detailed logging by adding to your configuration:
{
"mcpServers": {
"blackout-tracker": {
"type": "stdio",
"command": "/path/to/venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/path/to/project",
"env": {
"PYTHONUNBUFFERED": "1",
"LOG_LEVEL": "DEBUG"
}
}
}
}Logs can be viewed in Claude Desktop console (accessible through developer menu).
source venv/bin/activate
python -m src.serverThe server expects input via stdio (standard input/output).
Using Docker (Recommended):
# Run specific test
docker-compose run --rm --entrypoint python test-runner tests/test_mcp_server.py
# Run apostrophe normalization test
docker-compose run --rm --entrypoint python test-runner tests/test_apostrophe_normalization.py
# Run internationalization test
docker-compose run --rm --entrypoint python test-runner tests/test_i18n.py
# Run parser integration test
docker-compose run --rm --entrypoint python test-runner tests/test_fill_form.pyUsing local Python environment:
# Activate virtual environment first
source venv/bin/activate # On Windows: venv\Scripts\activate
# Parser tests
python tests/test_fill_form.py # Full cycle test
python tests/test_visible.py # Visible browser test
python tests/test_save_html.py # Save HTML test
# MCP server validation
python tests/test_mcp_server.py
# Apostrophe normalization test (regression test)
python tests/test_apostrophe_normalization.py
# Internationalization test
python tests/test_i18n.pypytest tests/The bridge scripts (watch_notifications.sh and battery_info.sh) run in the background with the & ampersand operator.
What is `&` (ampersand)?
& runs the script in background - terminal is immediately available for other commands&, the script runs in foreground - terminal is blocked until you press Ctrl+C& is essential to keep your terminal usableCheck if scripts are running:
ps aux | grep -E "battery_info|watch_notifications" | grep -v grepStop the scripts:
# Stop battery bridge
pkill -f battery_info.sh
# Stop notification bridge
pkill -f watch_notifications.sh
# Stop both at once
pkill -f "battery_info.sh|watch_notifications.sh"# View MCP server logs
docker-compose logs -f mcp-server
# View notification daemon logs (see monitoring in action!)
docker-compose logs -f notification-daemon
# View both logs together
docker-compose logs -f
# Stop all services
docker-compose down
# Restart MCP server after code changes
docker-compose restart mcp-server
# Restart notification daemon
docker-compose restart notification-daemon
# Run tests
docker-compose --profile test run --rm test-runner
# Or run one test specifically:
docker exec -i blackout-tracker-mcp python tests/test_apostrophe_normalization.pyThe notification daemon automatically:
docker-compose up -dView daemon logs:
docker-compose logs -f notification-daemonYou'll see output like:
[23:27:18] Check #1: Looking for upcoming outages...
✓ No upcoming outages in next 30 min
Next check in 60 minutesWhy Docker Can't Send macOS Notifications Directly:
Docker containers run in an isolated environment and cannot directly access macOS system APIs, including the Notification Center. The daemon running inside Docker can only write to logs and stdout, which is why we need a bridge solution to forward notifications to your macOS Notification Center.
Solution: Using terminal-notifier + watch script
To receive native macOS notifications in Notification Center:
1. Install terminal-notifier:
brew install terminal-notifierThis tool allows sending notifications to macOS Notification Center from the command line.
2. Run the notification watch script:
The watch_notifications.sh script monitors Docker daemon logs and forwards notifications to macOS:
./watch_notifications.sh &This will:
blackout-notifier container logs in real-time&) - your terminal remains usableTo stop watching:
pkill -f watch_notifications.sh3. OPTIONAL: Automatic startup on system login (LaunchAgent):
To have notifications start automatically when you log in to macOS:
Create LaunchAgent plist file:
mkdir -p ~/Library/LaunchAgentsCreate ~/Library/LaunchAgents/com.blackout.notifier.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.blackout.notifier</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/ABSOLUTE/PATH/TO/PROJECT/watch_notifications.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/blackout-notifier-watch.log</string>
<key>StandardErrorPath</key>
<string>/tmp/blackout-notifier-watch-error.log</string>
<key>WorkingDirectory</key>
<string>/ABSOLUTE/PATH/TO/PROJECT</string>
</dict>
</plist>Important: Replace /ABSOLUTE/PATH/TO/PROJECT with your actual project path.
Load the LaunchAgent:
launchctl load ~/Library/LaunchAgents/com.blackout.notifier.plistVerify it's running:
launchctl list | grep blackoutStop the LaunchAgent (if needed):
launchctl unload ~/Library/LaunchAgents/com.blackout.notifier.plistView logs:
tail -f /tmp/blackout-notifier-watch.logHow It Works:
docker logs -fNotification Details:
Important Notes:
docker-compose up -dBest for: Development, testing, debugging
Prerequisites:
Step-by-step setup:
1. Clone the repository:
git clone <repository-url>
cd blackout_tracker_mcp2. Create virtual environment:
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate3. Install dependencies:
pip install -r requirements.txt4. Install Playwright browser:
playwright install chromium5. Verify installation:
python tests/test_mcp_server.pyYou should see: ✓ ALL VALIDATIONS PASSED
6. Configure Claude:
Open your Claude configuration file (code ~/.claude.json) and add:
{
"mcpServers": {
"blackout-tracker": {
"type": "stdio",
"command": "/ABSOLUTE/PATH/TO/PROJECT/venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/ABSOLUTE/PATH/TO/PROJECT",
"env": {}
}
}
}Important:
/ABSOLUTE/PATH/TO/PROJECT/ with the actual path to your project."mcpServers" at the root level of ~/.claude.json, before the "projects" section (not inside it). This makes the MCP server available globally across all projects.How to find your absolute path:
cd blackout_tracker_mcp
pwd # This shows your absolute pathExample for macOS/Linux:
{
"mcpServers": {
"blackout-tracker": {
"type": "stdio",
"command": "/Users/john/projects/blackout_tracker_mcp/venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/Users/john/projects/blackout_tracker_mcp",
"env": {}
}
}
}Example for Windows:
{
"mcpServers": {
"blackout-tracker": {
"type": "stdio",
"command": "C:\\Users\\john\\projects\\blackout_tracker_mcp\\venv\\Scripts\\python.exe",
"args": ["-m", "src.server"],
"cwd": "C:\\Users\\john\\projects\\blackout_tracker_mcp",
"env": {}
}
}
}7. Restart Claude Code/Desktop
If there's an mcp.json file in your project directory, Claude Code will automatically detect and offer to use the MCP server when you open the project folder.
This is the fastest way to test during development.
For questions and suggestions, please create issues in the repository.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.