Summary
profile_manager.py (confirmed in the published PyPI 0.3.0 release) guards write_page against clobbering by the running Elgato app like this:
def is_stream_deck_app_running() -> bool:
if sys.platform != "darwin":
return False
...
def stop_stream_deck_app(*, graceful_timeout: float = 3.0) -> dict[str, Any]:
if sys.platform != "darwin":
return {"stopped": False, "graceful": [], "forced": [], "reason": "non-darwin platform"}
...
Both functions unconditionally treat every non-macOS platform as "app not running," and write_page's guard is:
if is_stream_deck_app_running():
if not auto_quit_app:
raise StreamDeckAppRunningError(...)
...
On Windows this branch is never entered, regardless of whether the Stream Deck app is actually running and regardless of auto_quit_app. The README documents Windows as a supported target for the default profile-writer mode ("the Elgato Stream Deck desktop app, which is available on macOS and Windows") and explicitly warns that "The Elgato desktop app keeps profiles in memory and can overwrite on-disk manifest edits when it quits" — but on Windows the safeguard against exactly that scenario silently does nothing.
Impact
Calling streamdeck_write_page on Windows while the Stream Deck app is running does not raise StreamDeckAppRunningError and appears to succeed. The on-disk edit can later be silently reverted the next time the user quits/restarts the Stream Deck app normally, with no error at write time and no indication anything was lost.
Repro
- On Windows, with the Elgato Stream Deck app running (
StreamDeck.exe in Task Manager).
- Call
ProfileManager().write_page(...) (or the streamdeck_write_page MCP tool) without stopping the app first.
- No
StreamDeckAppRunningError is raised; the manifest is written to disk immediately.
- Quit/restart the Stream Deck app normally — it may overwrite the on-disk manifest with its in-memory state, discarding the edit from step 2/3 with no warning.
Suggested fix
Implement is_stream_deck_app_running() / stop_stream_deck_app() for Windows too, e.g. via psutil or tasklist/taskkill (the real process name is StreamDeck.exe, not Stream Deck/Elgato Stream Deck as used in the current STREAM_DECK_APP_PROCESS_NAMES for the macOS pgrep/osascript/killall calls). Happy to send a PR if useful — worked around it locally in the meantime with:
Stop-Process -Name StreamDeck -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
# ... call write_page ...
Start-Process "C:\Program Files\Elgato\StreamDeck\StreamDeck.exe"
Related, smaller Windows gaps noticed while debugging this
create_action raises ProfileValidationError unconditionally on sys.platform == "win32" (POSIX-only .sh + chmod implementation). A path-based button (com.elgato.streamdeck.system.open) works as a substitute for simple cases, but there's no Windows equivalent for "create a new script-backed action" the way .sh works on POSIX.
restart_app also raises on any non-macOS platform, so after a write the app must be relaunched manually on Windows (matches the README's note, just flagging it's a hard error rather than a no-op).
Environment
streamdeck-mcp 0.3.0 (via uvx streamdeck-mcp)
- Windows 11
- Elgato Stream Deck app (Windows),
ProfilesV3
Summary
profile_manager.py(confirmed in the published PyPI0.3.0release) guardswrite_pageagainst clobbering by the running Elgato app like this:Both functions unconditionally treat every non-macOS platform as "app not running," and
write_page's guard is:On Windows this branch is never entered, regardless of whether the Stream Deck app is actually running and regardless of
auto_quit_app. The README documents Windows as a supported target for the default profile-writer mode ("the Elgato Stream Deck desktop app, which is available on macOS and Windows") and explicitly warns that "The Elgato desktop app keeps profiles in memory and can overwrite on-disk manifest edits when it quits" — but on Windows the safeguard against exactly that scenario silently does nothing.Impact
Calling
streamdeck_write_pageon Windows while the Stream Deck app is running does not raiseStreamDeckAppRunningErrorand appears to succeed. The on-disk edit can later be silently reverted the next time the user quits/restarts the Stream Deck app normally, with no error at write time and no indication anything was lost.Repro
StreamDeck.exein Task Manager).ProfileManager().write_page(...)(or thestreamdeck_write_pageMCP tool) without stopping the app first.StreamDeckAppRunningErroris raised; the manifest is written to disk immediately.Suggested fix
Implement
is_stream_deck_app_running()/stop_stream_deck_app()for Windows too, e.g. viapsutilortasklist/taskkill(the real process name isStreamDeck.exe, notStream Deck/Elgato Stream Deckas used in the currentSTREAM_DECK_APP_PROCESS_NAMESfor the macOSpgrep/osascript/killallcalls). Happy to send a PR if useful — worked around it locally in the meantime with:Related, smaller Windows gaps noticed while debugging this
create_actionraisesProfileValidationErrorunconditionally onsys.platform == "win32"(POSIX-only.sh+chmodimplementation). Apath-based button (com.elgato.streamdeck.system.open) works as a substitute for simple cases, but there's no Windows equivalent for "create a new script-backed action" the way.shworks on POSIX.restart_appalso raises on any non-macOS platform, so after a write the app must be relaunched manually on Windows (matches the README's note, just flagging it's a hard error rather than a no-op).Environment
streamdeck-mcp0.3.0 (viauvx streamdeck-mcp)ProfilesV3