Files
skald-connectors/SKALD.md
T
dguiducci 2750e773d4 Aggiunto connector Google Maps (mcp_local)
- Script: gmaps_mcp_server.py (MCP stdio, JSON-RPC 2.0)
- 6 tools: status, directions, geocode, reverse_geocode, search_places, distance_matrix
- Auth: API key via env GOOGLE_MAPS_API_KEY
- Verify: test Geocoding API con probe 'Rome, IT' 
- Dipendenze: googlemaps>=4.10.0
- Icone SVG pin Google Maps
2026-07-22 21:46:43 +01:00

21 KiB
Raw Blame History

Skald Connectors Marketplace

Reference locale

Updated: 2026-07-22

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.

Per deployare l'ultima versione del marketplace sul server:

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.

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/
├── connectors.json          ← INDICE (radice di fiducia unica)
├── index.html               ← Catalogo UI (legge connectors.json via fetch)
├── oauth/
│   └── show.html            ← OAuth callback receiver (client-side, no backend)
├── gmail/                   ← Un connector per cartella
│   ├── 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. preview)
├── email/
│   ├── connector.json
│   ├── email_mcp_server.py
│   ├── verify.py
│   ├── requirements.txt
│   ├── icon_sm.svg
│   └── icon_lg.svg
├── ssh/
│   ├── connector.json
│   ├── ssh_mcp_server.py
│   ├── requirements.txt
│   ├── icon_sm.svg
│   └── icon_lg.svg
└── tavily/
    ├── connector.json
    ├── verify.py
    ├── icon_sm.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.

{
  "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.

{
  "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": "One-line description for LLM context..."
    }
  ],
  "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
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:

// 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.

"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.

"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:

{"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 hash sha256 sono solo in connectors.json (l'indice)
  • connector.json non contiene hash di sé stesso — è il file manifesto
  • L'indice è l'unica radice di fiducia; in futuro si può firmare digitalmente solo l'indice
  • Sui file locali, per calcolare/aggiornare gli hash:
    python3 -c "import hashlib; print(hashlib.sha256(open('file.py','rb').read()).hexdigest())"
    

Workflow locale

  1. Lavora su file nella cartella connectors/
  2. Modifica connectors.json, connector.json, script, icone
  3. Prima del deploy aggiorna gli sha256 in connectors.json:
    python3 scripts/update_hashes.py
    
  4. Fai l'upload sul server con rsync:
    rsync -avz --delete connectors/ dguiducci@skald-server:/var/www/connectors.skaldagent.net/
    
  5. Verifica su https://connectors.skaldagent.net/

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/

Comando di deploy (da eseguire con sudo o con rsync):

# Sync se il server permette rsync via SSH
rsync -avz --delete ./connectors/ dguiducci@skald-server:/var/www/connectors.skaldagent.net/

Dopo il deploy, verificare i permessi:

sudo chown -R caddy:caddy /var/www/connectors.skaldagent.net/
sudo find /var/www/connectors.skaldagent.net/ -type f -exec chmod 644 {} \;

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
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.