Add Exa connector: mcp_remote, neural web search, optional API key (free tier), verify.py with MCP initialize probe

This commit is contained in:
2026-07-19 14:13:28 +01:00
parent b83b2feb0f
commit 341e4382c8
5 changed files with 160 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
#!/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()