add playwright connector (v1 / 1.0.0) + commit pending docs reorganization
- new global mcp_local connector wrapping @playwright/mcp@0.0.79: index.js argv wrapper (--headless --isolated --no-sandbox) importing the package cli.js, postinstall downloads chromium-only browser, verify.js headless-launch probe, 24 tools with display names - also carries the pending docs work: changelog extracted to CHANGELOG.md, manifest guide, SKALD.md/CLAUDE.md updates
This commit is contained in:
@@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
The **Skald Connectors Marketplace** — a catalog of tested connectors (adapters that let Skald agents talk to external services). It is **not an application**: there is no build system, package manager, or test suite. The repo is a set of JSON manifests, static HTML, icons, and standalone Python MCP scripts that are served as-is over HTTP.
|
||||
|
||||
`SKALD.md` is the authoritative spec (written in Italian) — read it before changing any schema or manifest.
|
||||
`SKALD.md` is the authoritative spec — read it before changing any schema or manifest.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -25,15 +25,15 @@ Connector taxonomy (see SKALD.md for full enums):
|
||||
- `{ENV:NAME}` — a non-sensitive value (host, port, username…), declared in the top-level `env[]` array.
|
||||
- `{SECRET:NAME}` — a sensitive value (password, API key, token), also declared in `env[]` with `secret: true`.
|
||||
|
||||
Legacy tokens `{key}`, `{env:NAME}`, `{secrets}/…` are **deprecated** and skald no longer substitutes them. The api-key of an `auth.type = "api_key"` connector is exposed as `{SECRET:<auth.param>}` (e.g. Tavily: `?tavilyApiKey={SECRET:tavilyApiKey}`). See SKALD.md § Sintassi placeholder.
|
||||
Legacy tokens `{key}`, `{env:NAME}`, `{secrets}/…` are **deprecated** and skald no longer substitutes them. The api-key of an `auth.type = "api_key"` connector is exposed as `{SECRET:<auth.param>}` (e.g. Tavily: `?tavilyApiKey={SECRET:tavilyApiKey}`). See SKALD.md § Placeholder syntax.
|
||||
|
||||
**Config via `env[]` (`env` manifest field):** a connector whose `requires` includes `ENV` declares its required environment variables in a top-level `env` array in `connector.json` — each entry has `name`, `label`, `description`, `required`, `secret`, and optional `default`/`example`. skald renders a real form from this schema (masking `secret: true` fields, marking `required`, using `example` as placeholder) and injects the collected values into the process environment at launch; the server reads `os.environ`. Nothing is written to disk. The `email` connector is the reference example (see SKALD.md § Campo env). **`tavily` now also declares `env[]`** (its API key as a `secret` field).
|
||||
**Config via `env[]` (`env` manifest field):** a connector whose `requires` includes `ENV` declares its required environment variables in a top-level `env` array in `connector.json` — each entry has `name`, `label`, `description`, `required`, `secret`, and optional `default`/`example`. skald renders a real form from this schema (masking `secret: true` fields, marking `required`, using `example` as placeholder) and injects the collected values into the process environment at launch; the server reads `os.environ`. Nothing is written to disk. The `email` connector is the reference example (see SKALD.md § The env field). **`tavily` now also declares `env[]`** (its API key as a `secret` field).
|
||||
|
||||
**Verify-before-save (`verify` manifest field).** A connector may declare a `verify` step — a shell command skald runs *after* the user fills the form and *before* persisting the activation, to confirm the credentials actually work:
|
||||
```json
|
||||
"verify": { "command": "python3 verify.py", "timeout_secs": 20 }
|
||||
```
|
||||
The command runs in the same sandbox as the server (container `skald-{userid}` for `mcp_local` user, host for `mcp_remote` global), with the collected env/secret injected. It must print one JSON object on stdout — `{"ok": bool, "message": string, "details"?: object}` — and exit 0 on success. If `verify` is absent, no test runs and the activation is direct. See SKALD.md § Campo verify. `email` and `tavily` ship a `verify.py`; `gmail` will get one in the OAuth phase.
|
||||
The command runs in the same sandbox as the server (container `skald-{userid}` for `mcp_local` user, host for `mcp_remote` global), with the collected env/secret injected. It must print one JSON object on stdout — `{"ok": bool, "message": string, "details"?: object}` — and exit 0 on success. If `verify` is absent, no test runs and the activation is direct. See SKALD.md § The verify field. `email` and `tavily` ship a `verify.py`; `gmail` will get one in the OAuth phase.
|
||||
|
||||
**MCP servers** (`connectors/gmail/gmail_mcp_server.py`, `connectors/email/email_mcp_server.py`) are hand-rolled JSON-RPC 2.0 servers over stdio — no MCP SDK / FastMCP. Shared conventions: **stdout is reserved for JSON-RPC**, all logging goes to stderr, a lock guards stdout writes, a background thread emits `event/new_email` push notifications, and each server exposes the same tool shape (`TOOLS` manifest + `TOOL_DISPATCH` + `handle_request`). Mirror this structure for new local connectors.
|
||||
- **Gmail** uses the Gmail API with OAuth; today it still reads its token from `./secrets/gmail_creds.json` (override `GMAIL_CREDS_PATH`) generated by `gmail_oauth_setup.py`. The `secrets/` path is **deprecated** — the OAuth phase (skald Fase 2) will migrate Gmail to `{ENV:}`/`{SECRET:}` and a loopback-listener flow. Push = History API polling. `verify` is not yet wired for Gmail.
|
||||
@@ -48,6 +48,15 @@ The command runs in the same sandbox as the server (container `skald-{userid}` f
|
||||
- **A new `verify.py` must be added to `files[]`** (with `sha256`+`size`) exactly like any other shipped file — skald refuses to run an unverified script.
|
||||
- The `secrets/` directory is **deprecated** in the model (credentials flow through `{ENV:}`/`{SECRET:}`). Gmail still uses it locally pending the OAuth migration; that path is gitignored — never commit credentials or OAuth tokens.
|
||||
|
||||
## Changelog
|
||||
|
||||
Every user-facing change to the marketplace (new connector, connector fix, version bump, icon update, deploy notes, etc.) must be recorded in **`CHANGELOG.md`** at the repo root. Rules:
|
||||
|
||||
- Follow the classic [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format (version headings, `Added`/`Changed`/`Fixed`/`Removed` categories, `[Unreleased]` section at the top). Use **date headings** (`## 2026-08-10`) instead of semver since each connector has its own version.
|
||||
- Write in English.
|
||||
- Add the entry in the same commit/change that modifies the connector files — do not defer it.
|
||||
- Never put changelog entries in `SKALD.md`; it is spec-only.
|
||||
|
||||
## Commands
|
||||
|
||||
Recompute a file hash (do this before deploy for every changed file; SKALD.md mentions a `scripts/update_hashes.py` helper that does not exist in the repo yet):
|
||||
|
||||
Reference in New Issue
Block a user