"""Run with project dependencies: PYTHONPATH=examples python examples/mcp_client.py [base]
Official SDK performs protocol negotiation. HTTP runtime uploads, model never sees raw file.
"""
import asyncio
import os
import sys
import time
from uuid import uuid4
import httpx2
from urllib.parse import urlparse
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
from http_client import Client

async def main(base):
    http=Client(base,".runtime/mcp-client.json")
    resume='--resume' in sys.argv[2:]
    job=await asyncio.to_thread(http.resume) if resume else None
    source=None if resume else http.request('POST','/v1/resources',{'format':'text','content':'Retries stop after three attempts.\n\nTimeout is 30 seconds.'})
    headers={'X-MarginNook-Staging':os.environ['MARGINNOOK_STAGING_TOKEN']} if os.environ.get('MARGINNOOK_STAGING_TOKEN') else {}
    async with httpx2.AsyncClient(headers=headers, timeout=httpx2.Timeout(180,connect=15), follow_redirects=False, trust_env=urlparse(base).hostname not in {'127.0.0.1','localhost','::1'}) as transport:
      async with streamable_http_client(base.rstrip('/')+'/mcp/', http_client=transport) as (read,write,*_):
        async with ClientSession(read,write) as session:
            await session.initialize()
            tools=await session.list_tools()
            assert {'aggregate','search_document','test_failures','read_evidence'} <= {t.name for t in tools.tools}
            if resume:
                evidence=await session.call_tool('read_evidence',{'resource_id':job['result']['normalized_source_resource']['id']})
                if not evidence.structured_content or evidence.structured_content.get('error'):
                    raise RuntimeError('Saved task evidence unavailable')
                print('MCP Python: saved task resumed and evidence read; no new upload or key')
                return
            arguments={'resource_id':source['id'],'query':'retry timeout','idempotency_key':str(uuid4())}
            http.save(source=source,key=arguments['idempotency_key'],arguments=arguments,job_id=None,
                      body={'tool':'document.search','resource_id':source['id'],'arguments':{'query':'retry timeout'}})
            deadline=time.monotonic()+180
            async with asyncio.timeout_at(deadline):
                call=await session.call_tool('search_document',arguments)
            job=call.structured_content
            if job and job.get('id'):http.save(job_id=job['id'])
            if job and job.get('status')=='pending':
                job=await asyncio.to_thread(http.wait,job,deadline)
            if not job or job.get('error') or job['status']!='completed':
                raise RuntimeError('MCP call did not complete; use HTTP client runtime with retained job ID.')
            evidence=await session.call_tool('read_evidence',{'resource_id':job['result']['normalized_source_resource']['id']})
            assert '30 seconds' in evidence.structured_content['text']
            replay=await session.call_tool('search_document',arguments)
            assert replay.structured_content['id']==job['id']
            bad=await session.call_tool('read_evidence',{'resource_id':'invalid-handle'})
            assert bad.structured_content['error']['code']=='NOT_FOUND'
    http.request('DELETE','/v1/resources/'+source['id'])
    print('MCP Python SDK: discovery, call, evidence, replay and structured error verified')

if __name__=='__main__':
    asyncio.run(main(sys.argv[1] if len(sys.argv)>1 else 'http://127.0.0.1:8000'))
