funifier-mcp 0.3.19 → 0.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "funifier-mcp",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "description": "Funifier AI toolkit — MCP server, API client, and Claude Code skills for the Funifier gamification platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -70,6 +70,7 @@ Then read a result with `funifier_read_doc path=<path>`.
70
70
  | Upload files to Funifier — images and documents for player avatars, challenge resources, and visual assets; use when adding media to the platform, not for CSV data import (use funifier-import-csv) or static frontend hosting (use funifier-implement-frontend) | `references/upload-file.md` |
71
71
  | Create, list, and drop MongoDB single-field indexes on Funifier collections via the REST API. Composite (multi-field) indexes are NOT supported by this endpoint — see Limitation section. | `references/manage-indexes.md` |
72
72
  | Cross-check a project's Funifier API calls against the live security document — scan code for usage, build an evidence-backed manifest, run the deterministic audit engine, and report missing scopes, excess tokens, and static danger findings; use when debugging 401s, auditing minimum privilege, or verifying permissions before deploying; audit is read-only and never changes any configuration | `references/audit-permissions.md` |
73
+ | Use the server-side utility classes from com.funifier.engine.util in Groovy triggers, schedulers, and public endpoints — validates CPF, encrypts fields with AES/BCrypt/PGP, renders Mustache templates, evaluates inline expressions, computes object diffs/changelogs, converts JSON, generates Excel, makes HTTP calls, and handles files and pagination | `references/server-utils.md` |
73
74
 
74
75
  ## Documented Modules
75
76
 
@@ -65,19 +65,39 @@ If search returns insufficient results, read these directly:
65
65
 
66
66
  ## Steps
67
67
 
68
- ## ⚠ Regra crítica: triggers não impedem persistência via throw
68
+ ## ⚠ Regra crítica: quando `throw` interrompe a operação
69
69
 
70
- O Funifier **sempre salva o documento** antes de executar o trigger.
70
+ **dois modos**, e qual vale depende de onde a trigger roda:
71
71
 
72
- - `before_create` enriquecimento apenas (normalizar, preencher defaults)
73
- - Rejeitar criação usar `after_create`: validar se inválido:
72
+ - **Modo A — estrito (`throw` aborta):** SÓ em `before_create`/`before_update`/`before_delete` de **coleções de banco** via Database API (`POST`/`PUT`/`DELETE /v3/database/{collection}`). O `DatabaseRest` roda via `TriggerManager.executeStrict`: qualquer exceção aborta a operação — o documento não é gravado/removido e a API responde **HTTP 500** `{ "message": "<msg>", "statusCode": 500 }`. ⚠️ **Recurso version-dependent** — nem toda instância recebeu a atualização. **Sonde antes de depender** (ver bloco de detecção abaixo) ou use o Modo B.
73
+ - **Modo B persistência garantida (`throw` NÃO cancela):** todo o resto (player, action, swap, quiz, achievement pelos managers, eventos `after_*`, `*_bulk`/`csv_*`). O documento é salvo antes do trigger rodar. Rejeitar = `after_create`:
74
74
  ```java
75
- database.delete(entity._id, "collection__c");
75
+ database.delete(entity.id, "collection__c");
76
76
  entity.clear();
77
77
  entity.put("message", "motivo");
78
78
  return;
79
79
  ```
80
- - Para lógica complexa, use `BusinessException` interna (capturada dentro do trigger, não propaga para a plataforma).
80
+ Para lógica complexa, use `BusinessException` interna (capturada dentro do trigger).
81
+
82
+ **Regra de ouro:** se o suporte ao Modo A não for confirmado, **gere código no Modo B** e diga ao usuário que o Modo A exige instância atualizada. Detalhes e exemplos: `funifier_read_doc path=guides/triggers-guide` §8.
83
+
84
+ ## 🔎 Detectar suporte ao Modo A (sonda)
85
+
86
+ Antes de entregar uma trigger que aborta via `throw`, confirme na instância conectada:
87
+
88
+ ```
89
+ # 1. cria trigger-sonda que sempre lança exceção
90
+ funifier_save type=trigger payload={"name":"__probe_strict_mode__","entity":"probe_strict__c","event":"before_create","active":true,"script":"void trigger(event, entity, player, database){ throw new RuntimeException(\"__STRICT_PROBE_BLOCKED__\"); }"}
91
+ # 2. tenta inserir (passa por DatabaseRest.insert → executeStrict)
92
+ funifier_database action=insert collection=probe_strict__c payload={"probe":true}
93
+ # → erro 500 com "__STRICT_PROBE_BLOCKED__" = Modo A SUPORTADO
94
+ # → insert bem-sucedido = Modo A NÃO suportado (use Modo B)
95
+ # 3. limpeza (sempre)
96
+ funifier_database action=delete collection=probe_strict__c filter={"probe":true}
97
+ funifier_delete type=trigger id=<_id da sonda>
98
+ ```
99
+
100
+ Sem permissão de escrita / produção sensível → **assuma o Modo B** e avise o usuário.
81
101
 
82
102
  ---
83
103
 
@@ -129,8 +149,8 @@ Perguntar (ou inferir do contexto):
129
149
  | `achievement` | `before_create` | Enriquecer conquista com dados de origem (`context.extra`) |
130
150
  | `player` | `after_create` | Inicializar campos customizados ao criar jogador |
131
151
  | `player` | `before_update` | Normalizar campos antes de salvar atualização |
132
- | `custom__c` | `before_create` | Normalizar/enriquecer documento customizado |
133
- | `custom__c` | `after_create` | Validar e rejeitar se inválido (delete + message) |
152
+ | `custom__c` | `before_create` | Normalizar/enriquecer documento; **rejeitar via `throw` no Modo A** (instância atualizada — sondar antes) |
153
+ | `custom__c` | `after_create` | Validar e rejeitar se inválido (delete + message) — **portável, qualquer instância** |
134
154
  | `custom__c` | `after_bulk` | Processar import em lote (entity é uma List) |
135
155
 
136
156
  ### 2. Verificar se já existe
@@ -183,11 +203,3 @@ funifier_logs type=trigger id=<_id>
183
203
  ```
184
204
 
185
205
  Confirme que não há erros de compilação ou execução. Se houver, leia o stack trace e corrija o script.
186
-
187
- ## Verified References
188
-
189
- | Claim | Status | Evidence |
190
- |-------|--------|----------|
191
- | Achievement constants TYPE_POINT=0, TYPE_CHALLENGE=1, TYPE_VIRTUAL_GOOD=2, TYPE_LEVEL=3 are defined in the Achievement class | ✓ verified | Class:src/main/java/com/funifier/engine/achievement/Achievement.java:Achievement |
192
- | ActionLog is the entity class for action triggers with fields actionId, userId, attributes (Map), time, and id | ✓ verified | Class:src/main/java/com/funifier/engine/action/ActionLog.java:ActionLog |
193
- | TriggerManager is the class that manages trigger script execution and lifecycle in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/integration/trigger/TriggerManager.java:TriggerManager |
@@ -90,9 +90,3 @@ Leia o arquivo de doc específico para o módulo com problema:
90
90
  - Scheduler → `funifier_read_doc path=modules/scheduler`
91
91
  - Aggregate → `funifier_read_doc path=guides/aggregates`
92
92
  - Security/Auth → `funifier_read_doc path=modules/security`
93
-
94
- ## Verified References
95
-
96
- | Claim | Status | Evidence |
97
- |-------|--------|----------|
98
- | TriggerManager is the entry point for trigger script execution and error capture in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/integration/trigger/TriggerManager.java:TriggerManager |
@@ -79,9 +79,3 @@ Baseado na tabela acima, instrua o usuário a usar a skill específica.
79
79
  ### 4. Se não encontrar skill específica
80
80
 
81
81
  Consulte `funifier_read_doc path=index` e leia o módulo relevante diretamente.
82
-
83
- ## Verified References
84
-
85
- | Claim | Status | Evidence |
86
- |-------|--------|----------|
87
- | Achievement is the core entity class representing all gamification rewards in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/achievement/Achievement.java:Achievement |
@@ -0,0 +1,94 @@
1
+ # funifier-server-utils
2
+
3
+ Use the server-side utility classes from com.funifier.engine.util in Groovy triggers, schedulers, and public endpoints — validates CPF, encrypts fields with AES/BCrypt/PGP, renders Mustache templates, evaluates inline expressions, computes object diffs/changelogs, converts JSON, generates Excel, makes HTTP calls, and handles files and pagination
4
+
5
+ ---
6
+
7
+ ## Formato do payload (obrigatório)
8
+
9
+ Funifier armazena código como **strings JSON escapadas**. Ao montar o payload do `funifier_save`:
10
+
11
+ - **Quebra de linha** → `\n` (nunca newline literal dentro da string)
12
+ - **Aspas duplas** dentro do código → `\"`
13
+ - **Backslash** → `\\` (regex `\b` vira `\\b`; dentro de Groovy com string-building pode exigir `\\\\b`)
14
+ - **Tab** → `\t` (se usar)
15
+ - **Pipelines de aggregate** vão como **string JSON** (não objeto aninhado) — serialize o array inteiro
16
+
17
+ A regra prática: monte o objeto em JavaScript normalmente e passe por `JSON.stringify` — o MCP faz isso automaticamente quando você entrega o payload como JSON. **Nunca** cole código multilinha cru no meio do JSON.
18
+
19
+ ### Exemplo 1 — custom-page (html + angularjs script)
20
+
21
+ ```json
22
+ {
23
+ "title": "Ciclos",
24
+ "slug": "studio/custom/ciclos",
25
+ "html": "<div class=\"row\">\n <div class=\"col-md-12\">\n <h2>Ciclos</h2>\n </div>\n</div>\n",
26
+ "script": "$scope.all = [];\n$scope.loading = false;\n\n$scope.list = function () {\n $scope.loading = true;\n};\n$scope.list();\n"
27
+ }
28
+ ```
29
+
30
+ ### Exemplo 2 — aggregate preparado (pipeline JSON + script Groovy)
31
+
32
+ ```json
33
+ {
34
+ "_id": "extrato",
35
+ "title": "Extrato de Pontos",
36
+ "collection": "extrato",
37
+ "aggregate": "[\n {\n \"$match\": { \"player\": \"$param:player\" }\n },\n {\n \"$sort\": { \"time\": -1 }\n }\n]",
38
+ "script": "void prepare(aggregations, params) {\n if (context.get(\"player\") != null) {\n params.put(\"player\", context.get(\"player\"));\n } else {\n params.put(\"player\", \"NAO_EXISTE\");\n }\n}\n"
39
+ }
40
+ ```
41
+
42
+ Note que `aggregate` é uma **string** contendo JSON serializado (com `\n` e `\"` escapados), **não** um array nativo. Mesma regra vale para `script` em triggers/schedulers/aggregates e `html`/`script` em custom-pages.
43
+
44
+ ---
45
+
46
+ ## Before starting — find relevant docs
47
+
48
+ Use the `funifier_search_docs` MCP tool to load only what you need:
49
+
50
+ ```
51
+ funifier_search_docs "cpf cnpj validar validate cpf-util aes encrypt decrypt criptografar criptografia bcrypt hash senha password pgp pgpcrypt rsa asymmetric totp otp 2fa qrcode google-authenticator mustache template render handlebars expression inline formula avaliar diff changelog auditoria comparar compare json serialize deserialize jsonutil excel xlsx spreadsheet planilha relatorio currency moeda formatar format http get post requisicao external url read-url pagination paginar paginacao paginate file stream arquivo util helper utility server-side groovy"
52
+ ```
53
+
54
+ Then read the most relevant results with `funifier_read_doc path=<path>`.
55
+
56
+ ## Primary docs for this skill
57
+
58
+ If search returns insufficient results, read these directly:
59
+
60
+ - `funifier_read_doc path=guides/server-utils`
61
+ - `funifier_read_doc path=guides/triggers-guide`
62
+ - `funifier_read_doc path=guides/java-managers`
63
+
64
+ ## Steps
65
+
66
+ ### 1. Understand the requirement
67
+
68
+ Ask the user what they want to create or accomplish. Gather:
69
+ - The name/title
70
+ - The purpose and behavior
71
+ - Any specific configuration or constraints
72
+
73
+ ### 2. Search for relevant documentation
74
+
75
+ Run the lexical search (command shown above) and read the returned files.
76
+
77
+ ### 3. Check existing resources (if MCP available)
78
+
79
+ Use `funifier_list` with the relevant type and a `search` parameter to see
80
+ if a similar resource already exists. Never list all resources without a search term.
81
+
82
+ ### 4. Design and confirm
83
+
84
+ Based on the docs, outline the configuration to the user and confirm before saving.
85
+
86
+ ### 5. Create or update
87
+
88
+ Use `funifier_save` with the appropriate type and a JSON payload to create or
89
+ update the resource. If MCP is unavailable, show the complete JSON for manual use.
90
+
91
+ ### 6. Validate
92
+
93
+ Use `funifier_logs` (for triggers/schedulers) or `funifier_get` to confirm
94
+ the resource was saved correctly and executed without errors.