#!/usr/bin/env bash
# Bash, curl 7.76+, Python 3. Set AMAZINGCAT_TOKEN in the environment; bash curl.sh.
set -euo pipefail
: "${AMAZINGCAT_TOKEN:?Set AMAZINGCAT_TOKEN in the server environment}"
umask 077
work=$(mktemp -d)
endpoint='https://mcp.amazingcat.net/mcp'
cleanup() {
  if [[ -f "$work/session-headers" ]]; then
    curl --silent --show-error --max-time 15 -X DELETE \
      -H "@$work/session-headers" "$endpoint" -o /dev/null || true
  fi
  rm -rf "$work"
}
trap cleanup EXIT

# Keep credentials out of curl's command-line arguments and temporary public files.
python3 - "$work/headers" <<'PY'
import os, pathlib, sys
token = os.environ["AMAZINGCAT_TOKEN"]
if "\r" in token or "\n" in token:
    raise SystemExit("Invalid token")
pathlib.Path(sys.argv[1]).write_text(
    "Authorization: Bearer " + token + "\n"
    "Accept: application/json, text/event-stream\n"
    "Content-Type: application/json\n", encoding="utf-8")
PY

# Decode either JSON or UTF-8 SSE. In SSE, select the matching JSON-RPC id.
cat > "$work/decode.py" <<'PY'
import json, pathlib, sys
body = pathlib.Path(sys.argv[1]).read_text(encoding="utf-8")
expected_id = int(sys.argv[2])
if body.lstrip().startswith("{"):
    message = json.loads(body)
else:
    message = None
    data = []
    for line in body.splitlines() + [""]:
        if line.startswith("data:"):
            data.append(line[5:].lstrip(" "))
        elif not line and data:
            event = json.loads("\n".join(data))
            data = []
            if event.get("id") == expected_id:
                message = event
                break
    if message is None:
        raise SystemExit("SSE ended without the matching JSON-RPC response")
if message.get("id") != expected_id or "error" in message:
    raise SystemExit("Unexpected JSON-RPC response or protocol error")
json.dump(message["result"], sys.stdout, ensure_ascii=False)
PY

post() {
  local name=$1 payload=$2 expected_id=${3:-}
  curl --silent --show-error --fail-with-body --no-buffer --max-time 120 \
    -X POST "$endpoint" -H "@$work/headers" \
    --data-binary "$payload" -D "$work/$name.headers" \
    -o "$work/$name.body" -w '%{http_code}' > "$work/$name.status"
  if [[ -n "$expected_id" ]]; then
    python3 "$work/decode.py" "$work/$name.body" "$expected_id" > "$work/$name.json"
  elif [[ "$(cat "$work/$name.status")" != 202 ]]; then
    echo 'Initialized notification was not accepted' >&2
    exit 1
  fi
}

post initialize '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"amazingcat-curl-example","version":"1.0"}}}' 1

# Preserve Mcp-Session-Id if supplied; use the negotiated protocol version.
python3 - "$work" <<'PY'
import json, pathlib, sys
work = pathlib.Path(sys.argv[1])
headers = work.joinpath("headers").read_text(encoding="utf-8")
sid = None
for line in work.joinpath("initialize.headers").read_text(encoding="utf-8").splitlines():
    if line.lower().startswith("mcp-session-id:"):
        sid = line.split(":", 1)[1].strip()
if sid:
    headers += "Mcp-Session-Id: " + sid + "\n"
version = json.loads(work.joinpath("initialize.json").read_text(encoding="utf-8"))["protocolVersion"]
headers += "MCP-Protocol-Version: " + version + "\n"
work.joinpath("headers").write_text(headers, encoding="utf-8")
if sid:
    work.joinpath("session-headers").write_text(headers, encoding="utf-8")
PY

post initialized '{"jsonrpc":"2.0","method":"notifications/initialized"}'
post tools-list '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' 2
post tools-call '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"kas_search","arguments":{"text":"восстановление OR пропуск","norms":"ГПК 112","year_from":2026,"year_to":2026,"court":2,"kind":"civil","limit":1,"detail":"brief"}}}' 3

# A 200 response may contain a quota/application error; check the MCP result too.
python3 - "$work" <<'PY'
import json, pathlib, sys
work = pathlib.Path(sys.argv[1])
read = lambda name: json.loads(work.joinpath(name + ".json").read_text(encoding="utf-8"))
result = read("tools-call")
if result.get("isError"):
    raise SystemExit("Tool returned an MCP error; inspect it privately")
texts = [b["text"] for b in result.get("content", []) if b.get("type") == "text"]
if not texts:
    raise SystemExit("Tool returned no text content")
try:
    data = json.loads(texts[0])
except json.JSONDecodeError:
    raise SystemExit("Tool returned non-JSON text; check quota/errors") from None
if not isinstance(data, dict) or data.get("error") or data.get("ошибка"):
    raise SystemExit("Tool returned an application error")
types = {}
for name in ("initialize", "tools-list", "tools-call"):
    for line in work.joinpath(name + ".headers").read_text(encoding="utf-8").splitlines():
        if line.lower().startswith("content-type:"):
            types[name] = line.split(":", 1)[1].strip()
print(json.dumps({
    "protocol_version": read("initialize")["protocolVersion"],
    "session_present": work.joinpath("session-headers").exists(),
    "tools_count": len(read("tools-list")["tools"]),
    "tool": "kas_search", "is_error": bool(result.get("isError")),
    "найдено": data.get("найдено"), "returned": len(data.get("результаты", [])),
    "response_content_types": types,
    "http_status": {name: int(work.joinpath(name + ".status").read_text())
                    for name in ("initialize", "initialized", "tools-list", "tools-call")},
}, ensure_ascii=False))
PY
