funifier-mcp 0.3.9 → 0.3.10
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/.cursor/rules/funifier.mdc +3 -1
- package/.github/copilot-instructions.md +2 -0
- package/AGENTS.md +5 -44
- package/README.md +1 -0
- package/datasource-funifier-docs/.coverage.json +4 -1
- package/dist/core/api-client.d.ts +8 -1
- package/dist/core/api-client.d.ts.map +1 -1
- package/dist/core/api-client.js +72 -0
- package/dist/core/api-client.js.map +1 -1
- package/dist/core/constants.d.ts +6 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +7 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/types/Role.d.ts +25 -0
- package/dist/core/types/Role.d.ts.map +1 -0
- package/dist/core/types/Role.js +3 -0
- package/dist/core/types/Role.js.map +1 -0
- package/dist/core/types/index.d.ts +1 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +1 -0
- package/dist/core/types/index.js.map +1 -1
- package/dist/mcp/bundle.js +97 -95
- package/dist/mcp/tools/get.d.ts.map +1 -1
- package/dist/mcp/tools/get.js +4 -0
- package/dist/mcp/tools/get.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +2 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/list-tools.d.ts.map +1 -1
- package/dist/mcp/tools/list-tools.js +6 -0
- package/dist/mcp/tools/list-tools.js.map +1 -1
- package/dist/mcp/tools/list-tools.test.js +2 -1
- package/dist/mcp/tools/list-tools.test.js.map +1 -1
- package/dist/mcp/tools/list.d.ts.map +1 -1
- package/dist/mcp/tools/list.js +13 -0
- package/dist/mcp/tools/list.js.map +1 -1
- package/dist/mcp/tools/permissions.d.ts +4 -0
- package/dist/mcp/tools/permissions.d.ts.map +1 -0
- package/dist/mcp/tools/permissions.js +241 -0
- package/dist/mcp/tools/permissions.js.map +1 -0
- package/dist/mcp/tools/permissions.test.d.ts +2 -0
- package/dist/mcp/tools/permissions.test.d.ts.map +1 -0
- package/dist/mcp/tools/permissions.test.js +99 -0
- package/dist/mcp/tools/permissions.test.js.map +1 -0
- package/package.json +2 -2
- package/skills/funifier/SKILL.md +1 -0
- package/skills/funifier/references/create-aggregate.md +6 -0
- package/skills/funifier/references/date-handling.md +172 -0
- package/skills/funifier/references/debug.md +2 -0
- package/skills/funifier/references/implement-frontend.md +18 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.test.js","sourceRoot":"","sources":["../../../src/mcp/tools/permissions.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "funifier-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
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",
|
|
@@ -72,4 +72,4 @@
|
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": ">=18"
|
|
74
74
|
}
|
|
75
|
-
}
|
|
75
|
+
}
|
package/skills/funifier/SKILL.md
CHANGED
|
@@ -36,6 +36,7 @@ Then read a result with `funifier_read_doc path=<path>`.
|
|
|
36
36
|
| Create a Funifier trigger — guided workflow from entity/event selection to Groovy code generation | `references/create-trigger.md` |
|
|
37
37
|
| Create a Funifier scheduler — guided workflow from naming and cron expression to Groovy code generation | `references/create-scheduler.md` |
|
|
38
38
|
| Create a Funifier prepared aggregate — guided workflow for building MongoDB aggregate pipelines for reports and dashboards | `references/create-aggregate.md` |
|
|
39
|
+
| Create, edit, or query Date fields safely via REST, funifier_database, triggers, schedulers, aggregate, and prepared aggregate; use whenever a payload or filter contains dates | `references/date-handling.md` |
|
|
39
40
|
| Create a Funifier challenge — missions with action rules and point rewards | `references/create-challenge.md` |
|
|
40
41
|
| Create a Funifier action — define trackable player behaviors with attributes | `references/create-action.md` |
|
|
41
42
|
| Create a Funifier point category — XP, coins, or custom metrics | `references/create-point.md` |
|
|
@@ -74,8 +74,12 @@ If search returns insufficient results, read these directly:
|
|
|
74
74
|
| `point_category` | Tipos de ponto — `_id`, `category`, `shortName` |
|
|
75
75
|
| `catalog_item` | Loja virtual — `_id`, `catalogId`, `name`, `requires` |
|
|
76
76
|
|
|
77
|
+
Se o pipeline filtrar ou criar campos de data, leia também `references/date-handling.md` antes de montar o payload.
|
|
78
|
+
|
|
77
79
|
### Expressões de data Funifier
|
|
78
80
|
|
|
81
|
+
Para regras completas de criação/edição/consulta de datas via REST, triggers, schedulers, aggregate e prepared aggregate, leia `references/date-handling.md`.
|
|
82
|
+
|
|
79
83
|
| Expressão | Significado |
|
|
80
84
|
|---|---|
|
|
81
85
|
| `{"$date": "-0d-"}` | Início do dia atual |
|
|
@@ -84,6 +88,8 @@ If search returns insufficient results, read these directly:
|
|
|
84
88
|
| `{"$date": "-0y-"}` | Início do ano atual |
|
|
85
89
|
| `{"$date": "-1d-"}` | Início do dia anterior |
|
|
86
90
|
|
|
91
|
+
**Importante:** em aggregate direto e prepared aggregate, prefira expressões relativas Funifier dentro de `$date` (`-0M-`, `-0M+`) ou timestamps em milissegundos para datas absolutas. Para datas absolutas parametrizadas em prepared aggregate, normalize no `script` com `DateUtil.parse(...)` e substitua diretamente em `$gte`/`$lte`.
|
|
92
|
+
|
|
87
93
|
---
|
|
88
94
|
|
|
89
95
|
## Steps
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# funifier-date-handling
|
|
2
|
+
|
|
3
|
+
Create, edit, or query Date fields safely via REST, funifier_database, triggers, schedulers, aggregate, and prepared aggregate; use whenever a payload or filter contains dates
|
|
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 "date dates bson extended-json aggregate prepared DateUtil strict timestamp timezone"
|
|
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/database-access`
|
|
61
|
+
- `funifier_read_doc path=guides/aggregates`
|
|
62
|
+
- `funifier_read_doc path=modules/database`
|
|
63
|
+
|
|
64
|
+
## Steps
|
|
65
|
+
|
|
66
|
+
## Regra de ouro
|
|
67
|
+
|
|
68
|
+
Use **BSON Extended JSON** para persistir datas em objetos customizados:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"startsAt": { "$date": "2026-05-28T13:30:00.000Z" },
|
|
73
|
+
"created": { "$date": "2026-05-28T13:30:00.000Z" }
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Evite salvar data como string ISO solta quando o campo será filtrado como data. String não compara corretamente com BSON Date em consultas Mongo.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Criar/editar datas via REST ou funifier_database
|
|
82
|
+
|
|
83
|
+
- Gere datas em UTC (`toISOString()` no JavaScript).
|
|
84
|
+
- Ao criar/editar documentos, envie campos de data como `{ "$date": "<ISO UTC>" }`.
|
|
85
|
+
- Em updates via `PUT /v3/database/<collection>`, reenvie o documento completo: o endpoint faz **full replace**.
|
|
86
|
+
- Use `strict=true` ao ler quando precisar confirmar tipos BSON preservados na resposta.
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"_id": "cycle_2026_05",
|
|
91
|
+
"name": "Ciclo Maio",
|
|
92
|
+
"startsAt": { "$date": "2026-05-01T00:00:00.000Z" },
|
|
93
|
+
"endsAt": { "$date": "2026-05-31T23:59:59.999Z" }
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Não salve assim se o campo será filtrado como data:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{ "startsAt": "2026-05-01T00:00:00.000Z" }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Triggers e schedulers
|
|
106
|
+
|
|
107
|
+
Scripts Groovy de triggers, schedulers e prepared aggregates já importam `DateUtil` e `JsonUtil` nos runners. Se o script precisa calcular/comparar datas, normalize explicitamente com `DateUtil.parse(...)`, `new Date()` ou `DateUtil.fromKeyword(...)`.
|
|
108
|
+
|
|
109
|
+
```groovy
|
|
110
|
+
void trigger(event, entity, player, database) {
|
|
111
|
+
entity.createdAt = new Date()
|
|
112
|
+
entity.startsAt = DateUtil.parse('2026-05-01T00:00:00.000Z')
|
|
113
|
+
entity.endsAt = DateUtil.fromKeyword('+7d+')
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Aggregate direto
|
|
120
|
+
|
|
121
|
+
Prefira períodos relativos com `$date`, que passam pelo `FunifierMarshaller` e são convertidos por `DateUtil.fromKeyword`:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
[
|
|
125
|
+
{
|
|
126
|
+
"$match": {
|
|
127
|
+
"time": {
|
|
128
|
+
"$gte": { "$date": "-0M-" },
|
|
129
|
+
"$lte": { "$date": "-0M+" }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Não generalize para `q` de GET/list/count/delete: esses caminhos montam a query string diretamente.
|
|
137
|
+
|
|
138
|
+
Para data absoluta em aggregate direto, prefira timestamp em milissegundos dentro de `$date` ou teste o formato na instância antes de documentar como padrão.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Prepared aggregate (`/v3/find/<id>`)
|
|
143
|
+
|
|
144
|
+
Regras extras:
|
|
145
|
+
|
|
146
|
+
1. O campo `aggregate` salvo no recurso é uma **string JSON serializada**, não array nativo.
|
|
147
|
+
2. Parâmetros só são substituídos quando aparecem como string literal `"$param:nome"`.
|
|
148
|
+
|
|
149
|
+
Para datas relativas, use parâmetros dentro de `$date` (`"$date":"$param:start"`) e preencha `params.start` com keywords como `-0M-`.
|
|
150
|
+
|
|
151
|
+
Para datas absolutas, normalize no `script` para `Date` e substitua diretamente em `$gte`/`$lte`:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"aggregate": "[{"$match":{"soldAt":{"$gte":"$param:start","$lte":"$param:end"}}}]",
|
|
156
|
+
"script": "void prepare(aggregations, params) {\n Date start = params.startIso ? DateUtil.parse(params.startIso) : DateUtil.fromKeyword('-0M-')\n Date end = params.endIso ? DateUtil.parse(params.endIso) : DateUtil.fromKeyword('-0M+')\n if (start == null || end == null) throw new IllegalArgumentException('Invalid date params')\n params.put('start', start)\n params.put('end', end)\n}\n"
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Não coloque o parâmetro convertido para `Date` dentro de `{ "$date": "$param:start" }`.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Checklist
|
|
165
|
+
|
|
166
|
+
- [ ] Salvar Date como `{ "$date": "<ISO UTC>" }`, nunca string solta.
|
|
167
|
+
- [ ] Preservar todos os campos em `PUT`.
|
|
168
|
+
- [ ] Usar keywords Funifier (`-0d-`, `-0M-`, `-0M+`, `+1d+`) apenas em caminhos que passam pelo `FunifierMarshaller`.
|
|
169
|
+
- [ ] Em prepared aggregate, salvar `aggregate` como string JSON serializada.
|
|
170
|
+
- [ ] Em prepared aggregate, usar `"$param:nome"` exatamente como string.
|
|
171
|
+
- [ ] Para data absoluta em prepared aggregate, converter no `script` com `DateUtil.parse`, validar `null`, e substituir o `Date` diretamente em `$gte`/`$lte`.
|
|
172
|
+
- [ ] Testar aggregate direto antes de salvar como prepared aggregate.
|
|
@@ -47,6 +47,8 @@ If search returns insufficient results, read these directly:
|
|
|
47
47
|
| Challenge não avança | Action não existe ou operator/total errado | `funifier_list type=action search=<id>` |
|
|
48
48
|
| Compra falha sem erro | Saldo insuficiente ou `requires` errado | Checar ponto do jogador: `GET /v3/player/<id>/status` |
|
|
49
49
|
| `/v3/database` retorna vazio | Scope `database` ausente na role | Adicionar `database` ao scope via Security |
|
|
50
|
+
| Filtro por data não encontra registros | Campo foi salvo como string ISO ou parâmetro ISO foi usado dentro de `$date` sem normalização | Salvar como `{ "$date": "<ISO UTC>" }`; em prepared aggregate converter ISO com `DateUtil.parse` no script |
|
|
51
|
+
| Prepared aggregate com data absoluta falha/retorna vazio | `"$param:start"` dentro de `{ "$date": ... }` recebeu string ISO | Converter no `script` para `Date` e usar `"$gte":"$param:start"` diretamente |
|
|
50
52
|
|
|
51
53
|
---
|
|
52
54
|
|
|
@@ -34,6 +34,7 @@ If search returns insufficient results, read these directly:
|
|
|
34
34
|
- **Senha do player no banco deve ser BCrypt** (`$2a$...`) — texto plano causa `"Invalid salt version"`
|
|
35
35
|
- **Scope `database`** é obrigatório na role para usar `/v3/database` — sem ele escrita retorna 201 mas não persiste
|
|
36
36
|
- **Header `Range: items=0-1000`** para listas sem paginação explícita
|
|
37
|
+
- **Datas em objetos de negócio:** enviar como `{ "$date": new Date(value).toISOString() }`, não string solta, quando o campo será consultado como data.
|
|
37
38
|
|
|
38
39
|
### Auth flow
|
|
39
40
|
|
|
@@ -72,6 +73,7 @@ const basicToken = 'Basic ' + btoa('API_KEY:APP_SECRET');
|
|
|
72
73
|
- `funifier_read_doc path=modules/auth`
|
|
73
74
|
- `funifier_read_doc path=modules/patterns`
|
|
74
75
|
- `funifier_read_doc path=guides/aggregates` (para relatórios)
|
|
76
|
+
- Se criar, editar ou filtrar datas, leia `references/date-handling.md`.
|
|
75
77
|
|
|
76
78
|
### 2. Implementar autenticação
|
|
77
79
|
|
|
@@ -101,6 +103,22 @@ const report = await fetch('/v3/database/achievement/aggregate', {
|
|
|
101
103
|
});
|
|
102
104
|
```
|
|
103
105
|
|
|
106
|
+
### Datas no frontend
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
const payload = {
|
|
110
|
+
_id: 'cycle_2026_05',
|
|
111
|
+
startsAt: { $date: new Date('2026-05-01T00:00:00.000Z').toISOString() },
|
|
112
|
+
endsAt: { $date: new Date('2026-05-31T23:59:59.999Z').toISOString() }
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
await fetch('/v3/database/cycle__c?strict=true', {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: { ...headers, 'Content-Type': 'application/json' },
|
|
118
|
+
body: JSON.stringify(payload)
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
104
122
|
### 5. Hospedar no Funifier (opcional)
|
|
105
123
|
|
|
106
124
|
Para arquivos estáticos, leia `funifier_read_doc path=modules/static-repo`.
|