71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
#!/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: <reason>"}
|
|
|
|
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()
|