"""Visibility probe: a tiny stdio MCP server (protocol 2025-11-25 style, newline-delimited JSON-RPC).
Each tool returns a different result shape carrying a unique CODE so we can see which channel reaches the model."""
import base64, json, os, sys

LOG = os.environ.get("PROBE_LOG", "probe-server.log")
UNLISTED = "probe://secret/unlisted-report"
LISTED = "probe://catalog/listed-report"
BODIES = {UNLISTED: "CODE: LINK-UNLISTED-8888 (body behind the unlisted link)",
          LISTED: "CODE: LINK-LISTED-8889 (body behind the listed link)"}

def tx(t, **kw): return {"type": "text", "text": t, **kw}

RESULTS = {
 "text": lambda: {"content": [tx("CODE: TEXT-1001")]},
 "json_text": lambda: {"content": [tx(json.dumps({"code": "JSONTEXT-1002"}))]},
 "structured_only": lambda: {"content": [], "structuredContent": {"code": "STRUCT-ONLY-2001"}},
 "structured_and_text_same": lambda: {"content": [tx(json.dumps({"code": "SAME-2002"}))], "structuredContent": {"code": "SAME-2002"}},
 "structured_and_text_diff": lambda: {"content": [tx("CODE: CONTENT-SIDE-2003")], "structuredContent": {"code": "STRUCT-SIDE-2004"}},
 "embedded_text": lambda: {"content": [{"type": "resource", "resource": {"uri": "probe://emb/text", "mimeType": "text/plain", "text": "CODE: EMB-TEXT-3001"}}]},
 "embedded_blob": lambda: {"content": [{"type": "resource", "resource": {"uri": "probe://emb/blob", "mimeType": "text/plain", "blob": base64.b64encode(b"CODE: EMB-BLOB-3002").decode()}}]},
 "link_unlisted": lambda: {"content": [{"type": "resource_link", "uri": UNLISTED, "name": "unlisted-report.txt", "description": "DESC-CODE-4001 report body is behind this link", "mimeType": "text/plain"}]},
 "link_listed": lambda: {"content": [{"type": "resource_link", "uri": LISTED, "name": "listed-report.txt", "description": "DESC-CODE-4002 report body is behind this link", "mimeType": "text/plain"}]},
 "audience_user_only": lambda: {"content": [tx("CODE: USERONLY-5001", annotations={"audience": ["user"]}), tx("CODE: ASSISTANT-5002", annotations={"audience": ["assistant"]})]},
 "is_error_structured": lambda: {"isError": True, "content": [tx("CODE: ERRTEXT-6001")], "structuredContent": {"code": "ERRSTRUCT-6002"}},
 "big_66k": lambda: {"content": [tx("CODE: BIGHEAD-7101\n" + ("filler line for size test. " * 40 + "\n") * 60 + "CODE: BIGTAIL-7102")]},
 "big_155k": lambda: {"content": [tx("CODE: BIGHEAD-7201\n" + ("filler line for size test. " * 40 + "\n") * 140 + "CODE: BIGTAIL-7202")]},
 "big_10k": lambda: {"content": [tx("CODE: BIGHEAD-10\n" + ("x" * 999 + "\n") * 9 + "CODE: BIGTAIL-10")]},
 "big_25k": lambda: {"content": [tx("CODE: BIGHEAD-25\n" + ("x" * 999 + "\n") * 24 + "CODE: BIGTAIL-25")]},
 "big_40k": lambda: {"content": [tx("CODE: BIGHEAD-40\n" + ("x" * 999 + "\n") * 39 + "CODE: BIGTAIL-40")]},
}

def log(o):
    with open(LOG, "a") as f: f.write(json.dumps(o, ensure_ascii=False) + "\n")

def handle(req):
    m, p = req.get("method"), req.get("params") or {}
    if m == "initialize":
        log({"initialize_protocolVersion": p.get("protocolVersion"), "clientInfo": p.get("clientInfo"), "capabilities": p.get("capabilities")})
        return {"protocolVersion": p.get("protocolVersion"), "capabilities": ({"tools": {}} if os.environ.get("NORES") else {"tools": {}, "resources": {}}), "serverInfo": {"name": "probe", "version": "1.0.0"}}
    if m == "tools/list":
        tools = []
        for n in RESULTS:
            t = {"name": n, "description": f"Probe tool {n}. Takes no arguments.", "inputSchema": {"type": "object", "properties": {}}}
            if n.startswith("structured") or n == "is_error_structured":
                t["outputSchema"] = {"type": "object", "properties": {"code": {"type": "string"}}, "required": ["code"]}
            tools.append(t)
        return {"tools": tools}
    if m == "tools/call":
        log({"tools_call": p.get("name")})
        return RESULTS[p["name"]]()
    if m == "resources/list":
        log({"resources_list": True})
        return {"resources": [{"uri": LISTED, "name": "listed-report.txt", "mimeType": "text/plain"}]}
    if m == "resources/templates/list": return {"resourceTemplates": []}
    if m == "resources/read":
        log({"resources_read": p.get("uri")})
        if p.get("uri") in BODIES: return {"contents": [{"uri": p["uri"], "mimeType": "text/plain", "text": BODIES[p["uri"]]}]}
        raise KeyError("not found")
    if m == "ping": return {}
    return None

for line in sys.stdin:
    req = json.loads(line)
    if "id" not in req: continue
    try:
        r = handle(req)
        resp = {"jsonrpc": "2.0", "id": req["id"], "result": r} if r is not None else {"jsonrpc": "2.0", "id": req["id"], "error": {"code": -32601, "message": "Method not found"}}
    except KeyError:
        resp = {"jsonrpc": "2.0", "id": req["id"], "error": {"code": -32002, "message": "Resource not found"}}
    sys.stdout.write(json.dumps(resp) + "\n"); sys.stdout.flush()
