#!/bin/sh
# websearch - simple web search for Bantam via Exa's MCP server (Streamable HTTP).
#
# Talks to https://mcp.exa.ai/mcp using the JSON-RPC MCP protocol:
#   1. initialize                 -> obtains an Mcp-Session-Id from response headers
#   2. notifications/initialized  -> no reply
#   3. tools/call (web_search_exa) -> prints the formatted result text
#
# Usage:
#   websearch "your query"
#   websearch "your query" [num_results]
#
# Environment:
#   EXA_MCP_ENDPOINT  optional; default https://mcp.exa.ai/mcp
#   EXA_API_KEY       optional; if set, sent as an URL query parameter (?api_key=)
#                    so that NO extra HTTP headers are added beyond Content-Type.
#
# Dependencies: curl, jq.

set -eu

if [ "$#" -lt 1 ]; then
  echo "Usage: websearch \"query\" [num_results]" >&2
  exit 1
fi

QUERY="$1"
NUM="${2:-5}"

ENDPOINT="${EXA_MCP_ENDPOINT:-https://mcp.exa.ai/mcp}"

# Append API key as a query parameter (no extra headers).
if [ -n "${EXA_API_KEY:-}" ]; then
  URL="${ENDPOINT}?api_key=${EXA_API_KEY}"
else
  URL="${ENDPOINT}"
fi

# Build the tools/call arguments JSON safely (proper query escaping).
ARGS=$(jq -n --arg q "$QUERY" --argjson n "$NUM" \
  '{query:$q, numResults:$n}')

# --- Step 1: initialize, capture headers (for Mcp-Session-Id) and body. ---
INIT_HEADERS=$(mktemp)
INIT_BODY=$(mktemp)
curl -s -D "$INIT_HEADERS" -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"websearch","version":"1.0"}}}' \
  > "$INIT_BODY"

SID=$(grep -i '^mcp-session-id:' "$INIT_HEADERS" | tr -d '\r' | awk '{print $2}')
if [ -z "$SID" ]; then
  echo "websearch: failed to obtain MCP session id" >&2
  cat "$INIT_BODY" >&2
  rm -f "$INIT_HEADERS" "$INIT_BODY"
  exit 1
fi

# --- Step 2: send initialized notification (fire and forget). ---
curl -s -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SID" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null

# --- Step 3: call web_search_exa and extract the text result. ---
CALL_BODY=$(mktemp)
curl -s -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SID" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"web_search_exa\",\"arguments\":$ARGS}}" \
  > "$CALL_BODY"

# Parse the response: take the last "data:" SSE payload (or the whole body
# if it is plain JSON) and print the text blocks from the result.
DATA=$(grep -E '^data:[[:space:]]' "$CALL_BODY" | tail -n1 | sed 's/^data:[[:space:]]*//')
if [ -z "$DATA" ]; then
  DATA=$(cat "$CALL_BODY")
fi

if [ -z "$DATA" ]; then
  echo "websearch: no response from MCP server" >&2
  rm -f "$INIT_HEADERS" "$INIT_BODY" "$CALL_BODY"
  exit 1
fi

# Surface server/protocol errors, then emit text content.
ERROR_MSG=$(printf '%s' "$DATA" | jq -r 'if .error then (.error|tostring) else empty end')
if [ -n "$ERROR_MSG" ]; then
  echo "websearch error: $ERROR_MSG" >&2
  rm -f "$INIT_HEADERS" "$INIT_BODY" "$CALL_BODY"
  exit 1
fi

printf '%s' "$DATA" | jq -r '
  (.result.content // [])
  | map(select(.type == "text"))
  | map(.text)
  | .[]
'

rm -f "$INIT_HEADERS" "$INIT_BODY" "$CALL_BODY"

exit 0
