Skip to main content
Glama
Fayeblade1488

Venice Browser MCP Bridge

hard_mcp_host.py3.38 kB
#!/usr/bin/env python3 import subprocess import os import json import sys import re import time # Magic number constant for response truncation MAX_RESPONSE_CHARS = 800 def run_bridge(env): return subprocess.Popen( [sys.executable, "src/venice_browser_mcp.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, text=False, # binary ) def write_cl(p, obj): """Write content-length framed message""" try: body = json.dumps(obj, separators=(",",":"), ensure_ascii=False).encode("utf-8") headers = f"Content-Length: {len(body)}\r\n\r\n".encode("ascii") p.stdin.write(headers + body) p.stdin.flush() except Exception as e: print(f"Error writing message: {e}", file=sys.stderr) raise def read_cl(p): """Read content-length framed message with proper error handling""" try: # Read headers headers = b"" while True: line = p.stdout.readline() if not line: # Return JSON-RPC error instead of raising exception return {"jsonrpc":"2.0","id":None,"error":{"code":-32603,"message":"EOF reading headers"}} if line in (b"\n", b"\r\n"): break headers += line m = re.search(br"Content-Length:\s*(\d+)", headers, flags=re.I) if not m: return {"jsonrpc":"2.0","id":None,"error":{"code":-32603,"message":"No Content-Length header from child"}} length = int(m.group(1)) body = p.stdout.read(length) if len(body) != length: return {"jsonrpc":"2.0","id":None,"error":{"code":-32603,"message":"Incomplete body read"}} return json.loads(body.decode("utf-8", "replace")) except json.JSONDecodeError as e: return {"jsonrpc":"2.0","id":None,"error":{"code":-32700,"message":f"Parse error: {str(e)}"}} except Exception as e: return {"jsonrpc":"2.0","id":None,"error":{"code":-32603,"message":f"Internal error: {str(e)}"}} if __name__ == "__main__": print("Navigate (content-length)...") env = os.environ.copy() env["MCP_FRAMING"] = "content-length" env["HEADLESS"] = "true" env["PYTHONUNBUFFERED"] = "1" # Proper subprocess management with context manager with run_bridge(env) as p: try: time.sleep(0.2) write_cl(p, {"jsonrpc":"2.0","id":"nav-1","method":"browser.navigate","params":{"url":"https://example.com"}}) resp = read_cl(p) print("Response:", json.dumps(resp, indent=2)[:MAX_RESPONSE_CHARS], "...") write_cl(p, {"jsonrpc":"2.0","id":"bye-1","method":"mcp.shutdown","params":{}}) resp2 = read_cl(p) print("Shutdown:", json.dumps(resp2, indent=2)[:MAX_RESPONSE_CHARS], "...") finally: # Ensure proper cleanup try: if p.stdin is not None and not p.stdin.closed: p.stdin.close() except Exception: pass try: p.wait(timeout=10) except subprocess.TimeoutExpired: p.terminate() try: p.wait(timeout=5) except subprocess.TimeoutExpired: p.kill()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fayeblade1488/Fayeblade_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server