- 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
10 KiB
10 KiB
Changelog
All notable changes to the Skald Connectors Marketplace are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
2026-08-19
Added
- New connector: Playwright (mcp_local, scope global, v1 / 1.0.0) — full browser automation via the official
@playwright/mcp@0.0.79(Microsoft), wrapped like http-fetch/firecrawl:package.jsonpins the package andindex.jsrewrites argv (--headless --isolated --no-sandbox, plus aprocess.argv.slice(2)passthrough) and imports the package'scli.js, which self-executes at import time.cli.jsis not in the packageexportsmap, so the wrapper resolves it from the exportedpackage.jsonpath.auth: none,requires: ["NODE"]. Runs headless with an isolated in-memory profile: no cookies/login state persisted between sessions (chosen over the default persistent profile — a shared household browser must not accumulate per-user sessions, and a persistent profile also allows only one browser instance at a time).- Browser download: the upstream
playwrightpackage does NOT download browsers atnpm install(verified on 1.63.0-alpha-2026-08-05), and@playwright/mcp0.0.79 no longer ships the oldbrowser_installtool (the README section is now empty). So the connector'spackage.jsoncarries apostinstallhook —node node_modules/@playwright/mcp/cli.js install-browser chromium— which downloads Chromium + headless shell + ffmpeg only (~350 MB; a bareinstall-browserwould also fetch Firefox and WebKit). Verified on a cold directory:npm install --omit=devruns the hook and the browser launches. verify.js(30s) resolvesplaywright-corerelative to@playwright/mcp(it is a transitive dep, not declared by the connector's own package.json) and launches a real headless Chromium on about:blank — catches the two real failure modes (binary missing, system libraries missing on slim hosts) before the activation is saved.- Default tool set = 24 tools (no
--capsextras); all getdisplay_nameintools[]because@playwright/mcpdoes not emit MCPtitlefields intools/list(the "Title:" lines in its README are not on the wire). - ⚠️ Security: the default set includes
browser_run_code_unsafe(RCE-equivalent, arbitrary JS in the server process) andbrowser_evaluate(arbitrary JS in the page); there is no CLI flag to disable individual core tools. Consistent with themcp_localtrust model (guide §3) and declared in the manifest descriptions. - Icons: official Playwright SVG (Microsoft catalog), sized 48/96.
- Tested E2E reproducing skald's path (
npm install --omit=dev+node index.js):initialize,tools/list(24 tools), realbrowser_navigate+browser_snapshoton https://example.com ✅, verify probe ok ✅
2026-08-10
Fixed
-
http-fetch + firecrawl:
npxlaunch was broken (v5 / 1.1.0) — both connectors declaredmcp_config: {command: "npx", args: ["-y", "<package>"]}and shipped no code files (onlyconnector.json+ icons).npx -y <package>is not expressible in skald. For atype: mcp_local, skald treatsargs[0]as the name of the file to run, not as an argument: at install it computesscript_path = "<id>/" + args[0]and clearsargs_json(marketplace.rs::install), thenglobal_enable(api/mcp.rs) resolves it to an absolute path and launches<command> <abs>. The real command becamenpx /…/connectors/http-fetch/-y— a nonexistent path, with-yand the package name lost. The process never answeredinitialize, sostart_serverfailed.- The failure was silent:
global_enablestill returns HTTP 200 with anerrorfield in the body, so the UI showed the connector as enabled while the runtime had no server. Andrender_mcp_list(loop_adapters/system.rs) builds the## MCP serverstable frommcp.tools(), i.e. the live runtime state, not the DB → the connector appeared activated and granted to the user but absent from the system context. ⚠️ This combination (200 +errorin the body) makes any connector that fails to start invisible in the UI: worth surfacing on the skald side. - Fix — two-file wrapper for both: a
package.jsonpinning the upstream package (mcp-fetch-server@1.1.2,firecrawl-mcp@3.23.7) and anindex.jsthat imports it for side effects (the module starts the JSON-RPC loop on stdio at import).mcp_configbecomes{command: "node", args: ["index.js"], transport: "stdio"}, i.e. a reallocal_script:ensure_installed_hostrunsnpm ci --omit=dev || npm install --omit=devin the connector folder before launch, exactly like whatsapp. Nonode_modulesshipped, no lockfile (like whatsapp). - Removed legacy fields
launch_command, top-leveltransport, anddependencies(dependenciesis only for the card, as already seen on gmaps;transportbelongs insidemcp_config). - firecrawl: removed
mcp_config.env: {"FIRECRAWL_API_KEY": "{SECRET:FIRECRAWL_API_KEY}"}— inert, same case as gmaps on 2026-08-10:apply_key_placeholdersubstitutes tokens only in the URL, never inenvvalues. It worked because the admin form sendsenvand that payload overwritesentry.env_json. - firecrawl: added
firecrawl_developer_searchtotools[](27 live tools vs 26 declared, verified on 3.23.7);requires["NODE"]→["NODE", "API_KEY"]. - Re-aligned manifest↔fragment versions to
5/1.1.0/2026-08-10for both: they were 2/1.0.1 (manifest) vs 4/1.0.3 (fragment), and skald prefers the manifest — soinstalled_versionstayed at 2 and the "Update available" badge would never have appeared. - Host requirement: these are
scope: globalconnectors, they run on the host, not in the container.mcp-fetch-serverwants Node ≥18,firecrawl-mcpwants Node ≥22. - Tested end-to-end reproducing skald's path (
npm ci || npm install+node <abs>/index.js):initialize,tools/list, and a realtools/call, stdout only JSON-RPC, clean stderr ✅ - Index regenerated with compile.py ✅
- ⚠️ Applying this to an instance that already has the connector installed is not just an Update.
refresh_connector_after_reinstall(skald/accessors.rs) updates only thedescriptionof themcp_global_serversrow, then restarts from that row:commandandargs_jsonstay the ones snapshotted at the firstglobal_enable, i.e. stillnpx+/…/connectors/<id>/-y. Procedure: deploy → Update from the marketplace (rewritesscript_pathin the catalog) → open the connector page and re-save the config, the only call that recomputescommand/argsand runsensure_installed_host. Same care already noted for gmaps. Whether the refresh should also re-derive command/args is open for evaluation on the skald side.
-
gmaps: missing dependency install + verify wired (v6 / 1.1.0)
- Added
requirements.txt(googlemaps>=4.10.0) — it was the only python connector without one. Dependencies were declared in the manifestdependenciesfield, which skald uses only for the card:ensure_installed_hostlooks exclusively atrequirements.txt/package.json. Result: empty.pydepsand logs full ofNo module named 'googlemaps', with the server still answeringtools/list(→connected — 6 tool(s)on a broken connector). - Wired the
verify(python3 verify.py, 20s):verify.pywas shipped but the manifest had noverifyblock, and skald readsverify_commandonly from there. Now an activation with broken dependencies fails visibly instead of starting silently. verify.pyputs.pydepsonsys.path: skald setsPYTHONPATHonly for the server process (global_row_spec), while verify runs assh -c "python3 verify.py"without it. Without this line, verify would fail with "Missing dependency" even on a correctly installed connector, disabling the row. ⚠️ Same latent risk for every connector with averifythat imports non-stdlib dependencies (gcal in container): to be checked.- Removed
mcp_config.env: {"GOOGLE_MAPS_API_KEY": "{SECRET:…}"}(introduced 2026-07-23): inert.apply_key_placeholdersubstitutes{SECRET:}/{ENV:}tokens only in the URL, never inenvvalues. It worked because the admin form sendsenvand that payload overwritesentry.env_json; with an empty form the process would have received the literal string. ⚠️ The spec in this file and in CLAUDE.md says the opposite — either fix the spec, or extend the substitution toenvvalues on the skald side. - Re-aligned manifest↔fragment versions to
6/1.1.0/2026-08-10: they were 2/1.0.1 vs 5/1.0.4, and skald prefers the manifest (manifest.version.or(entry.version)) — soinstalled_versionstayed at 2 and the "Update available" badge would never have appeared. requires:ENV→API_KEY; server error messages cleaned of references tosecrets/gmaps_api_key.txt(deprecated path).- Index regenerated with compile.py ✅
- Added
2026-08-07
Added
- New connector: LinkedIn (mcp_local, scope user): server.py + session.py + verify.py + PNG icons
- Added to
connectors/index.json, index regenerated with compile.py (17 connectors total) .gitignoreupdated to ignore.claude/- Deploy to connectors.skaldagent.net via
skaldserveralias (192.168.1.100, LAN — no Tailscale)
2026-07-23
Changed
- gmaps: env var injection fix — added
mcp_config.envinconnector.jsonto injectGOOGLE_MAPS_API_KEYinto the MCP process. The connector was declared asdelivery: envbut withoutmcp_config.envSkald could not pass the variable to the Python process. Version bump: fragment 4→5, connector 1→2. Index regenerated with compile.py ✅ - Context7 icon update (PNG) — replaced Context7 icons from SVG to PNG (new icon provided by the user):
icon_sm.png— 48×48 (2.7 KB),icon_lg.png— 96×96 (4.5 KB). Old SVGs removed, references updated in fragment.json and connector.json. Version bump: fragment 3→4, connector 1→2. Index regenerated with compile.py ✅ - SerpAPI Flights icon update (PNG) — replaced SerpAPI Flights icons from SVG to PNG:
icon_sm.png— 48×48 (2.9 KB),icon_lg.png— 96×96 (6.8 KB). Old SVGs removed, references updated in fragment.json and connector.json. Version bump: fragment 4→5, connector 2→3. Index regenerated with compile.py ✅