Files
ahmed cc2018aae7
build / sanity (push) Waiting to run
build / macos-build (push) Waiting to run
HisenseBar v1.0.0: native menu-bar remote for Hisense VIDAA TVs
- SwiftUI popover: apps grid w/ live search, sources, glass remote, gradient volume slider, animations
- Persistent python protocol bridge (vidaa-control, MQTT/TLS :36669)
- Wake-on-LAN power-on, one-time PIN pairing with token auto-refresh
- MCP server for AI agents (11 tv_* tools) + live test script
- Gitea Actions CI workflow
2026-10-13 18:20:11 +03:00

85 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Live test for mcp_tv_server.py: handshake, tools/list, real TV calls. Exit 0 = pass."""
import json
import subprocess
import sys
SERVER = "/Users/ahmedmohammed/Documents/rae/HisenseBar/mcp_tv_server.py"
PY = "/Users/ahmedmohammed/Documents/rae/.venv/bin/python3"
proc = subprocess.Popen([PY, SERVER], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, text=True, bufsize=1)
failures = []
def send(msg):
proc.stdin.write(json.dumps(msg) + "\n")
proc.stdin.flush()
def recv(expect_id, timeout=30):
import time
start = time.time()
while time.time() - start < timeout:
line = proc.stdout.readline()
if not line:
break
try:
msg = json.loads(line)
except json.JSONDecodeError:
continue
if msg.get("id") == expect_id:
return msg
raise TimeoutError(f"no response for id {expect_id}")
def check(name, cond, detail=""):
print(("PASS" if cond else "FAIL"), name, detail)
if not cond:
failures.append(name)
# 1. initialize handshake
send({"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "test"}}})
r = recv(1)
check("initialize", "serverInfo" in r.get("result", {}), r.get("result", {}).get("serverInfo", {}).get("name"))
send({"jsonrpc": "2.0", "method": "notifications/initialized"})
# 2. tools/list
send({"jsonrpc": "2.0", "id": 2, "method": "tools/list"})
r = recv(2)
tools = [t["name"] for t in r["result"]["tools"]]
check("tools_list", len(tools) == 11, f"{len(tools)} tools")
# 3. live TV calls
send({"jsonrpc": "2.0", "id": 3, "method": "tools/call",
"params": {"name": "tv_get_volume", "arguments": {}}})
r = recv(3)
vol_text = r["result"]["content"][0]["text"]
check("tv_get_volume", "Volume:" in vol_text and not r["result"].get("isError", False), vol_text)
send({"jsonrpc": "2.0", "id": 4, "method": "tools/call",
"params": {"name": "tv_get_state", "arguments": {}}})
r = recv(4)
check("tv_get_state", not r["result"].get("isError", False), r["result"]["content"][0]["text"][:60])
# wake the screen first (fake_sleep blocks sourcelist)
send({"jsonrpc": "2.0", "id": 41, "method": "tools/call",
"params": {"name": "tv_send_key", "arguments": {"key": "KEY_HOME"}}})
recv(41)
import time as _t; _t.sleep(5)
send({"jsonrpc": "2.0", "id": 5, "method": "tools/call",
"params": {"name": "tv_list_sources", "arguments": {}}})
r = recv(5)
srcs = r["result"]["content"][0]["text"]
check("tv_list_sources", "HDMI1" in srcs, srcs[:60])
proc.stdin.close()
proc.wait(timeout=5)
print("=" * 30)
print("RESULT:", "PASS" if not failures else f"FAIL ({failures})")
sys.exit(0 if not failures else 1)