"""Exact fixed context cost per tool, in Claude tokens (messages.count_tokens, model claude-opus-5-5)."""
import asyncio, json, anthropic
from mcp import ClientSession
from mcp.client.stdio import stdio_client, StdioServerParameters
client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY
MSG = [{"role": "user", "content": "Open example.com and tell me its title."}]
SERVERS = {"playwright-mcp": ["@playwright/mcp", "--headless", "--isolated"],
           "agent-browser-mcp": ["agent-browser", "mcp"],
           "devtools-mcp": ["chrome-devtools-mcp", "--headless", "--isolated", "--no-usage-statistics", "--no-performance-crux"]}
AB_TOOL = {"name": "agent_browser", "description": "Run one agent-browser CLI command. Pass everything after `agent-browser`, for example `open https://example.com` or `snapshot -i`.",
           "input_schema": {"type": "object", "properties": {"args": {"type": "string"}}, "required": ["args"]}}
async def mcp_tools(args):
    async with stdio_client(StdioServerParameters(command="npx", args=args)) as (r, w):
        async with ClientSession(r, w) as s:
            await s.initialize()
            return [{"name": t.name, "description": t.description or "", "input_schema": t.input_schema} for t in (await s.list_tools()).tools]
async def main():
    base = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG).input_tokens
    out = {"baseline_message": base}
    for name, args in SERVERS.items():
        tools = await mcp_tools(args); json.dump(tools, open(f"tools_{name}.json", "w"), indent=1)
        n = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG, tools=tools).input_tokens
        out[name] = {"tools": len(tools), "overhead_tokens": n - base}
    skill = open("ab_skill_core.md").read()
    n = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG, tools=[AB_TOOL], system=skill).input_tokens
    n_tool_only = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG, tools=[AB_TOOL]).input_tokens
    out["agent-browser"] = {"tools": 1, "overhead_tokens_with_core_skill": n - base, "overhead_tokens_tool_only": n_tool_only - base}
    lite = open("phase_b.py").read().split("LITE = ")[1].split("# agent-browser-agentsmd")[0]
    lite = eval(lite.strip())
    agents_md = eval(open("phase_b.py").read().split("AGENTS_MD = ")[1].split("AB_TOOL")[0].strip())
    n_md = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG, tools=[AB_TOOL], system=agents_md).input_tokens
    out["agent-browser"]["overhead_tokens_with_agents_md"] = n_md - base
    n_lite = client.messages.count_tokens(model="claude-opus-5-5", messages=MSG, tools=[AB_TOOL], system=lite).input_tokens
    out["agent-browser"]["overhead_tokens_with_3_rules"] = n_lite - base
    json.dump(out, open("overhead.json", "w"), indent=1)
    rows = [("Playwright MCP 0.0.83", out["playwright-mcp"]["tools"], out["playwright-mcp"]["overhead_tokens"]),
            ("Chrome DevTools MCP 1.12.0", out["devtools-mcp"]["tools"], out["devtools-mcp"]["overhead_tokens"]),
            ("agent-browser 0.39.3 MCP, core tools", out["agent-browser-mcp"]["tools"], out["agent-browser-mcp"]["overhead_tokens"]),
            ("agent-browser 0.39.3 + core skill", 1, n - base),
            ("agent-browser 0.39.3 + AGENTS.md block", 1, n_md - base),
            ("agent-browser 0.39.3 + 3 rules", 1, n_lite - base),
            ("agent-browser 0.39.3, tool only", 1, n_tool_only - base)]
    print(f"{"setup":<40}{'tools':>6}{'tokens':>9}")
    for name, t, k in rows:
        print(f"{name:<40}{t:>6}{k:>9,}")
asyncio.run(main())
