#!/usr/bin/env python3
"""Minimal stdio MCP server for APIMART discovery and verified execution."""
from __future__ import annotations
import json,os,sys
from apimart_cli import MODEL,estimate_cost,find_guides,generate,list_models,model_info,task_status
TOOLS=[
 {'name':'apimart_list_models','description':'List all APIMART model discovery records and identify models with verified execution support.','inputSchema':{'type':'object','properties':{}}},
 {'name':'apimart_model_info','description':'Return an APIMART model hub, evidence guides and verified execution metadata when available.','inputSchema':{'type':'object','properties':{'model':{'type':'string'}}}},
 {'name':'apimart_find_guides','description':'Find observation-dated pricing, limits or commercial-policy guides for an APIMART model.','inputSchema':{'type':'object','required':['model'],'properties':{'model':{'type':'string'},'intent':{'enum':['pricing','limits','commercial_policy']}}}},
 {'name':'apimart_estimate_video_cost','description':'Estimate verified APIMART Seedance 2.5 cost in USD.','inputSchema':{'type':'object','required':['resolution','duration'],'properties':{'resolution':{'enum':['480p','720p','1080p']},'duration':{'type':'integer'},'input_video_seconds':{'type':'number','minimum':0}}}},
 {'name':'apimart_generate_video','description':'Build or explicitly execute a verified Seedance 2.5 generation request. Paid execution requires execute=true and APIMART_API_KEY.','inputSchema':{'type':'object','required':['prompt'],'properties':{'prompt':{'type':'string'},'resolution':{'enum':['480p','720p','1080p']},'duration':{'type':'integer'},'size':{'type':'string'},'moderate':{'type':'boolean'},'execute':{'type':'boolean'}}}},
 {'name':'apimart_get_task','description':'Get an APIMART asynchronous task by task_id.','inputSchema':{'type':'object','required':['task_id'],'properties':{'task_id':{'type':'string'},'language':{'type':'string'}}}},
]
def text_result(value:object)->dict:return {'content':[{'type':'text','text':json.dumps(value,ensure_ascii=False,indent=2)}]}
def call_tool(name:str,a:dict)->dict:
 if name=='apimart_list_models':return text_result(list_models())
 if name=='apimart_model_info':return text_result(model_info(a.get('model',MODEL)))
 if name=='apimart_find_guides':return text_result(find_guides(a['model'],a.get('intent')))
 if name=='apimart_estimate_video_cost':return text_result(estimate_cost(a['resolution'],int(a['duration']),float(a.get('input_video_seconds',0))))
 if name=='apimart_generate_video':
  payload={'model':MODEL,'prompt':a['prompt'],'resolution':a.get('resolution','720p'),'duration':int(a.get('duration',5)),'size':a.get('size','adaptive'),'nsfw_check':bool(a.get('moderate',False))}; estimate=estimate_cost(payload['resolution'],payload['duration'])
  if not a.get('execute',False):return text_result({'dry_run':True,'payload':payload,'cost':estimate,'next':'Set execute=true to submit'})
  return text_result(generate(payload,os.getenv('APIMART_API_KEY','')))
 if name=='apimart_get_task':return text_result(task_status(a['task_id'],os.getenv('APIMART_API_KEY',''),a.get('language','en')))
 raise ValueError(f'Unknown tool: {name}')
def handle(msg:dict)->dict|None:
 method,ident=msg.get('method'),msg.get('id')
 if method=='notifications/initialized':return None
 if method=='initialize':result={'protocolVersion':'2025-03-26','capabilities':{'tools':{}},'serverInfo':{'name':'apimart-agent-toolkit','version':'0.2.0'}}
 elif method=='tools/list':result={'tools':TOOLS}
 elif method=='tools/call':
  p=msg.get('params',{});result=call_tool(p.get('name',''),p.get('arguments',{}))
 else:return {'jsonrpc':'2.0','id':ident,'error':{'code':-32601,'message':'Method not found'}}
 return {'jsonrpc':'2.0','id':ident,'result':result}
def read_message(stream)->dict|None:
 first=stream.readline()
 if not first:return None
 if first.lstrip().startswith(b'{'):return json.loads(first)
 headers={};line=first
 while line not in (b'\r\n',b'\n',b''):
  k,v=line.decode().split(':',1);headers[k.lower()]=v.strip();line=stream.readline()
 return json.loads(stream.read(int(headers['content-length'])))
def write_message(stream,msg:dict)->None:
 body=json.dumps(msg,ensure_ascii=False,separators=(',',':')).encode();stream.write(f'Content-Length: {len(body)}\r\n\r\n'.encode()+body);stream.flush()
def main()->None:
 while True:
  msg=read_message(sys.stdin.buffer)
  if msg is None:return
  try:response=handle(msg)
  except Exception as exc:response={'jsonrpc':'2.0','id':msg.get('id'),'error':{'code':-32603,'message':str(exc)}}
  if response is not None:write_message(sys.stdout.buffer,response)
if __name__=='__main__':main()
