Files
claude-plugins/wordpress/skills/mcp-happyfiles/SKILL.md
T
Emanuel Almeida 87e4290283 docs: skill mcp-happyfiles — MCP HappyFiles Pro (pastas media library)
Documenta a taxonomia happyfiles_category (hierárquica, attachments), o
gotcha include_children=true por omissão no WP_Query (corrigido no MCP),
query_var=false na taxonomia (wp post list --happyfiles_category não
funciona), e confirma no código-fonte que apagar pasta nunca apaga
ficheiros. 9 tools, verificação ponta-a-ponta contra descomplicar.pt
(produção) e starter.descomplicar.pt documentada.
2026-08-19 06:33:26 +01:00

109 lines
8.0 KiB
Markdown

---
name: mcp-happyfiles
description: MCP dedicado multi-site (node stdio, ligação `happyfiles` em ~/.omp/agent/mcp.json) para gerir as pastas da media library organizadas pelo HappyFiles Pro em qualquer site do bundle Descomplicar® onde o plugin esteja activo — listar pastas com contagem e hierarquia, criar/renomear/apagar pastas, listar ficheiros de uma pasta ou sem pasta, mover ficheiros entre pastas. Apagar uma pasta NUNCA apaga ficheiros. Site é um parâmetro em cada tool, não uma ligação fixa. Usar quando "happyfiles mcp", "pastas media library", "organizar biblioteca de media", "mover ficheiros de pasta wordpress", "criar pasta happyfiles", "apagar pasta happyfiles", "ficheiros sem pasta", "uncategorized happyfiles".
layer: wiki
---
# /mcp-happyfiles — MCP dedicado multi-site ao HappyFiles Pro
Projecto em `/media/ealmeida/Dados/Dev/mcp-happyfiles/` (TypeScript, SDK MCP oficial, stdio). Sem
código PHP novo no WordPress — cada tool corre `wp eval` via `ssh server` sobre a **API nativa de
taxonomias do WordPress** (`get_terms`, `wp_insert_term`, `wp_update_term`, `wp_delete_term`,
`wp_set_object_terms`, `wp_delete_object_term_relationships`), nunca SQL directo. `site` é um
parâmetro em cada tool, não uma ligação fixa por site.
## Arquitectura de dados (confirmada no código-fonte do plugin em 19-08-2026)
O HappyFiles Pro **não tem tabelas próprias** para pastas de media library. Cada "pasta" é um termo
da taxonomia custom `happyfiles_category` (constante `HAPPYFILES_TAXONOMY`), registada só para o
post type `attachment`, **hierárquica** (usa `parent`/`term_id` nativos do WordPress). Cada
ficheiro (attachment) pertence a uma pasta através de uma relação normal
`wp_term_relationships` — exactamente como categorias/tags em posts.
- **Contagem de ficheiros por pasta** = `WP_Term->count`, mantida automaticamente pelo WordPress via
`_update_generic_term_count` (callback registado pelo próprio plugin) sempre que
`wp_set_object_terms`/`wp_delete_term` corre. Nunca precisa de ser recalculada manualmente.
- **Metadados extra por pasta** (termmeta, opcionais): `happyfiles_position` (inteiro, ordenação
manual na UI) e `happyfiles_folder_color` (cor custom). Ambos ausentes por omissão.
- **"Sem pasta" (Uncategorized)** não é um termo real — é `tax_query` com `operator => NOT EXISTS`
sobre `happyfiles_category`. O próprio `Data::get_folders()` do plugin usa a convenção
`term_id = -1` para esta pseudo-pasta e `-2` para "Todos os ficheiros"; este MCP replica a mesma
convenção internamente (`folderId: -1` nas tools de listagem de ficheiros).
- **Gotcha WP_Query confirmado ao vivo:** `tax_query` por omissão tem `include_children => true`
(taxonomia hierárquica) — listar ficheiros de uma pasta-pai sem `include_children: false` devolve
também os ficheiros de todas as subpastas (reproduzido: pasta "Clientes" mostrava 120 ficheiros em
vez dos 7 directamente associados). Este MCP força sempre `include_children => false`, replicando
o mesmo padrão que o próprio `Actions::delete_folder()` do plugin usa para não apagar relações de
subpastas por engano.
- **`query_var` da taxonomia é `false`** (`public => false` na chamada `register_taxonomy`, confirmado
via `get_taxonomy('happyfiles_category')->query_var`) — `wp post list --happyfiles_category=X`
**não funciona**, nem via WP-CLI nem em pedidos normais; o próprio plugin nunca depende disto,
constrói sempre `tax_query` explícito em PHP. Por isso este MCP também nunca usa esse atalho.
- **Apagar pasta nunca apaga ficheiros:** `Actions::delete_folder()` (e o `wp_delete_term()` nativo
que ele chama) só remove a linha da taxonomia e as relações `wp_term_relationships` — os posts
`attachment` continuam a existir, só passam a "Sem pasta". Confirmado no código-fonte
(`includes/actions.php`) e testado ao vivo neste MCP (ver secção Verificação).
- **Uma pasta por ficheiro por omissão:** `wp_set_object_terms($id, [$folderId], $taxonomy, false)`
com `append=false` **substitui** a pasta anterior — é o comportamento por omissão do HappyFiles
Pro (`happyfiles_multiple_folders` = false). Este MCP replica exactamente essa semântica em
`happyfiles_move_files`.
## Sites conhecidos
Chamar `happyfiles_list_sites` para a lista actual. Confirmados HappyFiles Pro 1.8.3 activo ao vivo
em 19-08-2026: `descomplicar` (produção, `/home/ealmeida/public_html` — 66 pastas reais em uso,
1218 attachments, 893 sem pasta), `emanuelalmeida` (`emanuelalmeida.pt`), `starter`
(`starter.descomplicar.pt`). Também aceita um path absoluto directamente
(`/home/ealmeida/<site>`) para sites fora desta lista, sem exigir rebuild do MCP.
## Tools (9)
| Tool | Read-only | Uso |
|---|---|---|
| `happyfiles_list_sites` | sim | Aliases conhecidos, path WP, nota de estado |
| `happyfiles_get_status` | sim | Plugin instalado/activo + versão |
| `happyfiles_list_folders` | sim | Todas as pastas: id, nome, slug, `parent`, `count`, `position`, `color`, mais `all_files_count`/`uncategorized_count` |
| `happyfiles_create_folder` | não | Nova pasta, `parentId` opcional para subpasta |
| `happyfiles_rename_folder` | não | Novo nome + slug recalculado |
| `happyfiles_delete_folder` | não | **Nunca apaga ficheiros.** `deleteSubfolders:true` apaga em cascata; por omissão as subpastas sobem para o pai (comportamento nativo `wp_delete_term`) |
| `happyfiles_list_files_in_folder` | sim | Ficheiros **directamente** numa pasta (não inclui subpastas), paginado |
| `happyfiles_list_uncategorized_files` | sim | Ficheiros sem nenhuma pasta atribuída, paginado |
| `happyfiles_move_files` | não | 1+ ficheiros para uma pasta (substitui a pasta anterior) ou `folderId: null` para desassociar (Sem pasta) |
Todas as tools exigem `site` como primeiro parâmetro.
## Segurança
Nenhuma escrita usa SQL directo nem classes internas do plugin (não são autoload-seguras fora do
wp-admin) — só as funções nativas de taxonomia do WordPress, as mesmas que os handlers AJAX do
próprio HappyFiles Pro chamam (`includes/actions.php`, `includes/ajax.php`), pelo que os hooks
(`created_term`, `edited_term`, `delete_term`, `set_object_terms`) disparam sempre. O corpo PHP
corrido por `wp eval` é sempre um template estático sem texto do utilizador interpolado; nomes de
pasta e IDs de ficheiros viajam em JSON codificado em base64 pelo **STDIN** do processo remoto
(`php://stdin` dentro do PHP, `stream_get_contents(STDIN)`), nunca na linha de comando — evita por
completo ter de escapar aspas/unicode num nome de pasta para a shell remota.
## Verificação
Construído e testado ponta-a-ponta contra produção e staging em 19-08-2026:
- **Leituras cruzadas independentes** (`descomplicar`, produção): `happyfiles_list_folders` devolveu
66 pastas, `all_files_count: 1218` e `uncategorized_count: 893` — confirmados byte-a-byte via
`wp eval`/`wp post list --format=count` directos fora do MCP. `happyfiles_list_files_in_folder`
na pasta "Clientes" (id 42) devolveu `total: 7` depois de corrigido o gotcha `include_children`
(tinha devolvido 120 antes da correcção); confirmado via `wp post term list <id>
happyfiles_category` em vários ficheiros individuais devolvidos.
- **Ciclo de escrita completo em `starter`** (site vazio de pastas, 7 attachments — sandbox seguro):
`happyfiles_create_folder` → `happyfiles_rename_folder` → `happyfiles_move_files` (ficheiro 19
para a pasta nova, confirmado via `wp post term list` directo) → `happyfiles_list_files_in_folder`
(1 item) / `happyfiles_list_uncategorized_files` (6 itens, confirmado) → `happyfiles_move_files`
de volta a `null` (confirmado `wp post term list` vazio de novo) → `happyfiles_delete_folder` →
estado final confirmado idêntico ao inicial (`wp term list` vazio, `wp post list --format=count`
ainda 7, `wp post get 19` com o título original intacto).
## Skills relacionadas
Nenhuma skill de conhecimento dedicada ao HappyFiles Pro existe neste bundle — esta skill é a única
documentação (arquitectura de dados + tools). Ver `wp-cli` para o padrão geral de gestão via
WP-CLI no servidor CWP.