mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-17 07:09:09 +02:00
claude_desktop: register headroom MCP server instead of proxy launch
headroom's proxy/wrap routing relies on ANTHROPIC_BASE_URL, which Claude Desktop force-overrides (headroom #869), so it cannot transparently compress the desktop app. Register headroom's MCP server (headroom mcp serve) in Claude Desktop's claude_desktop_config.json instead -- the supported integration -- exposing the headroom_compress/headroom_retrieve/headroom_stats tools inside the app. The plain desktop launch is left untouched. The JSON merge is idempotent, preserves any other MCP servers and top-level keys, backs up malformed config, and removes the entry again when install_headroom is disabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgMcG1QjsSHcDQBxgPpRUw
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
## 1.6 (07-07-2026)
|
||||
|
||||
- Fix default desktop launch failing when `install_headroom` is enabled (the default): `headroom wrap` only supports coding-agent CLIs (`claude`, `codex`, ...) with agent arguments after `--`, so wrapping `claude-desktop` produced an invalid command that left the app unlaunched. Launch Claude Desktop through headroom's standalone compression proxy (`headroom proxy` + `ANTHROPIC_BASE_URL`) instead. Note: Claude Desktop currently overrides `ANTHROPIC_BASE_URL` ([headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869)), so transparent compression engages only once upstream adds Desktop support; the app launches normally in the meantime.
|
||||
- Make the autostart resilient: if the headroom/custom launch command fails to start, fall back to the plain Claude Desktop launch so the app always comes up.
|
||||
- Fix default desktop launch failing when `install_headroom` is enabled (the default): the code rewrote the launch to `headroom wrap claude-desktop …`, but `headroom wrap` only supports coding-agent CLIs (`claude`, `codex`, ...) with arguments after `--`, so it produced an invalid command that left the app unlaunched. Leave the plain launch intact and instead register the `headroom` MCP server (`headroom mcp serve`) in Claude Desktop's config, exposing the `headroom_compress`/`headroom_retrieve`/`headroom_stats` tools inside the app. This is the supported headroom integration for Desktop, which overrides `ANTHROPIC_BASE_URL` so transparent proxy compression is not possible ([headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869)). Disabling the option removes the entry again.
|
||||
- Make the autostart resilient: if the launch command fails to start, fall back to the plain Claude Desktop launch so the app always comes up.
|
||||
|
||||
## 1.5 (07-07-2026)
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Claude Desktop sign-in requires a claude.ai plan that supports the Desktop app.
|
||||
| `DRINODE` | | Optional GPU device override for Selkies. |
|
||||
| `DNS_server` | `8.8.8.8` | DNS server used by the standard DNS module. |
|
||||
| `auto_update` | `true` | Check Anthropic's apt repository and upgrade `claude-desktop` at add-on startup. |
|
||||
| `install_headroom` | `true` | Launch Claude Desktop through the baked-in `headroom` compression proxy. Note: Claude Desktop currently overrides the proxy endpoint ([headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869)), so transparent compression only engages once upstream adds Desktop support; the app still launches normally, and falls back to a plain launch if the proxy command fails. |
|
||||
| `install_headroom` | `true` | Register the baked-in `headroom` MCP server in Claude Desktop, exposing its `headroom_compress`/`headroom_retrieve`/`headroom_stats` context-compression tools inside the app. (Claude Desktop overrides `ANTHROPIC_BASE_URL`, so transparent proxy compression is not possible — MCP is the supported path; see [headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869).) Disabling removes the entry again. |
|
||||
| `install_rtk` | `true` | Configure the rtk Claude Code `PreToolUse` hook in the persistent Claude Code settings. |
|
||||
| `install_caveman` | `true` | Install the caveman Claude Code plugin into the persistent Claude Code home. |
|
||||
| `install_github_cli` | `true` | Enable first-start checks and setup for the baked-in `git` and `gh` commands. |
|
||||
|
||||
@@ -8,23 +8,60 @@ CLAUDE_DESKTOP_COMMAND_FILE="/tmp/claude-desktop-command"
|
||||
DEFAULT_CLAUDE_DESKTOP_COMMAND='claude-desktop --no-sandbox --disable-dev-shm-usage --password-store=gnome-libsecret'
|
||||
printf '%s\n' "$DEFAULT_CLAUDE_DESKTOP_COMMAND" > "$CLAUDE_DESKTOP_COMMAND_FILE"
|
||||
|
||||
# headroom's "wrap"/proxy routing works by setting ANTHROPIC_BASE_URL, which the Claude Desktop
|
||||
# Electron app force-overrides to the production endpoint (headroom #869), so transparent
|
||||
# compression cannot be applied to the desktop launch. The integration that does work with
|
||||
# Claude Desktop is headroom's MCP server, which exposes the headroom_compress/headroom_retrieve/
|
||||
# headroom_stats tools inside the app. Register it in Claude Desktop's MCP config, leaving the
|
||||
# plain launch untouched. The merge is idempotent and preserves any other MCP servers.
|
||||
CLAUDE_DESKTOP_CONFIG="$HOME/.config/Claude/claude_desktop_config.json"
|
||||
if bashio::config.true 'install_headroom'; then
|
||||
if command -v headroom &> /dev/null; then
|
||||
# headroom "wrap" only supports coding-agent CLIs (claude|codex|cursor|...) and is
|
||||
# invalid for the Claude Desktop Electron app, so route the launch through headroom's
|
||||
# standalone compression proxy instead: start "headroom proxy" and point Claude Desktop
|
||||
# at it via ANTHROPIC_BASE_URL.
|
||||
#
|
||||
# NOTE: Claude Desktop currently force-overrides ANTHROPIC_BASE_URL to the production
|
||||
# endpoint (headroom #869), so compression only actually engages once upstream adds
|
||||
# Desktop support. Until then the app still launches normally, and the autostart falls
|
||||
# back to a plain launch if this command fails.
|
||||
HEADROOM_PROXY_PORT="8787"
|
||||
bashio::log.info "headroom $(headroom --version 2> /dev/null || true) available; launching Claude Desktop through the headroom proxy on 127.0.0.1:${HEADROOM_PROXY_PORT} (transparent compression pending Claude Desktop support, headroom #869)"
|
||||
printf '%s\n' "headroom proxy --port ${HEADROOM_PROXY_PORT} > /tmp/headroom-proxy.log 2>&1 & ANTHROPIC_BASE_URL=http://127.0.0.1:${HEADROOM_PROXY_PORT} ${DEFAULT_CLAUDE_DESKTOP_COMMAND}" > "$CLAUDE_DESKTOP_COMMAND_FILE"
|
||||
bashio::log.info "headroom $(headroom --version 2> /dev/null || true) available; registering the headroom MCP server for Claude Desktop"
|
||||
HEADROOM_BIN="$(command -v headroom)" CLAUDE_DESKTOP_CONFIG="$CLAUDE_DESKTOP_CONFIG" python3 - <<'PY' || bashio::log.warning "Unable to register the headroom MCP server automatically"
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(os.environ["CLAUDE_DESKTOP_CONFIG"])
|
||||
try:
|
||||
data = json.loads(path.read_text()) if path.exists() else {}
|
||||
if not isinstance(data, dict):
|
||||
data = {}
|
||||
except Exception:
|
||||
if path.exists():
|
||||
path.rename(path.with_suffix(path.suffix + ".bak"))
|
||||
data = {}
|
||||
servers = data.get("mcpServers")
|
||||
if not isinstance(servers, dict):
|
||||
servers = {}
|
||||
data["mcpServers"] = servers
|
||||
servers["headroom"] = {"command": os.environ.get("HEADROOM_BIN", "headroom"), "args": ["mcp", "serve"]}
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(data, indent=2) + "\n")
|
||||
PY
|
||||
else
|
||||
bashio::log.warning "headroom is not available"
|
||||
fi
|
||||
elif [ -f "$CLAUDE_DESKTOP_CONFIG" ]; then
|
||||
bashio::log.info "Removing the headroom MCP server from Claude Desktop"
|
||||
CLAUDE_DESKTOP_CONFIG="$CLAUDE_DESKTOP_CONFIG" python3 - <<'PY' || bashio::log.warning "Unable to remove the headroom MCP server automatically"
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(os.environ["CLAUDE_DESKTOP_CONFIG"])
|
||||
try:
|
||||
data = json.loads(path.read_text())
|
||||
except Exception:
|
||||
data = None
|
||||
if isinstance(data, dict):
|
||||
servers = data.get("mcpServers")
|
||||
if isinstance(servers, dict) and servers.pop("headroom", None) is not None:
|
||||
if not servers:
|
||||
data.pop("mcpServers", None)
|
||||
path.write_text(json.dumps(data, indent=2) + "\n")
|
||||
PY
|
||||
fi
|
||||
|
||||
if bashio::config.true 'install_rtk'; then
|
||||
|
||||
Reference in New Issue
Block a user