"""How many tokens do MCP tool definitions add to an agent's context before the first
question? Connect to each server over stdio, list its tools, and count the tokens of
the definitions the agent receives (name, description and input schema as JSON).
Tokens are counted with OpenAI's o200k_base tokenizer, so other models will differ a little.
Run on October 12, 2026, from Mumbai.
Run with: uv run --with mcp --with tiktoken python measure.py"""
import asyncio
import json

import tiktoken
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

enc = tiktoken.get_encoding("o200k_base")
SERVERS = {
    "Playwright MCP": ("npx", ["-y", "@playwright/mcp@0.0.83", "--headless"]),
    "Chrome DevTools MCP": ("npx", ["-y", "chrome-devtools-mcp@1.10.1", "--headless"]),
    "Filesystem": ("npx", ["-y", "@modelcontextprotocol/server-filesystem@1.0.0", "/tmp"]),
    "Fetch": ("uvx", ["mcp-server-fetch"]),
    "Git": ("uvx", ["mcp-server-git"]),
    "Everything (reference)": ("npx", ["-y", "@modelcontextprotocol/server-everything@1.0.0"]),
}


async def tools_of(cmd, args):
    async with stdio_client(StdioServerParameters(command=cmd, args=args)) as (r, w):
        async with ClientSession(r, w) as s:
            await s.initialize()
            return (await s.list_tools()).tools


async def main():
    out = {}
    for name, (cmd, args) in SERVERS.items():
        tools = await tools_of(cmd, args)
        defs = [{"name": t.name, "description": t.description or "", "input_schema": t.input_schema} for t in tools]
        per_tool = {d["name"]: len(enc.encode(json.dumps(d))) for d in defs}
        out[name] = {"tools": len(defs), "tokens": sum(per_tool.values()), "per_tool": per_tool}
        print(f"{name:24} {len(defs):3} tools {sum(per_tool.values()):7,} tokens")
    json.dump(out, open("results.json", "w"), indent=1)
    print(f"{'All six':24} {sum(v['tools'] for v in out.values()):3} tools {sum(v['tokens'] for v in out.values()):7,} tokens")


asyncio.run(main())
