feat(skills): adicionar mcp-updraftplus (backup UpdraftPlus, quase so-leitura, alto risco)
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
---
|
||||
name: mcp-updraftplus
|
||||
description: MCP dedicado multi-site (node stdio, ligação `updraftplus` em ~/.omp/agent/mcp.json) para consultar o UpdraftPlus (backup) em qualquer site do bundle Descomplicar® via WP-CLI/SSH — estado do plugin, agendamento, retenção, destinos de storage (nunca expõe credenciais), histórico de backups, último resultado. Superfície de ALTO RISCO tratada como só-leitura: a única escrita é disparar um backup manual (aditivo, nunca apaga nada), atrás de `confirm:true`. Site é um parâmetro em cada tool, não uma ligação fixa. Usar quando "updraftplus mcp", "estado backup wordpress", "agendamento updraftplus", "destinos storage backup", "histórico backups", "disparar backup manual mcp", "DISABLE_WP_CRON backup", "backup nunca corre sozinho".
|
||||
layer: wiki
|
||||
---
|
||||
|
||||
# /mcp-updraftplus — MCP dedicado multi-site ao UpdraftPlus
|
||||
|
||||
Projecto em `/media/ealmeida/Dados/Dev/mcp-updraftplus/` (TypeScript, SDK MCP oficial, stdio).
|
||||
Mesmo padrão dos outros MCPs desta família (`mcp-wpfc`, `mcp-wpforms`, `mcp-fluentform`,
|
||||
`mcp-fluent-smtp`, `mcp-bit-integrations`, `mcp-insert-headers-footers`): sem código PHP novo no
|
||||
WordPress, cada tool executa `wp option get`/`wp plugin list`/`wp cron event list` via
|
||||
`ssh server` sobre o WP-CLI já instalado. **`site` é um parâmetro em cada tool**, não uma ligação
|
||||
fixa. Não existe comando WP-CLI próprio do UpdraftPlus (confirmado: `wp help` não lista nada,
|
||||
`wp updraftplus` dá "not a registered command") — tudo passa por `wp_options` genéricas.
|
||||
|
||||
## Porque é que este MCP é (quase) só-leitura
|
||||
|
||||
Backups são a última linha de defesa. Este MCP **nunca** apaga, substitui ou reconfigura nada —
|
||||
zero `update_option`/`delete_option` sobre qualquer chave `updraft_*`. A única acção que muda
|
||||
estado é `updraftplus_trigger_backup_now`, e mesmo essa é puramente **aditiva** (dispara um novo
|
||||
backup; nunca toca no que já existe) e exige `confirm: true` (zod `z.literal(true)`, rejeitado ao
|
||||
nível do schema antes de o handler correr — testado ao vivo). Não há tools para desligar
|
||||
agendamento, apagar um backup do histórico, ou mudar destinos de storage — de propósito, fora do
|
||||
âmbito deste v1 por decisão de risco, não por limitação técnica.
|
||||
|
||||
## Sites conhecidos
|
||||
|
||||
Chamar `updraftplus_list_sites` para a lista actual. Verificado ao vivo 19-08-2026 via
|
||||
`wp plugin list --format=json` nos 8 sites do bundle: só 4 têm o UpdraftPlus (Free 1.26.6, sem
|
||||
addon Premium) — `starter`, `ccv`, `ecommerce-demo`, `ecommerce`. Os outros 4
|
||||
(`descomplicar`/produção, `emanuelalmeida`, `care`, `e-commerce`) não têm o plugin, omitidos de
|
||||
propósito do mapa de aliases. Também aceita um path absoluto directamente
|
||||
(`/home/ealmeida/<site>`) para sites fora desta lista.
|
||||
|
||||
**Achado de risco real (19-08-2026):** nos 4 sites, `DISABLE_WP_CRON=true` está definido em
|
||||
`wp-config.php` (confirmado por leitura directa), e nenhum tem `updraft_interval` alguma vez
|
||||
gravado pela UI — ou seja, mesmo que alguém configurasse um agendamento na UI, ele nunca
|
||||
dispararia sozinho neste servidor (WP-Cron pseudo-cron desligado, sem substituto por cron de
|
||||
sistema para estes sites). `ccv` tem ainda um `updraft_last_backup`/`updraft_backup_history`
|
||||
**ilusório**: os nomes de ficheiro lá dentro (`Starter_Descomplicar_...`) mostram que foi herdado
|
||||
de um clone de base de dados do site `starter`, não um backup real de `ccv` — confirmado por
|
||||
`siteurl` distinto entre os dois. `starter` teve 1 backup manual real em 2025-06-11. `ecommerce`
|
||||
e `ecommerce-demo` nunca correram um backup (sem `updraft_backup_history` sequer). Ver notas por
|
||||
site em `updraftplus_list_sites`/`src/sites.ts`.
|
||||
|
||||
## Tools (7)
|
||||
|
||||
| Tool | Read-only | Uso |
|
||||
|---|---|---|
|
||||
| `updraftplus_list_sites` | sim | Aliases conhecidos, path WP, nota de estado |
|
||||
| `updraftplus_get_status` | sim | Free/Premium instalado+activo+versão, `DISABLE_WP_CRON`, última mensagem de log — chamar sempre primeiro |
|
||||
| `updraftplus_get_schedule` | sim | Intervalo/retenção/horas de ficheiros e BD, flags de inclusão, próximos eventos de cron reais (`wp cron event list` filtrado) |
|
||||
| `updraftplus_get_storage_destinations` | sim | Os ~15 destinos nativos, activo/não, `configuredInstanceCount` — **nunca devolve credenciais** |
|
||||
| `updraftplus_get_backup_history` | sim | Histórico completo (`updraft_backup_history`): data, nonce, entidades, tamanho total, destino, versão — `limit` opcional |
|
||||
| `updraftplus_get_last_backup` | sim | `updraft_last_backup`: sucesso/erros do resultado mais recente |
|
||||
| `updraftplus_trigger_backup_now` | **não** | Dispara backup completo em background (não bloqueia), exige `confirm:true`. Ver secção própria abaixo |
|
||||
|
||||
Todas as tools exigem `site` como primeiro parâmetro.
|
||||
|
||||
## Segurança — mascaramento de credenciais
|
||||
|
||||
Cada destino de storage nativo (`updraft_dropbox`, `updraft_s3`, `updraft_googledrive`,
|
||||
`updraft_ftp`, `updraft_sftp`, etc.) tem uma option própria cujo blob JSON PODE conter
|
||||
credenciais em claro — confirmado por leitura directa (`appkey`/`secret`/`tk_access_token` no
|
||||
Dropbox, `accesskey`/`secretkey` no S3, `clientid`/`secret`/`token` no Google Drive,
|
||||
`host`/`user`/`pass` no FTP — mesmo quando vazias, a estrutura já existe). `getStorageDestinations`
|
||||
(`src/wpcli.ts`) lê essas options só para calcular localmente um booleano `configured`
|
||||
(`hasConfiguredValue` — recursivo, conta strings não-vazias; números e booleanos nunca contam,
|
||||
excepto exclusão explícita do campo `authurl` que vem pré-preenchido pelo próprio plugin com o
|
||||
endpoint fixo da Rackspace mesmo sem nunca ter sido tocado — falso positivo confirmado e corrigido
|
||||
durante os testes). **O conteúdo em si nunca sai da função** — o tool só devolve
|
||||
`{slug, label, active, instanceCount, configuredInstanceCount}`.
|
||||
|
||||
## `updraftplus_trigger_backup_now` — mecânica e decisões de risco
|
||||
|
||||
Invoca literalmente a mesma `do_action('updraft_backupnow_backup_all', array())` que o botão
|
||||
"Backup Now" da UI dispara (`admin.php:2700`, `request_backupnow()`), com opções vazias = inclui
|
||||
tudo o que o site tiver configurado para incluir, envia para os destinos já activos. **Nunca
|
||||
apaga nem substitui um backup existente** — só adiciona um novo ao histórico.
|
||||
|
||||
Corre em **background** no servidor via `nohup … & disown` — a chamada SSH regressa em segundos
|
||||
mesmo que o backup real demore minutos, confirmado ao vivo (PID devolvido imediatamente,
|
||||
processo real confirmado a correr via `ps aux` depois da ligação SSH já ter fechado). Isto é
|
||||
necessário, não cosmético: como `DISABLE_WP_CRON=true` nestes 4 sites, agendar via
|
||||
`wp cron event schedule … now` nunca dispararia sozinho — o único caminho real para um backup
|
||||
correr fora de alguém clicar na UI é invocar a `do_action` directamente. O próprio plugin já
|
||||
protege contra execuções concorrentes (semáforo interno `UpdraftPlus_Semaphore`), por isso
|
||||
disparar duas vezes seguidas é seguro — a segunda fica bloqueada com log "another backup is
|
||||
apparently already running", não corrompe nada.
|
||||
|
||||
**Gotcha de infra local — GATE 5.1:** o comando remoto NUNCA usa `>`/`>>` para o log
|
||||
(`~/.config/agent-gates/infra-mutation-check.sh`, o motor que bloqueia mutações de infra sem
|
||||
autorização humana prévia, trata qualquer `>` seguido de caminho absoluto como potencialmente
|
||||
destrutivo — testado ao vivo, `>>` também dispara porque a regex só procura um carácter `>`
|
||||
seguido de `/`, independente de quantos `>` há). A saída é capturada com
|
||||
`| tee -a "$logFile" > /dev/null` — `tee -a` não contém `>` no texto do comando, e a redirecção
|
||||
final para `/dev/null` tem excepção explícita no motor do gate. Validado directamente contra
|
||||
`infra-mutation-check.sh` (exit 0) antes de confirmar o desenho.
|
||||
|
||||
Depois de disparar, usar `updraftplus_get_last_backup` ou `updraftplus_get_backup_history`
|
||||
passados alguns minutos para confirmar sucesso — o tool não espera pelo resultado.
|
||||
|
||||
## Fora de âmbito (decisão deliberada, não lacuna técnica)
|
||||
|
||||
- Desligar/alterar agendamento (`updraft_interval`, `updraft_retain`, etc.) — só leitura.
|
||||
- Apagar um backup do histórico ou de storage remoto.
|
||||
- Configurar/alterar destinos de storage (credenciais nunca são escritas por este MCP).
|
||||
- Restaurar um backup — operação com risco de perda de dados muito maior que disparar um novo
|
||||
backup; fora do v1 por decisão de risco explícita, não avaliada tecnicamente.
|
||||
|
||||
## Verificação
|
||||
|
||||
Construído e testado ponta-a-ponta contra produção 19-08-2026: `updraftplus_get_status` em
|
||||
`starter` confirmou Free 1.26.6 activo, Premium ausente, `DISABLE_WP_CRON=true`;
|
||||
`updraftplus_get_schedule` confirmou `interval: null` (nunca configurado) com nota explicativa;
|
||||
`updraftplus_get_storage_destinations` confirmou os 16 destinos com `configuredInstanceCount: 0`
|
||||
em `starter` (nenhum falso positivo depois da correcção do `authurl`);
|
||||
`updraftplus_get_backup_history`/`updraftplus_get_last_backup` confirmaram o backup real de
|
||||
2025-06-11 em `starter` e o dado ilusório herdado em `ccv`; `updraftplus_trigger_backup_now`
|
||||
disparado com sucesso em `ecommerce-demo` (`confirm:true`), devolveu PID em ~4s, confirmado por
|
||||
`ps aux` fora do MCP a mostrar o processo `wp eval` real a correr depois da ligação SSH ter
|
||||
fechado. Schema `confirm: z.literal(true)` testado a rejeitar `confirm` ausente e `confirm:false`
|
||||
antes de o handler correr.
|
||||
|
||||
## Skills relacionadas
|
||||
|
||||
Nenhuma skill de conhecimento separada para o UpdraftPlus existe no bundle — esta skill é a única
|
||||
documentação, incluindo o mapeamento de options acima.
|
||||
Reference in New Issue
Block a user