- 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
83 lines
3.6 KiB
Markdown
83 lines
3.6 KiB
Markdown
# Bug report: verify dei connector MCP in container fallisce con `exec: "-e": executable file not found`
|
|
|
|
**Progetto**: skald-circle (non il marketplace)
|
|
**File**: `crates/skald-core/src/mcp/verify.rs`
|
|
**Introdotto da**: commit `e6c4e20` — "feat(mcp): OAuth per-user connectors (§15) — providers, PKCE copy-paste flow, env credential delivery"
|
|
**Priorità**: alta — blocca l'attivazione di tutti i connector `mcp_local` + `scope: user` che hanno env/secret nel verify (LinkedIn ora, Email alla prossima riattivazione)
|
|
|
|
---
|
|
|
|
## 1. Sintomo
|
|
|
|
Attivando il connector `linkedin` (mcp_local, scope user) dal frontend, il verify fallisce con:
|
|
|
|
```
|
|
Failed — OCI runtime exec failed: exec failed: unable to start container process: exec: "-e": executable file not found in $PATH
|
|
```
|
|
|
|
## 2. Causa radice
|
|
|
|
In `crates/skald-core/src/mcp/verify.rs` (~righe 144-152) il comando `docker exec` viene costruito con il **nome del container PRIMA delle opzioni `-e`**:
|
|
|
|
```rust
|
|
VerifyTarget::Container { container, workdir } => {
|
|
let mut c = tokio::process::Command::new("docker");
|
|
c.arg("exec")
|
|
.arg("-w").arg(workdir)
|
|
.arg(container); // ← container name
|
|
inject_env_flags(&mut c, env_values, secret_values); // ← -e KEY=VAL DOPO il container
|
|
c.arg("sh").arg("-c").arg(&resolved);
|
|
c
|
|
}
|
|
```
|
|
|
|
`inject_env_flags` (righe 285-293) aggiunge `cmd.arg("-e").arg(format!("{k}={v}"))` per ogni env/secret.
|
|
|
|
Risultato: viene generato
|
|
|
|
```
|
|
docker exec -w <workdir> <container> -e KEY=VAL -e KEY2=VAL2 sh -c "python3 verify.py"
|
|
```
|
|
|
|
La sintassi di `docker exec` è `docker exec [OPTIONS] CONTAINER COMMAND [ARG...]`: **dopo** il nome del container ogni argomento è interpretato come COMMAND. Docker prova quindi a eseguire l'eseguibile `-e` → errore OCI.
|
|
|
|
## 3. Connector colpiti
|
|
|
|
Il bug scatta solo quando `env_values`/`secret_values` non sono vuoti, cioè quando il manifest del connector dichiara `env[]` (o secret) e il verify gira **in container**:
|
|
|
|
| Connector | Container? | Verify con env? | Colpito |
|
|
|---|---|---|---|
|
|
| linkedin | ✅ user | ✅ 2 secret + 3 env | ❌ si — errore visibile |
|
|
| email | ✅ user | ✅ 8 env | ❌ si — già attivo, fallirà alla prossima riattivazione |
|
|
| gcal / drive / gmail | ✅ user | credenziali OAuth via altro path | probabilmente no |
|
|
| gmaps, context7, tavily… | host / global | VerifyTarget::Host | no |
|
|
|
|
Nota: il path di **lancio del server MCP** in `crates/mcp-client/src/server.rs` (~righe 261-273) costruisce lo stesso comando **nell'ordine corretto** (`-i`, poi `-e …`, poi container) — usarlo come riferimento.
|
|
|
|
## 4. Fix suggerito
|
|
|
|
Spostare `inject_env_flags` **prima** di `.arg(container)` in `verify.rs`:
|
|
|
|
```rust
|
|
VerifyTarget::Container { container, workdir } => {
|
|
let mut c = tokio::process::Command::new("docker");
|
|
c.arg("exec").arg("-w").arg(workdir);
|
|
inject_env_flags(&mut c, env_values, secret_values); // ← spostato qui
|
|
c.arg(container);
|
|
c.arg("sh").arg("-c").arg(&resolved);
|
|
c
|
|
}
|
|
```
|
|
|
|
Il comando generato diventa:
|
|
|
|
```
|
|
docker exec -w <workdir> -e KEY=VAL -e KEY2=VAL2 <container> sh -c "python3 verify.py"
|
|
```
|
|
|
|
## 5. Verifica consigliata
|
|
|
|
1. **Test unitario**: aggiungere un test che costruisca il comando per `VerifyTarget::Container` e verifichi l'ordine degli argomenti (`docker exec -w <wd> -e K=V <container> sh -c …`). I test esistenti in `verify.rs` coprono solo `apply_placeholders`.
|
|
2. **E2E**: riattivare `linkedin` dal frontend (deve superare il verify con il cookie li_at).
|
|
3. **Regressione**: riattivare `email` (8 env) per confermare che il bug era latente anche lì.
|