Files
skald-connectors/SKALD.md
T

605 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Skald Connectors Marketplace
### 2026-07-23 — Context7 icon update (PNG)
- Sostituite icone Context7 da SVG a PNG (icona nuova fornita dall'utente):
- `icon_sm.png` — 48×48 (2.7 KB)
- `icon_lg.png` — 96×96 (4.5 KB)
- Vecchi SVG rimossi, riferimenti aggiornati in fragment.json e connector.json
- Version bump: fragment 3→4, connector 1→2
- Indice rigenerato con compile.py ✅
## Reference locale
### 2026-07-23 — SerpAPI Flights icon update (PNG)
- Sostituite icone SerpAPI Flights da SVG a PNG:
- `icon_sm.png` — 48×48 (2.9 KB)
- `icon_lg.png` — 96×96 (6.8 KB)
- Vecchi SVG rimossi, riferimenti aggiornati in fragment.json e connector.json
- Version bump: fragment 4→5, connector 2→3
- Indice rigenerato con compile.py ✅
- **[docs/connector.manifest_guide.md](docs/connector.manifest_guide.md)** — Guida ufficiale per generare connector corretti (copiata da `skald-circle/blueprint/`)
_Updated: 2026-07-23_
**Remote**: `https://git.skaldagent.net/dguiducci/skald-connectors.git`
**Live**: `https://connectors.skaldagent.net/`
**OAuth callback**: `https://connectors.skaldagent.net/oauth/show.html`
## Deploy
Il branch **`main`** è il branch di **release**. Solo codice pronto per produzione finisce qui.
Sviluppo e versioni alfa-staranno su branch separati in futuro.
Deploy rapido con MCP SSH:
```bash
mcp__ssh__exec alias=skald-home-server command="/home/dguiducci/marketplace_deploy.sh"
```
Oppure via SSH classico:
```bash
ssh dguiducci@skald-home-server /home/dguiducci/marketplace_deploy.sh
```
Lo script sul server fa:
1. `git pull` in `/home/dguiducci/repos/skald-connectors/`
2. `cp -r connectors/*` in `/var/www/connectors.skaldagent.net/`
La directory `/var/www/connectors.skaldagent.net/` è di proprietà di `dguiducci`,
quindi non serve sudo per la copia.
**Prima del deploy**, ricordarsi di rigenerare l'indice:
```bash
python3 scripts/compile.py
```
## Cos'è
Il **marketplace** è il catalogo dei connector testati per Skald. Ogni connector è un adattatore che permette a Skald di interfacciarsi con un servizio esterno (API, email, calendario, ricerca, messaggistica, ecc.).
Due tipi di connector:
- **`mcp_remote`** — un MCP server già hosted, accessibile via URL (es. Tavily).
- **`mcp_local`** — script Python/Node da eseguire lato client (es. Gmail, Google Calendar).
## Friendly tool names (2026-07-21)
Ogni tool MCP deve esporre un nome friendly per la UI di Skald. Due modi, in ordine di preferenza:
1. **Via script MCP (preferito)** — aggiungere `"title": "Friendly Name"` nella definizione di ogni tool dentro `tools/list`. Funziona per tutti gli script locali (Python/Node) che controlliamo.
2. **Via manifest (fallback)** — aggiungere `"tools": [{"name": "...", "display_name": "..."}]` in `connector.json` **e** in `connectors.json`. Usato solo per connector remoti o package esterni (es. `npx -y firecrawl-mcp`).
**Ordine di risoluzione** (Skald li prova in quest'ordine):
1. `tools[].display_name` dal manifest
2. `title` dal `tools/list` dell'MCP server
3. Prettify automatico del nome raw (`send_message` → "Send Message")
Stato attuale (2026-07-21): tutti i 13 connector del marketplace hanno `title` nello script o `tools[]` nel manifest.
## Struttura directory
```
connectors/
├── index.json ← lista ordinata degli id dei connector (input per compile.py)
├── connectors.json ← INDICE COMPILATO (generato da compile.py, non editare)
├── compile.py ← genera connectors.json
├── index.html ← Catalogo UI (legge connectors.json via fetch)
├── oauth/
│ └── show.html ← OAuth callback receiver (client-side, no backend)
├── gmail/ ← Un connector per cartella
│ ├── fragment.json ← Frammento dell'indice (id, name, type, ..., SENZA files[])
│ ├── connector.json ← Configurazione tecnica
│ ├── gmail_mcp_server.py ← Script MCP
│ ├── gmail_oauth_setup.py ← Script setup OAuth
│ ├── requirements.txt ← Dipendenze Python
│ ├── icon_sm.svg ← Icona piccola (48×48)
│ └── icon_lg.svg ← Icona grande (es. 96×96)
├── email/
│ ├── fragment.json
│ ├── connector.json
│ ├── email_mcp_server.py
│ ├── verify.py
│ ├── requirements.txt
│ ├── icon_sm.svg
│ └── icon_lg.svg
├── ssh/
│ ├── fragment.json
│ ├── connector.json
│ ├── ssh_mcp_server.py
│ ├── requirements.txt
│ ├── icon_sm.svg
│ └── icon_lg.svg
└── tavily/
├── fragment.json
├── connector.json
├── verify.py
├── icon_sm.png
└── icon_lg.png
```
└── icon_lg.png
```
## Schema — connectors.json (root)
Questo è l'**unico punto di fiducia**. Contiene `type`, `scope` e gli sha256 dei file di ogni connector.
Non ha hash di sé stesso — in futuro potrà essere firmato digitalmente.
```json
{
"version": 1,
"connectors": [
{
"id": "gmail",
"name": "Gmail",
"type": "mcp_local",
"scope": "user",
"icon_small": "gmail/icon_sm.svg",
"icon_large": "gmail/icon_lg.svg",
"user_description": "Read, send, and manage Gmail emails via OAuth...",
"requires": ["OAUTH", "PYTHON"],
"tags": ["email", "mcp", "local", "google"],
"auth": {
"type": "oauth2",
"provider": "google",
"scopes": [
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.labels"
]
},
"folder": "gmail",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"files": [
| `auth` | per OAuth | Oggetto con `type`, `provider`, `scopes` per badge UI (NO `deliver` qui, è nel manifest) |
{"path": "gmail_mcp_server.py", "sha256": "a50d4da9621f7a4b092f...", "size": 46772},
{"path": "gmail_oauth_setup.py", "sha256": "e488acb289c43a3e6d54...", "size": 3627},
{"path": "icon_lg.svg", "sha256": "93c8d9c8dae96f0206e5...", "size": 254},
{"path": "icon_sm.svg", "sha256": "029d7f5d81de6cf2b17b...", "size": 251},
{"path": "requirements.txt", "sha256": "3f659cc5e5f0543f1326...", "size": 82}
]
}
]
}
```
### Campi dell'indice
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `id` | ✅ | Identificatore unico (kebab-case) |
| `name` | ✅ | Nome visualizzato |
| `type` | ✅ | `mcp_remote` o `mcp_local` |
| `scope` | ✅ | `global` o `user` |
| `icon_small` | ✅ | Path relativo dalla root del marketplace |
| `icon_large` | ✅ | Path relativo dalla root del marketplace |
| `user_description` | ✅ | Descrizione breve per la UI |
| `requires` | ✅ | Array di enum requisiti |
| `tags` | ✅ | Array di tag per filtraggio |
| `folder` | ✅ | Nome della cartella del connector |
| `version` | ✅ | Intero per-connector, +1 a ogni modifica dei file |
| `version_string` | ✅ | Semver (solo display) |
| `version_release_date` | ✅ | Data ISO 8601 YYYY-MM-DD (solo display) |
| `files` | ✅ | Array di file con sha256 (NO self-hash) |
## Schema — connector.json (per cartella)
Configurazione tecnica per l'attivazione del connector.
```json
{
"id": "gmail",
"name": "Gmail",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"type": "mcp_local",
"scope": "user",
"launch_command": "python3 gmail_mcp_server.py",
"transport": "stdio",
"requires": ["OAUTH", "PYTHON"],
"tags": ["email", "mcp", "local", "google"],
"dependencies": [
"google-api-python-client>=2.150.0",
"google-auth>=2.35.0",
"google-auth-oauthlib>=1.2.0"
],
"setup_instructions": [
"Install dependencies: pip install -r requirements.txt",
"Run: python3 gmail_oauth_setup.py (optional, for standalone use — Skald handles OAuth)"
],
"docs": [
{
"lang": "en",
"description": "Full description for human users...",
"llm_short_description": "Google Calendar — read, create, update, delete, and respond to calendar events. Supports push notifications."
}
],
"auth": {
"type": "oauth2",
"provider": "google",
"scopes": [
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.labels"
],
"deliver": {
"as": "env",
"format": "google_authorized_user",
"env": "GMAIL_CREDS_JSON"
}
},
"mcp_config": {
"command": "python3",
"args": ["gmail_mcp_server.py"]
},
"homepage": "https://mail.google.com",
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg"
}
```
### Campi del connector.json
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `id` | ✅ | Identificatore unico (match con folder name) |
| `name` | ✅ | Nome visualizzato |
| `version` | ✅ | Intero per-connector, +1 a ogni modifica dei file |
| `version_string` | ✅ | Semver (solo display) |
| `version_release_date` | ✅ | Data ISO 8601 YYYY-MM-DD (solo display) |
| `type` | ✅ | `mcp_remote` o `mcp_local` |
| `scope` | ✅ | `global` o `user` |
| `requires` | ✅ | Array di enum requisiti |
| `tags` | ✅ | Array di tag |
| `auth` | ✅ | Oggetto configurazione autenticazione |
| `docs` | ✅ | Array di documentazione multilingua. **`llm_short_description`** è il campo che finisce nel system prompt dell'LLM — deve descrivere COSA FA il connector, non elencare i tool (l'LLM li vede dopo `activate_tools`). Esempio: *"Weather — current conditions, 16-day forecast, and AQI data for any location."*
| `icon_small` | ✅ | Nome file icona nella cartella locale |
| `icon_large` | ✅ | Nome file icona nella cartella locale |
| `launch_command` | solo `mcp_local` | Comando per avviare il server MCP |
| `transport` | solo `mcp_local` | `stdio` (default) |
| `dependencies` | consigliato | Dipendenze Python/Node (array vuoto se solo stdlib) |
| `env` | se `requires` include `ENV` | Variabili d'ambiente che l'utente deve fornire (schema per la UI) — vedi § Campo env |
| `setup_instructions` | consigliato | Passi per configurare il connector |
| `mcp_config` | solo `mcp_local` | Configurazione per l'MCP client |
| `homepage` | opzionale | URL del servizio |
## Enum riservati
### type (tipo di connector)
| Valore | Descrizione | Esempi |
|--------|-------------|--------|
| `mcp_remote` | Server MCP hosted, accessibile via URL | Tavily, Weather |
| `mcp_local` | Script da eseguire localmente | Gmail, Google Calendar, WhatsApp |
| `script` | Script standalone (non MCP) | *(futuro)* |
### scope (ambito di configurazione)
| Valore | Descrizione | Esempi |
|--------|-------------|--------|
| `global` | Una singola istanza/config per tutto il sistema | Tavily, Weather, Google Trends |
| `user` | Ogni utente ha la propria istanza/autenticazione | Gmail, WhatsApp, Google Calendar |
### requires (prerequisiti)
| Valore | Descrizione |
|--------|-------------|
| `API_KEY` | Richiede una chiave API da configurare |
| `OAUTH` | Richiede autenticazione OAuth (Google, ecc.) |
| `DOCKER` | Richiede Docker Engine |
| `NODE` | Richiede Node.js runtime |
| `PYTHON` | Richiede Python 3 |
| `SECRETS_DIR` | ❌ **Deprecato** — la cartella `secrets/` è rimossa dal modello; i connector devono usare `ENV`/`SECRET` (vedi § Sintassi placeholder) |
| `ENV` | Richiede variabili d'ambiente (dichiarate nel campo `env` del manifest) |
## Campo auth
Struttura che descrive come il connector gestisce l'autenticazione:
```json
// API key in query string
{"type": "api_key", "delivery": "query", "param": "tavilyApiKey"}
// API key in header
{"type": "api_key", "delivery": "header", "param": "X-API-Key"}
// OAuth2 — provider SOLO slug (Skald risolve endpoint + client secrets)
{"type": "oauth2", "provider": "google", "scopes": ["...", "..."]}
// OAuth2 con deliver (Skald inietta il JSON authorized_user via env var)
{"type": "oauth2", "provider": "google", "scopes": ["..."],
"deliver": {"as": "env", "format": "google_authorized_user", "env": "GMAIL_CREDS_JSON"}}
// OAuth2 con deliver su file (legacy)
{"type": "oauth2", "provider": "google", "scopes": ["..."],
"deliver": {"as": "file", "format": "google_authorized_user", "path": "{secrets}/gmail_creds.json"}}
// Password / app-password fornita via variabili d'ambiente
{"type": "password", "delivery": "env"}
// Nessuna autenticazione
{"type": "none"}
```
### Campo deliver (solo OAuth2)
Dichiara **come** Skald consegna la credenziale OAuth ottenuta al processo del server MCP.
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `as` | ✅ | `"file"` (su disco) o `"env"` (variabile d'ambiente) |
| `format` | ✅ | Nome della serializzazione — es. `"google_authorized_user"` (JSON Google che `from_authorized_user_file` legge), `"refresh_token"`, `"access_token"` |
| `path` | solo `as=file` | Path con placeholder `{secrets}` (Skald lo espande a dir per-utente a runtime). DEVE matchare il path in `mcp_config.env`. |
| `env` | solo `as=env` | Nome della variabile d'ambiente in cui Skald inietta l'intero JSON authorized_user. **Non va dichiarata in `mcp_config.env`** — Skald la inietta a runtime. |
Il feed NON contiene MAI: `client_id`, `client_secret`, `endpoint` URL, `redirect_uri`. Questi sono risolti lato Skald a partire dal nome del `provider`.
## Campo env (variabili d'ambiente)
Usato quando `requires` include `ENV`. È un **array** che dichiara le variabili
d'ambiente che l'utente deve fornire per far funzionare il connector; **nessuna
credenziale finisce su disco né in `secrets/`** — l'host raccoglie i valori,
obbliga la compilazione dei campi obbligatori, e li inietta come environment
nel processo del server MCP al lancio. Il server le legge da `os.environ`.
```json
"env": [
{
"name": "EMAIL_IMAP_HOST", // nome della variabile d'ambiente
"label": "IMAP host", // etichetta per la UI
"description": "IMAP server hostname (es. imap.gmail.com)",
"required": true, // se true, l'host deve obbligare la compilazione
"secret": false, // se true, la UI la maschera e la tratta come segreto
"example": "imap.gmail.com" // placeholder/esempio (opzionale)
},
{
"name": "EMAIL_PASSWORD",
"label": "Password / app password",
"description": "Password o app-password del provider",
"required": true,
"secret": true,
"default": "" // valore di default se non obbligatorio (opzionale)
}
]
```
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `name` | ✅ | Nome della variabile d'ambiente (UPPER_SNAKE_CASE) |
| `label` | ✅ | Etichetta breve per la UI |
| `description` | ✅ | Testo di aiuto |
| `required` | ✅ | Se `true`, l'host obbliga l'utente a fornire un valore |
| `secret` | consigliato | Se `true`, valore sensibile (mascherato, non loggato) |
| `default` | opzionale | Valore usato se non fornito (solo per non obbligatorie) |
| `example` | opzionale | Placeholder di esempio per la UI |
## Sintassi placeholder (unificata)
Ogni valore che skald deve riempire a runtime con un dato fornito dall'utente
usa **uno di due token**, ovunque compaia (URL, `mcp_config.env`, `verify.command`):
| Token | Significato | Esempio |
|-------|-------------|---------|
| `{ENV:NAME}` | Variabile non sensibile (hostname, porta, username…) | `{ENV:EMAIL_IMAP_HOST}` |
| `{SECRET:NAME}` | Variabile sensibile (password, API key, token) | `{SECRET:EMAIL_PASSWORD}` |
`NAME` è il nome dichiarato nell'array `env[]` (campo `name`). skald raccoglie
i valori tramite un form (maschera i `{SECRET:}`), li inietta come environment
nel processo del server MCP / verify, e sostituisce i token nel manifest.
Regole:
- I token non riconosciuti (es. `{secrets}/…`, legacy `{key}`, `{env:NAME}`)
sono **deprecati**: skald non li sostituisce e il manifest va aggiornato.
- `{SECRET:<auth.param>}` è riservato alla chiave primaria quando
`auth.type = "api_key"` (es. Tavily: `{SECRET:tavilyApiKey}`). skald tratta
quel valore anche come API key per il routing bearer/header.
- Un token `{ENV:X}` o `{SECRET:X}` la cui `X` non è nell'`env[]` del manifest
viene sostituito con stringa vuota (l'host non può indovinarlo).
### Deprecations
| Token | Stato | Sostituzione |
|-------|-------|--------------|
| `{key}` | ❌ deprecato | `{SECRET:<auth.param>}` |
| `{env:NAME}` | ❌ deprecato | `{ENV:NAME}` |
| `{secrets}/…` | ❌ deprecato | Il connector deve dichiarare il path come `{ENV:…}` (la cartella `secrets/` è rimossa dal modello) |
## Campo verify (test prima del salvataggio)
Dichiara un comando shell che skald esegue **dopo** che l'utente ha compilato
il form e **prima** di persistere l'attivazione. Serve a verificare che le
credenziali appena inserite funzionino davvero.
```json
"verify": {
"command": "python3 verify.py",
"timeout_secs": 20
}
```
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `command` | ✅ | Comando shell. Gira nello stesso sandbox del server: container `skald-{userid}` per `mcp_local` user, host per `mcp_remote` global. Le env/secret dichiarati sono iniettate |
| `timeout_secs` | opzionale | Default 15. skald killa il processo allo scadere |
### Convenzione output
Il comando deve stampare **un singolo oggetto JSON su stdout** e nient'altro:
```json
{"ok": true, "message": "IMAP and SMTP authentication successful", "details": {"imap": "...", "smtp": "..."}}
{"ok": false, "message": "IMAP login failed: INVALID_CREDENTIALS"}
```
| Campo | Tipo | Descrizione |
|-------|------|-------------|
| `ok` | bool | `true` = test passato |
| `message` | string | Messaggio mostrato all'utente (mai loggare secret qui dentro) |
| `details` | object | Opzionale, dettagli strutturati mostrati in `<pre>` |
Exit code: 0 su successo, ≠ 0 su fallimento (skald usa l'exit code come
fallback se il parse JSON fallisce). **Mai stampare credenziali** nel
`message`/`details`.
### Dove mettere lo script
Se `command` referenzia un file (es. `verify.py`), il file va:
1. Aggiunto all'array `files[]` in `connectors.json` (con `sha256` e `size`)
2. Salvato nella cartella del connector (`<id>/verify.py`)
skald lo scarica, ne verifica lo SHA-256 contro l'indice, e lo rende disponibile
nello stesso path del server principale (container per i `mcp_local`, dir
`./scripts/<id>/` sull'host per i `mcp_remote`).
### Senza verify
Se `verify` manca, skald **non esegue nessun test** — l'attivazione è diretta
come oggi. Il connector va in `auth_state='ready'` senza verifica. Per i
`mcp_remote` non c'è fallback handshake: l'autore del manifest decide se vuole
il test scrivendo `verify`.
## Convenzioni icone
- **Formato**: SVG per icone vettoriali (meglio per retina/zoom), PNG per raster
- **Nome**: `icon_sm.{svg|png}` (small, ~48×48px), `icon_lg.{svg|png}` (large, ~96×96px)
- **Path**: relativo alla cartella del connector
- **Nell'indice** la path è `{folder}/{filename}` (es. `gmail/icon_sm.svg`)
## Integrità file (sha256)
- Gli SHA-256 sono generati **automaticamente** da `scripts/compile.py` a partire
dai file fisici presenti in ogni cartella — mai manuali, mai stale.
- L'unico file firmato (in futuro) sarà `connectors.json` (l'indice).
- `fragment.json` e `index.json` non hanno hash — sono solo input di compilazione.
## Struttura directory
```
connectors/
├── index.json ← lista ordinata degli id dei connector (input per compile.py)
├── connectors.json ← INDICE COMPILATO (generato da compile.py, non editare)
├── compile.py ← genera connectors.json (lanciato da scripts/compile.py)
├── index.html ← Catalogo UI (legge connectors.json via fetch)
├── oauth/
│ └── show.html ← OAuth callback receiver
├── gmail/ ← Un connector per cartella
│ ├── fragment.json ← Frammento dell'indice (id, name, type, ..., SENZA files[])
│ ├── connector.json ← Configurazione tecnica (mcp_config, auth.deliver, ...)
│ ├── gmail_mcp_server.py ← Script MCP
│ ├── gmail_oauth_setup.py ← Script setup OAuth
│ ├── requirements.txt ← Dipendenze Python
│ ├── icon_sm.svg ← Icona piccola (48×48)
│ └── icon_lg.svg ← Icona grande (es. 96×96)
├── email/
│ ├── fragment.json
│ ├── connector.json
│ ├── email_mcp_server.py
│ ├── verify.py
│ ├── requirements.txt
│ ├── icon_sm.svg
│ └── icon_lg.svg
└── ...
```
## Workflow locale
1. **Aggiungere un nuovo connector**:
- Crea cartella `connectors/<id>/`
- Crea `fragment.json` (id, name, type, scope, icone, auth, tools, ...)
- Crea `connector.json` (config tecnica: mcp_config, launch_command, ...)
- Aggiungi script MCP, icone, verify.py, requirements.txt
- Aggiungi l'id a `connectors/index.json`
- Lancia `python3 scripts/compile.py`
2. **Modificare un connector esistente**:
- Modifica i file nella cartella del connector
- **Non toccare** `connectors.json` — viene rigenerato
- Lancia `python3 scripts/compile.py`
3. **Prima del deploy**:
```bash
python3 scripts/compile.py # rigenera connectors.json con SHA-256 fresh
python3 scripts/compile.py --verify # (opzionale) verifica che sia aggiornato
```
4. **Deploy sul server**:
```bash
ssh dguiducci@skald-home-server /home/dguiducci/marketplace_deploy.sh
```
oppure con MCP SSH:
```bash
# via mcp__ssh__exec alias "skald-home-server"
/home/dguiducci/marketplace_deploy.sh
```
(Il deploy script fa `git pull` + `cp -r connectors/* /var/www/connectors.skaldagent.net/`)
5. Verifica su `https://connectors.skaldagent.net/`
## Fragment.json
Vedi [docs/connector.manifest_guide.md](docs/connector.manifest_guide.md) per la guida completa
alla creazione.
`fragment.json` contiene tutti i campi dell'entry di `connectors.json` **tranne** `files[]`.
Questi sono i campi obbligatori:
| Campo | Obbligatorio | Descrizione |
|-------|-------------|-------------|
| `id` | ✅ | Identificatore unico (match con folder name) |
| `name` | ✅ | Nome visualizzato |
| `type` | ✅ | `mcp_remote` o `mcp_local` |
| `scope` | ✅ | `global` o `user` |
| `icon_small` | ✅ | Path relativo dalla root del marketplace |
| `icon_large` | ✅ | Path relativo dalla root del marketplace |
| `user_description` | ✅ | Descrizione breve per la UI |
| `requires` | ✅ | Array di enum requisiti |
| `tags` | ✅ | Array di tag per filtraggio |
| `folder` | ✅ | Nome della cartella del connector (match con `id`) |
| `version` | ✅ | Intero per-connector, +1 a ogni modifica dei file |
| `version_string` | ✅ | Semver (solo display) |
| `version_release_date` | ✅ | Data ISO 8601 (solo display) |
| `tools` | ✅ | Array di `{name, display_name}` per friendly names UI |
| `auth` | opzionale | Configurazione autenticazione (se diversa da `"none"`) |
Nota: l'array `files[]` (con SHA-256 e size) viene aggiunto **automaticamente**
da `compile.py` scansionando i file presenti nella cartella — non va mai scritto
a mano.
## Deploy su server remoto
Il server remoto è:
- **Host**: skald-home-server (192.168.1.100 / 145.40.169.107)
- **User**: dguiducci
- **Path**: `/var/www/connectors.skaldagent.net/`
- **Proprietario**: `caddy:caddy`
- **Sudo**: richiesto per scrivere in `/var/www/`
## Connector attuali
| ID | Nome | Tipo | Scope | Auth | Verify |
|----|------|------|-------|------|--------|
| `context7` | Context7 | `mcp_remote` | `global` | none | `verify.py` (MCP initialize probe) |
| `gmaps` | Google Maps | `mcp_local` | `global` | api_key (env: `GOOGLE_MAPS_API_KEY`) | `verify.py` (Geocoding API probe) |
| `exa` | Exa | `mcp_remote` | `global` | api_key (`{SECRET:exaApiKey}` in URL — optional, free tier) | `verify.py` (MCP initialize probe) |
| `tavily` | Tavily | `mcp_remote` | `global` | api_key (`{SECRET:tavilyApiKey}` in URL) | `verify.py` (HTTP probe `/search`) |
| `serpapi-flights` | SerpAPI Flights | `mcp_remote` | `global` | api_key (`{SECRET:serpapiApiKey}` in URL) | `verify.py` (MCP initialize probe) |
| `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 | — |
| `ssh` | SSH Remote Access | `mcp_local` | `user` | none (auth runtime per-alias) | — |
| `weather` | Weather (Open-Meteo) | `mcp_local` | `global` | none | — |
| `google-trends` | Google Trends | `mcp_local` | `global` | none | `verify.py` (trendspyg import probe) |
| `wikipedia` | Wikipedia | `mcp_local` | `global` | none | — |
| `whatsapp` | WhatsApp | `mcp_local` | `user` | qr | — |
**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.