mcp / scripts /set_space_variable.py
mikeboone's picture
Claude Opus 5.5
docs(muze): MUZE_ENGINE_MAIN_TABS defaults ON since 56a7b8e β€” the variable is now the emergency off
4162a45
Raw History Blame Contribute Delete
4.96 kB
#!/usr/bin/env python
"""Show or set a public VARIABLE on one of the DemoPrep HF Spaces.
Variables are the per-Space switches that make ONE commit behave differently on
test and prod β€” e.g. MUZE_ENGINE_MAIN_TABS=false as an emergency off on one Space
(unset = ON everywhere since 2026-09-22).
They are NOT secrets: on a public Space anyone can read them. Secrets go through
scripts/setup_test_mcp_secrets.py.
./.venv/bin/python scripts/set_space_variable.py test-mcp --show
./.venv/bin/python scripts/set_space_variable.py test-mcp MUZE_ENGINE_MAIN_TABS true
./.venv/bin/python scripts/set_space_variable.py mcp MUZE_ENGINE_MAIN_TABS false --dry-run
./.venv/bin/python scripts/set_space_variable.py test-mcp MUZE_ENGINE_MAIN_TABS --delete
Space may be a short name (test-mcp, mcp, demoprep, test-demoprep) or a full
`owner/name` repo id.
Setting or deleting a variable RESTARTS the Space and kills any build in flight.
Check the MCP `status` tool for active_builds first. Set the variable BEFORE
pushing code that reads it β€” old code ignores the variable, so the extra
restart is harmless, and the new code comes up already in the intended mode.
Token: HF_TOKEN from the environment, else from the .env named by --env
(default: <repo root>/.env). Reading variables on a public Space needs no token.
"""
import argparse
import os
import sys
from pathlib import Path
SHORT_NAMES = {
"test-mcp": "thoughtspot-demoprep/test-mcp",
"mcp": "thoughtspot-demoprep/mcp",
"demoprep": "thoughtspot-dp/demoprep",
"test-demoprep": "thoughtspot-dp/test-demoprep",
}
DEFAULT_ENV = Path(__file__).resolve().parent.parent / ".env"
def repo_id_of(space: str) -> str:
if "/" in space:
return space
if space in SHORT_NAMES:
return SHORT_NAMES[space]
sys.exit(f"ERROR: unknown Space {space!r}. Use one of {sorted(SHORT_NAMES)} or a full owner/name.")
def token_from(env_path: Path) -> str:
tok = (os.getenv("HF_TOKEN") or "").strip()
if tok:
return tok
if env_path.exists():
for raw in env_path.read_text().splitlines():
line = raw.strip()
if line.startswith("HF_TOKEN="):
return line.split("=", 1)[1].strip().strip('"').strip("'")
sys.exit(f"ERROR: no HF_TOKEN in the environment or in {env_path}. "
"A write needs one; pass --env to point at the .env that has it.")
def show(api, repo_id: str) -> None:
variables = api.get_space_variables(repo_id=repo_id)
if not variables:
print(f"{repo_id}: no variables set")
return
print(f"{repo_id}:")
for key, var in sorted(variables.items()):
updated = getattr(var, "updated_at", None) or getattr(var, "updatedAt", "")
print(f" {key} = {var.value!r} (updated {updated})")
def main() -> None:
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("space", help="test-mcp | mcp | demoprep | test-demoprep | owner/name")
ap.add_argument("key", nargs="?", help="variable name")
ap.add_argument("value", nargs="?", help="value to set")
ap.add_argument("--show", action="store_true", help="list the Space's variables and exit")
ap.add_argument("--delete", action="store_true", help="delete KEY instead of setting it")
ap.add_argument("--dry-run", action="store_true", help="say what would change, touch nothing")
ap.add_argument("--env", type=Path, default=DEFAULT_ENV, help="the .env holding HF_TOKEN")
args = ap.parse_args()
from huggingface_hub import HfApi
repo_id = repo_id_of(args.space)
if args.show or not args.key:
# Reads work without a token on a public Space; send one if we have it.
tok = (os.getenv("HF_TOKEN") or "").strip() or None
show(HfApi(token=tok), repo_id)
return
if args.delete and args.value is not None:
sys.exit("ERROR: --delete takes KEY only, no value.")
if not args.delete and args.value is None:
sys.exit("ERROR: give a VALUE to set, or --delete, or --show.")
action = f"DELETE {args.key}" if args.delete else f"SET {args.key}={args.value!r}"
print(f"{action} on {repo_id} β€” this RESTARTS the Space and kills in-flight builds.")
if args.dry_run:
print("--dry-run: nothing was changed.")
return
if input("Proceed? [y/N] ").strip().lower() != "y":
sys.exit("Aborted.")
api = HfApi(token=token_from(args.env))
if args.delete:
api.delete_space_variable(repo_id=repo_id, key=args.key)
else:
api.add_space_variable(repo_id=repo_id, key=args.key, value=args.value)
print("done. Now:")
show(api, repo_id)
print("\nNEXT: after the restart, call the `config_check` tool and confirm `muze.main_tabs` "
"(or whatever the variable drives) reads as intended. A booted container is not a verified one.")
if __name__ == "__main__":
main()