#!/usr/bin/env python3 """Verify connectivity to Exa's hosted MCP server. Reads exaApiKey from the environment (optional — Exa works in free tier without one), sends a lightweight JSON-RPC initialize to https://mcp.exa.ai/mcp, and prints a single JSON object: {"ok": true, "message": "Exa MCP endpoint is reachable"} {"ok": false, "message": "Exa MCP endpoint is unreachable: "} The API key is never printed. HTTP-level verification only — no search queries. stdlib only (urllib). """ import json import os import sys import urllib.error import urllib.request def _result(ok, message): print(json.dumps({"ok": ok, "message": message})) sys.exit(0 if ok else 1) def main(): api_key = os.environ.get("exaApiKey", "").strip() # Also accept UPPER_SNAKE form if not api_key: api_key = os.environ.get("EXA_API_KEY", "").strip() url = "https://mcp.exa.ai/mcp" if api_key: url += f"?exaApiKey={api_key}" body = json.dumps({ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-03-26", "capabilities": {}, "clientInfo": {"name": "skald-verify", "version": "1.0.0"}, }, }).encode("utf-8") req = urllib.request.Request( url, data=body, headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(req, timeout=15) as resp: if 200 <= resp.status < 300: label = "with API key" if api_key else "free tier" _result(True, f"Exa MCP endpoint is reachable ({label})") _result(False, f"Exa returned HTTP {resp.status}") except urllib.error.HTTPError as e: if e.code in (401, 403): _result(False, "Exa API key is invalid or unauthorized " f"(HTTP {e.code})") _result(False, f"Exa returned HTTP {e.code}: {e.reason}") except Exception as e: _result(False, f"Exa MCP endpoint is unreachable: {e}") if __name__ == "__main__": main()