feat(wordpress): nova skill mcp-fluent-booking - MCP dedicado FluentBooking/FluentBooking Pro
Cobre: calendarios, event types, reservas (listar/detalhe/mudar estado/reenviar confirmacao), actividade, disponibilidade, reports, definicoes gerais, anfitrioes, estado do plugin/licenca Pro. 15 tools via REST API real com Application Password (nao SSH/SQL como mcp-bit-social - o FluentBooking regista register_rest_route com permission_callback por capability). Testado ponta-a-ponta em producao 19-08-2026, incluindo escrita sem mutar dados reais (422 'No changes found' do proprio plugin). references/api-reference.md com os endpoints/filtros/enums confirmados e references/diagnostics.md com o playbook de uso (agenda, cancelamento, health check).
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# FluentBooking — referência da REST API (confirmado em produção, 2026-08-19)
|
||||
|
||||
Namespace: `fluent-booking/v2` (WP REST API real, `wp-json/fluent-booking/v2/...`). Auth: Basic
|
||||
Auth com Application Password — o `permission_callback` de cada rota é uma `Policy` que verifica
|
||||
`current_user_can()`/`PermissionManager`, não nonce de sessão. 100 rotas registadas entre free e
|
||||
Pro; este ficheiro documenta só as usadas pelo MCP.
|
||||
|
||||
## Calendários (`/calendars`)
|
||||
|
||||
`GET /calendars` — lista todos, cada um com `slots[]` (event types) aninhados, incluindo
|
||||
`settings.weekly_schedules` completo por dia. `GET /calendars/{id}` — um só, mesma forma.
|
||||
|
||||
Campos relevantes de um calendar: `id`, `title`, `slug`, `status` (`active`/…), `type`
|
||||
(`simple`/…), `visibility` (`public`/…), `author_timezone`, `public_url`
|
||||
(`https://descomplicar.pt/?fluent-booking=calendar&host=<slug>`), `author_profile` (nome, avatar,
|
||||
telefone).
|
||||
|
||||
## Event types (`/events/{event_id}`, aninhado em `calendars[].slots[]`)
|
||||
|
||||
`GET /events/{event_id}` → `{calendar_event: {...}}`. Campos: `id`, `calendar_id`, `duration`
|
||||
(minutos), `title`, `slug`, `description` (HTML), `settings.schedule_type`
|
||||
(`weekly_schedules`/…), `settings.weekly_schedules.<dia>.{enabled, slots:[{start,end}]}`.
|
||||
|
||||
**Gotcha de nomes:** `GET /calendars/event-lists` (sem id) devolve sempre
|
||||
`{"code":"plugin_exception", ...}` em produção — não é um bug do MCP, o controller
|
||||
`CalendarController@getCalendarEventLists` está partido standalone nesta instalação. Não usar
|
||||
este endpoint; listar event types via `fb_list_calendars`/`fb_get_calendar` (já vêm aninhados).
|
||||
|
||||
## Reservas (`/schedules`)
|
||||
|
||||
`GET /schedules` — parâmetros via `filters[...]` (bracket notation, o MCP trata isto
|
||||
automaticamente a partir de campos planos no input schema):
|
||||
|
||||
| Filtro | Valores | Nota |
|
||||
|---|---|---|
|
||||
| `filters[period]` | `upcoming` (omissão), `completed`, `cancelled`, `pending`, `no_show`, `latest_bookings`, `all` | Valor fora da lista cai silenciosamente para `upcoming` |
|
||||
| `filters[author]` | id numérico do calendário, `me`, `all` | Sem permissão "ver todas as reservas", o utilizador só vê as suas mesmo que peça `all` |
|
||||
| `filters[event]` | id numérico do event type | |
|
||||
| `filters[event_type]` | `single`/`group`/… | |
|
||||
| `filters[email]` | email do convidado | |
|
||||
| `filters[range]` | `[date_from, date_to]` | Filtra por `created_at`, não pela hora da reunião |
|
||||
| `search` | texto livre | nome/email do convidado |
|
||||
| `page` | inteiro | paginação Laravel-style |
|
||||
|
||||
Forma de uma reserva (`schedules.data[]`): `id`, `hash`, `calendar_id`, `event_id`, `group_id`
|
||||
(agrupa reservas de grupo), `host_user_id`, `start_time`/`end_time` (timezone do site),
|
||||
`first_name`/`last_name`/`email`/`phone`/`message`, `location_details`
|
||||
(`{type, online_meeting_link}` ou presencial), `status`
|
||||
(`scheduled`/`completed`/`cancelled`/`rejected`/`no_show`), `payment_status`, `source_url`
|
||||
(página onde o convidado marcou), `custom_form_data` (campos custom do formulário de marcação,
|
||||
por chave), `calendar_event` (event type completo aninhado, redundante mas presente sempre),
|
||||
`happening_status`, `booking_status_text`, `reschedule_url`.
|
||||
|
||||
`GET /schedules/{id}` — mesma forma para uma reserva.
|
||||
|
||||
`PUT /schedules/{id}` (`fb_update_booking_status`) — body `{column:"status", value:<estado>,
|
||||
cancel_reason?, reject_reason?, refund_payment?}`. Colunas válidas no controller real:
|
||||
`internal_note`, `email`, `phone`, `first_name`, `last_name`, `status`, `payment_status` — o MCP
|
||||
só expõe `status` deliberadamente (as outras deixam editar dados do convidado sem justificação de
|
||||
negócio clara; ver SKILL.md "Fora do âmbito"). Side-effects reais confirmados no código
|
||||
(`SchedulesController::patchBooking`):
|
||||
- `status=cancelled` → `Booking::cancelMeeting($reason, 'host', $userId)` + email de cancelamento.
|
||||
- `status=rejected` → `Booking::rejectMeeting($reason, $userId)`.
|
||||
- `status=scheduled` com `payment_method`+`payment_order` associados → marca a order como `paid`.
|
||||
- Valor igual ao actual → `422 {"message":"No changes found"}` (não é um bug, é a validação do
|
||||
próprio plugin — útil para testar o caminho de escrita sem mutar nada).
|
||||
|
||||
`POST /schedules/{id}/send-confirmation-email` (`fb_send_confirmation_email`) — sem body, envia
|
||||
email real.
|
||||
|
||||
## Actividade (`/schedules/{id}/activities`, `/reports/activities`)
|
||||
|
||||
Mesma forma nos dois: `{id, booking_id, parent_id, created_by, status, type, title, description,
|
||||
created_at, updated_at}`. `/reports/activities` é o log do site inteiro (todas as reservas);
|
||||
`/schedules/{id}/activities` filtra a uma só.
|
||||
|
||||
## Disponibilidade (`/availability`)
|
||||
|
||||
`GET /availability` — lista templates reutilizáveis (`{id, host_name, title, usage_count,
|
||||
settings:{timezone, date_overrides[], weekly_schedules}}`). `GET /availability/{id}` — um só,
|
||||
envelope `{schedule: {...}}` em vez de `{availabilities: {data:[...]}}`.
|
||||
|
||||
## Reports (`/reports`, `/reports/graph-reports`)
|
||||
|
||||
`GET /reports` → `{overview: [{title, period?, number, content, stat}], latest_books: [...]}`.
|
||||
Métricas confirmadas: Total Bookings, Completed Bookings, Cancelled Bookings, Total Guests.
|
||||
|
||||
`GET /reports/graph-reports?date_range[0]=YYYY-MM-DD&date_range[1]=YYYY-MM-DD` →
|
||||
`{booked_stats, completed_stats, cancelled_stats}`, cada um `{"YYYY-MM-DD": count}`. Sem
|
||||
`date_range`, o controller usa uma janela por omissão (~7 dias, granularidade adaptada ao
|
||||
intervalo — dia/semana/mês).
|
||||
|
||||
## Definições e equipa
|
||||
|
||||
`GET /settings/general` → `{payments, emailing, administration}` (moeda, remetente/rodapé de
|
||||
email, `auto_cancel_timing`, dia de início da semana). `GET /admin/all-hosts` →
|
||||
`{hosts: [{id, name, label, avatar, calendar_id, deleted_user}]}`. `GET /settings/license` (Pro)
|
||||
→ `{status, variation_title, expires, is_expired, activation_hash, renew_url, purchase_url}`.
|
||||
@@ -0,0 +1,57 @@
|
||||
# FluentBooking — playbook de diagnóstico
|
||||
|
||||
## "Quem marcou uma reunião?" / ver a agenda
|
||||
|
||||
`fb_list_bookings({period: "upcoming"})` para o que vem aí (omitir `period` já faz isto por
|
||||
omissão). Para histórico completo (incluindo já realizadas/canceladas), usar
|
||||
`fb_list_bookings({period: "all"})` — **omitir `period` NUNCA mostra o histórico**, só o que
|
||||
ainda não aconteceu. Filtrar por convidado com `email` ou `search` (nome).
|
||||
|
||||
Cada resultado já traz `location_details` (link da reunião online), `custom_form_data` (respostas
|
||||
ao formulário de marcação — telefone, empresa, cargo, conforme configurado no event type) e
|
||||
`source_url` (de que página do site veio a marcação).
|
||||
|
||||
## Cancelar ou reagendar uma reunião
|
||||
|
||||
Cancelar: `fb_update_booking_status({booking_id, status: "cancelled", cancel_reason: "..."})` —
|
||||
dispara o email de cancelamento ao convidado automaticamente, não é preciso fazer mais nada.
|
||||
`refund_payment: true` só faz sentido se a reserva tiver `payment_method` associado (evento pago).
|
||||
|
||||
Reagendar não é uma tool deste MCP — a reserva tem um `reschedule_url` próprio
|
||||
(`https://descomplicar.pt/?fluent-booking=booking&meeting_hash=...&type=reschedule`) que o
|
||||
convidado usa directamente; não há endpoint admin para reatribuir hora sem passar por aí.
|
||||
|
||||
## Marcar como "não compareceu" / concluída manualmente
|
||||
|
||||
`fb_update_booking_status({booking_id, status: "no_show"})` ou `status: "completed"`. Sem motivo
|
||||
associado (`cancel_reason`/`reject_reason` só se aplicam a `cancelled`/`rejected`).
|
||||
|
||||
## Reenviar confirmação a um convidado
|
||||
|
||||
`fb_send_confirmation_email({booking_id})` — só se o convidado pedir explicitamente ou perdeu o
|
||||
email original. Dispara um envio real; não usar para "confirmar que a tool funciona".
|
||||
|
||||
## `fb_list_bookings` devolve vazio
|
||||
|
||||
Quase sempre é o `period` por omissão (`upcoming`) sem reservas futuras — confirmar com
|
||||
`fb_get_reports` (overview mostra o total histórico) antes de assumir que a agenda está vazia; se
|
||||
o total for >0 mas `upcoming` vier vazio, repetir com `period: "all"`.
|
||||
|
||||
## Investigar uma reunião específica em detalhe
|
||||
|
||||
`fb_get_booking({booking_id})` para os dados completos, depois `fb_list_activities({booking_id})`
|
||||
para a timeline (emails de lembrete enviados, mudanças de estado, quem cancelou e porquê — o
|
||||
`created_by` fica `null` quando a acção foi automática/pelo sistema).
|
||||
|
||||
## Health check rápido
|
||||
|
||||
`fb_get_plugin_status` (versões + licença Pro) + `fb_get_reports` (totais) — dois tools sem
|
||||
argumentos para um snapshot inicial. `fb_list_hosts` confirma que anfitriões têm calendário activo
|
||||
antes de investigar "porque é que ninguém consegue marcar reunião com X".
|
||||
|
||||
## Fora do âmbito deste MCP (fazer via wp-admin)
|
||||
|
||||
- Criar uma reserva em nome de alguém (payload de slots dinâmico, risco de email indevido).
|
||||
- Gerir equipa/permissões, métodos de pagamento, integrações Zoom/Google Calendar/CalDAV, SMS
|
||||
(Twilio), webhooks, cupões.
|
||||
- Activar/desactivar a licença Pro (`fb_get_plugin_status` é read-only).
|
||||
Reference in New Issue
Block a user