Add SerpAPI Flights connector: mcp_remote, flight search via Google Flights, verify.py with MCP initialize probe
This commit is contained in:
@@ -470,6 +470,7 @@ sudo find /var/www/connectors.skaldagent.net/ -type f -exec chmod 644 {} \;
|
||||
| `tavily` | Tavily | `mcp_remote` | `global` | api_key (`{SECRET:tavilyApiKey}` in URL) | `verify.py` (HTTP probe `/search`) |
|
||||
| `gmail` | Gmail | `mcp_local` | `user` | oauth2 (Google) + deliver: `env/google_authorized_user` (via `GMAIL_CREDS_JSON`) | ⏳ Fase 2 — OAuth via loopback listener |
|
||||
| `gcal` | Google Calendar | `mcp_local` | `user` | oauth2 (Google) + deliver: `env/google_authorized_user` (via `GCAL_CREDS_JSON`) | `verify.py` (creds load + API probe) |
|
||||
| `drive` | Google Drive | `mcp_local` | `user` | oauth2 (Google) + deliver: `env/google_authorized_user` (via `DRIVE_CREDS_JSON`) | `verify.py` (creds load + Drive API probe) |
|
||||
| `email` | Email (IMAP/SMTP) | `mcp_local` | `user` | password (env) | `verify.py` (IMAP+SMTP probe) |
|
||||
| `firecrawl` | Firecrawl | `mcp_local` | `global` | api_key (env) | — |
|
||||
| `http-fetch` | HTTP Fetch | `mcp_local` | `global` | none | — |
|
||||
@@ -477,6 +478,6 @@ sudo find /var/www/connectors.skaldagent.net/ -type f -exec chmod 644 {} \;
|
||||
| `weather` | Weather (Open-Meteo) | `mcp_local` | `global` | none | — |
|
||||
| `wikipedia` | Wikipedia | `mcp_local` | `global` | none | — |
|
||||
| `whatsapp` | WhatsApp | `mcp_local` | `user` | qr | — |
|
||||
**Stato del verify-before-save in skald**: `exa`, `email`, `tavily`, e `gcal` hanno `verify` completo
|
||||
**Stato del verify-before-save in skald**: `exa`, `drive`, `email`, `tavily`, e `gcal` hanno `verify` completo
|
||||
(script + JSON output); `gmail` aspetta la Fase 2 (OAuth via loopback listener).
|
||||
Un connector senza `verify` viene attivato senza test — vedi § Senza verify.
|
||||
|
||||
@@ -372,6 +372,51 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "serpapi-flights",
|
||||
"name": "SerpAPI Flights",
|
||||
"type": "mcp_remote",
|
||||
"scope": "global",
|
||||
"icon_small": "serpapi-flights/icon_sm.svg",
|
||||
"icon_large": "serpapi-flights/icon_lg.svg",
|
||||
"user_description": "Search and compare flights, lookup airport codes, and explore routes via SerpAPI\u2019s Google Flights integration.",
|
||||
"tags": [
|
||||
"flights",
|
||||
"travel",
|
||||
"mcp",
|
||||
"remote",
|
||||
"search"
|
||||
],
|
||||
"auth": {
|
||||
"type": "api_key"
|
||||
},
|
||||
"folder": "serpapi-flights",
|
||||
"version": 1,
|
||||
"version_string": "1.0.0",
|
||||
"version_release_date": "2026-07-19",
|
||||
"files": [
|
||||
{
|
||||
"path": "connector.json",
|
||||
"sha256": "7c2bd621f461001483787036c5692021f34f3838b90e215be00cae470103526a",
|
||||
"size": 1352
|
||||
},
|
||||
{
|
||||
"path": "verify.py",
|
||||
"sha256": "eca6298a01cc1c8ce2aece9170a0b228efda7cb8a5c469d1ca3b62932fb7ea51",
|
||||
"size": 2003
|
||||
},
|
||||
{
|
||||
"path": "icon_sm.svg",
|
||||
"sha256": "6dbd397e7e06d0431089b12e590c0a5dafa362dcb7117af122e240ea9231edc3",
|
||||
"size": 570
|
||||
},
|
||||
{
|
||||
"path": "icon_lg.svg",
|
||||
"sha256": "5a2ffa7f2502fd27dc0027395db2c863bb544c8de1eef8131a5228d87402c8e6",
|
||||
"size": 574
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ssh",
|
||||
"name": "SSH Remote Access",
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"id": "serpapi-flights",
|
||||
"name": "SerpAPI Flights",
|
||||
"version": 1,
|
||||
"version_string": "1.0.0",
|
||||
"version_release_date": "2026-07-19",
|
||||
"type": "mcp_remote",
|
||||
"scope": "global",
|
||||
"tags": [
|
||||
"flights",
|
||||
"travel",
|
||||
"mcp",
|
||||
"remote",
|
||||
"search"
|
||||
],
|
||||
"docs": [
|
||||
{
|
||||
"lang": "en",
|
||||
"description": "Search and compare flights, lookup airport codes, explore routes and prices via SerpAPI's Google Flights integration. Covers departure/arrival search, price comparison, and routing across dates.",
|
||||
"llm_short_description": "Flight search via SerpAPI: search flights, lookup airport codes, compare prices and routes using Google Flights data."
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"type": "api_key"
|
||||
},
|
||||
"env": [
|
||||
{
|
||||
"name": "serpapiApiKey",
|
||||
"label": "SerpAPI API key",
|
||||
"description": "Get one at https://serpapi.com/manage-api-key (free plan includes 100 searches/month).",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"example": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
||||
}
|
||||
],
|
||||
"mcp_config": {
|
||||
"url": "https://mcp.serpapi.com/{SECRET:serpapiApiKey}/mcp",
|
||||
"transport": "streamable-http"
|
||||
},
|
||||
"verify": {
|
||||
"command": "python3 verify.py",
|
||||
"timeout_secs": 15
|
||||
},
|
||||
"homepage": "https://serpapi.com/google-flights-api",
|
||||
"icon_small": "icon_sm.svg",
|
||||
"icon_large": "icon_lg.svg"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" fill="none">
|
||||
<rect width="96" height="96" rx="16" fill="#1a73e8"/>
|
||||
<g transform="translate(48,48) rotate(-45)" fill="#fff">
|
||||
<path d="M0-36c-1.2 0-2.4.6-3 1.6l-5 8.6c-.6 1-.2 2.4.8 3 .4.2.8.4 1.2.4h3l7.6 13-14.6 4.4c-1.2.4-2 1.4-2 2.6v4c0 1.2.8 2.2 2 2.6l19 5.6 5.6 19c.4 1.2 1.4 2 2.6 2h4c1.2 0 2.2-.8 2.6-2l4.4-14.6 13 7.6v3c0 .4.2.8.4 1.2.6 1 2 1.4 3 .8l8.6-5c1-.6 1.6-1.8 1.6-3V-4c0-1.2-.6-2.4-1.6-3l-8.6-5c-1-.6-2.4-.2-3 .8-.4.6-.4 1.2-.4 1.8v3l-13 7.6-4.4-14.6c-.4-1.2-1.4-2-2.6-2H4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 574 B |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
|
||||
<rect width="48" height="48" rx="8" fill="#1a73e8"/>
|
||||
<g transform="translate(24,24) rotate(-45)" fill="#fff">
|
||||
<path d="M0-18c-.6 0-1.2.3-1.5.8l-2.5 4.3c-.3.5-.1 1.2.4 1.5.2.1.4.2.6.2h1.5l3.8 6.5-7.3 2.2c-.6.2-1 .7-1 1.3v2c0 .6.4 1.1 1 1.3l9.5 2.8 2.8 9.5c.2.6.7 1 1.3 1h2c.6 0 1.1-.4 1.3-1l2.2-7.3 6.5 3.8v1.5c0 .2.1.4.2.6.3.5 1 .7 1.5.4l4.3-2.5c.5-.3.8-.9.8-1.5V-2c0-.6-.3-1.2-.8-1.5l-4.3-2.5c-.5-.3-1.2-.1-1.5.4-.2.3-.2.6-.2.9v1.5l-6.5 3.8-2.2-7.3c-.2-.6-.7-1-1.3-1h-2z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 570 B |
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify SerpAPI Flights MCP connectivity.
|
||||
|
||||
Reads serpapiApiKey from the environment, sends a lightweight JSON-RPC
|
||||
initialize to https://mcp.serpapi.com/{key}/mcp, and prints:
|
||||
|
||||
{"ok": true, "message": "SerpAPI Flights MCP endpoint is reachable"}
|
||||
{"ok": false, "message": "SerpAPI Flights MCP endpoint is unreachable: <reason>"}
|
||||
|
||||
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("serpapiApiKey", "").strip()
|
||||
if not api_key:
|
||||
api_key = os.environ.get("SERPAPI_API_KEY", "").strip()
|
||||
if not api_key:
|
||||
_result(False, "No SerpAPI API key provided (serpapiApiKey env var is empty)")
|
||||
|
||||
url = f"https://mcp.serpapi.com/{api_key}/mcp"
|
||||
|
||||
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:
|
||||
_result(True, "SerpAPI Flights MCP endpoint is reachable")
|
||||
_result(False, f"SerpAPI returned HTTP {resp.status}")
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code in (401, 403):
|
||||
_result(False, "SerpAPI API key is invalid or unauthorized "
|
||||
f"(HTTP {e.code})")
|
||||
_result(False, f"SerpAPI returned HTTP {e.code}: {e.reason}")
|
||||
except Exception as e:
|
||||
_result(False, f"SerpAPI Flights MCP endpoint is unreachable: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user