import base64,hashlib,ipaddress,json,os,socket,sys,urllib.request,urllib.error
from pathlib import Path
from urllib.parse import urlsplit
BASE='https://api.quickrouter.ai'
ROOT=Path(os.environ.get('QUICKROUTER_MCP_STATE','.quickrouter-video-state')).resolve();ROOT.mkdir(parents=True,exist_ok=True)
KEY=Path(os.environ['QUICKROUTER_TEST_KEY_FILE']).read_text().strip()
def save(p,x):p.write_text(json.dumps(x,ensure_ascii=False,indent=2).replace(KEY,'<REDACTED>')+'\n')
def api(path,body=None):
 req=urllib.request.Request(BASE+path,data=json.dumps(body).encode() if body is not None else None,headers={'Authorization':'Bearer '+KEY,'Content-Type':'application/json'})
 class Locked(urllib.request.HTTPRedirectHandler):
  def redirect_request(self,*args,**kwargs):raise ValueError('API redirect refused')
 with urllib.request.build_opener(Locked).open(req,timeout=240) as r:return json.load(r)
def public_url(url):
 p=urlsplit(url)
 if p.scheme!='https' or p.username or p.password or not p.hostname:raise ValueError('HTTPS public result required')
 if any(not ipaddress.ip_address(x[4][0]).is_global for x in socket.getaddrinfo(p.hostname,p.port or 443,type=socket.SOCK_STREAM)):raise ValueError('Private result address refused')
 return url
TOOLS=[{'name':'create_video','description':'Submit once per request_key; repeat returns saved task, unknown submission never retries.','inputSchema':{'type':'object','properties':{'request_key':{'type':'string','pattern':'^[a-z0-9-]{1,40}$'},'prompt':{'type':'string','minLength':1}},'required':['request_key','prompt'],'additionalProperties':False}}, {'name':'read_task','description':'Read a task recorded by create_video.','inputSchema':{'type':'object','properties':{'request_key':{'type':'string'}},'required':['request_key'],'additionalProperties':False}}, {'name':'download_result','description':'Download only the succeeded result of a recorded task; never accept arbitrary URLs.','inputSchema':{'type':'object','properties':{'request_key':{'type':'string'}},'required':['request_key'],'additionalProperties':False}}]
def call(name,args):
 import re
 key=args.get('request_key','')
 if not re.fullmatch('[a-z0-9-]{1,40}',key):raise ValueError('Invalid request_key')
 state=ROOT/(key+'.json')
 if name=='create_video':
  prompt=args['prompt'];digest=hashlib.sha256(prompt.encode()).hexdigest()
  if state.exists():
   d=json.loads(state.read_text())
   if d.get('input_sha256')!=digest:raise ValueError('request_key already belongs to different input')
   return {'reused':True,'task_id':d.get('task_id'),'submission':d['submission']}
  save(state,{'submission':'unknown','input_sha256':digest})
  d=api('/api/v3/contents/generations/tasks',{'model':'doubao-seedance-2-0-mini-260615','content':[{'type':'text','text':prompt}],'duration':4,'resolution':'720p','ratio':'16:9','generate_audio':False})
  if not d.get('id'):raise ValueError('Missing task id; inspect journal before any resubmission')
  save(state,{'submission':'accepted','input_sha256':digest,'task_id':d['id']});return {'reused':False,'task_id':d['id'],'submission':'accepted'}
 if not state.exists():raise ValueError('Unknown request_key')
 d=json.loads(state.read_text());tid=d.get('task_id')
 if not tid:raise ValueError('Unknown submission; manual reconciliation required')
 result=api('/api/v3/contents/generations/tasks/'+tid);save(ROOT/(key+'-response.json'),result)
 if name=='read_task':return {'task_id':tid,'status':result.get('status'),'usage':result.get('usage')}
 if name=='download_result':
  if result.get('status')!='succeeded':raise ValueError('Task not succeeded; do not download')
  url=public_url(result['content']['video_url'])
  class PublicRedirect(urllib.request.HTTPRedirectHandler):
   def redirect_request(self,req,fp,code,msg,headers,newurl):return super().redirect_request(req,fp,code,msg,headers,public_url(newurl))
  with urllib.request.build_opener(PublicRedirect).open(url,timeout=60) as r:data=r.read(80*1024*1024+1)
  if len(data)>80*1024*1024:raise ValueError('Output over 80 MiB limit')
  p=ROOT/(key+'.mp4');p.write_bytes(data)
  return {'file':p.name,'bytes':len(data),'sha256':hashlib.sha256(data).hexdigest(),'task_id':tid}
 raise ValueError('Unknown tool')
for line in sys.stdin:
 try:
  req=json.loads(line);method=req['method'];rid=req.get('id')
  if method=='initialize':result={'protocolVersion':'2024-11-05','capabilities':{'tools':{}},'serverInfo':{'name':'quickrouter-video-journal','version':'1.0.0'}}
  elif method=='tools/list':result={'tools':TOOLS}
  elif method=='tools/call':result={'content':[{'type':'text','text':json.dumps(call(req['params']['name'],req['params'].get('arguments',{})),ensure_ascii=False)}]}
  elif rid is None:continue
  else:raise ValueError('Unsupported method')
  print(json.dumps({'jsonrpc':'2.0','id':rid,'result':result}),flush=True)
 except Exception as e:
  print(json.dumps({'jsonrpc':'2.0','id':req.get('id') if 'req' in locals() else None,'error':{'code':-32000,'message':str(e).replace(KEY,'<REDACTED>')}}),flush=True)
