#!/usr/bin/env python3 """ Human-friendly MCP test client. Usage: mcp-test.py ShowCommands mcp-test.py ListBlueprintAssets filter=lx mcp-test.py ShowCommands verbose=true """ import sys import json import socket HOST = "localhost" PORT = 9847 TIMEOUT = 120 # Map ASCII characters to the Unicode geometric delimiters used by the plugin. DELIMITER_MAP = str.maketrans({ '<': '◂', '>': '▸', '*': '◆', '.': '◦', '|': '│', }) def main(): args = sys.argv[1:] if not args: print("Usage: mcp-test.py ShowCommands [key=value ...]") sys.exit(1) msg = {"command": args[0]} for arg in args[1:]: key, _, value = arg.partition("=") if value.lower() == "true": value = True elif value.lower() == "false": value = False else: try: value = int(value) except ValueError: pass msg[key] = value # Translate ASCII delimiter shortcuts to Unicode geometric shapes. for key, value in msg.items(): if isinstance(value, str): msg[key] = value.translate(DELIMITER_MAP) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(TIMEOUT) try: sock.connect((HOST, PORT)) except (ConnectionRefusedError, socket.timeout, OSError) as e: print(f"Cannot connect to {HOST}:{PORT} — is the editor running?") sys.exit(1) sock.sendall((json.dumps(msg) + "\n").encode()) result = b"" while True: chunk = sock.recv(65536) if not chunk: break result += chunk if b"\0" in result: break sock.close() result = result[:result.index(b"\0")].decode() if b"\0" in result else result.decode() try: parsed = json.loads(result) print(json.dumps(parsed, indent=2)) except json.JSONDecodeError: print(result) if __name__ == "__main__": main()