funifier-mcp 0.1.0
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/README.md +351 -0
- package/dist/core/api-client.d.ts +131 -0
- package/dist/core/api-client.d.ts.map +1 -0
- package/dist/core/api-client.js +796 -0
- package/dist/core/api-client.js.map +1 -0
- package/dist/core/config.d.ts +11 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +37 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/constants.d.ts +51 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +57 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +26 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types/Action.d.ts +13 -0
- package/dist/core/types/Action.d.ts.map +1 -0
- package/dist/core/types/Action.js +3 -0
- package/dist/core/types/Action.js.map +1 -0
- package/dist/core/types/Aggregate.d.ts +11 -0
- package/dist/core/types/Aggregate.d.ts.map +1 -0
- package/dist/core/types/Aggregate.js +3 -0
- package/dist/core/types/Aggregate.js.map +1 -0
- package/dist/core/types/AiKnowledge.d.ts +10 -0
- package/dist/core/types/AiKnowledge.d.ts.map +1 -0
- package/dist/core/types/AiKnowledge.js +3 -0
- package/dist/core/types/AiKnowledge.js.map +1 -0
- package/dist/core/types/AuthModule.d.ts +12 -0
- package/dist/core/types/AuthModule.d.ts.map +1 -0
- package/dist/core/types/AuthModule.js +3 -0
- package/dist/core/types/AuthModule.js.map +1 -0
- package/dist/core/types/Challenge.d.ts +26 -0
- package/dist/core/types/Challenge.d.ts.map +1 -0
- package/dist/core/types/Challenge.js +3 -0
- package/dist/core/types/Challenge.js.map +1 -0
- package/dist/core/types/ChallengeAggregate.d.ts +13 -0
- package/dist/core/types/ChallengeAggregate.d.ts.map +1 -0
- package/dist/core/types/ChallengeAggregate.js +3 -0
- package/dist/core/types/ChallengeAggregate.js.map +1 -0
- package/dist/core/types/CustomPage.d.ts +15 -0
- package/dist/core/types/CustomPage.d.ts.map +1 -0
- package/dist/core/types/CustomPage.js +3 -0
- package/dist/core/types/CustomPage.js.map +1 -0
- package/dist/core/types/Leaderboard.d.ts +33 -0
- package/dist/core/types/Leaderboard.d.ts.map +1 -0
- package/dist/core/types/Leaderboard.js +3 -0
- package/dist/core/types/Leaderboard.js.map +1 -0
- package/dist/core/types/Level.d.ts +17 -0
- package/dist/core/types/Level.d.ts.map +1 -0
- package/dist/core/types/Level.js +3 -0
- package/dist/core/types/Level.js.map +1 -0
- package/dist/core/types/Point.d.ts +8 -0
- package/dist/core/types/Point.d.ts.map +1 -0
- package/dist/core/types/Point.js +3 -0
- package/dist/core/types/Point.js.map +1 -0
- package/dist/core/types/PublicEndpoint.d.ts +14 -0
- package/dist/core/types/PublicEndpoint.d.ts.map +1 -0
- package/dist/core/types/PublicEndpoint.js +3 -0
- package/dist/core/types/PublicEndpoint.js.map +1 -0
- package/dist/core/types/Quiz.d.ts +33 -0
- package/dist/core/types/Quiz.d.ts.map +1 -0
- package/dist/core/types/Quiz.js +3 -0
- package/dist/core/types/Quiz.js.map +1 -0
- package/dist/core/types/Scheduler.d.ts +15 -0
- package/dist/core/types/Scheduler.d.ts.map +1 -0
- package/dist/core/types/Scheduler.js +3 -0
- package/dist/core/types/Scheduler.js.map +1 -0
- package/dist/core/types/Trigger.d.ts +14 -0
- package/dist/core/types/Trigger.d.ts.map +1 -0
- package/dist/core/types/Trigger.js +3 -0
- package/dist/core/types/Trigger.js.map +1 -0
- package/dist/core/types/VirtualGood.d.ts +21 -0
- package/dist/core/types/VirtualGood.d.ts.map +1 -0
- package/dist/core/types/VirtualGood.js +3 -0
- package/dist/core/types/VirtualGood.js.map +1 -0
- package/dist/core/types/Websocket.d.ts +10 -0
- package/dist/core/types/Websocket.d.ts.map +1 -0
- package/dist/core/types/Websocket.js +3 -0
- package/dist/core/types/Websocket.js.map +1 -0
- package/dist/core/types/Widget.d.ts +15 -0
- package/dist/core/types/Widget.d.ts.map +1 -0
- package/dist/core/types/Widget.js +3 -0
- package/dist/core/types/Widget.js.map +1 -0
- package/dist/core/types/index.d.ts +18 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +34 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/api-holder.d.ts +40 -0
- package/dist/mcp/api-holder.d.ts.map +1 -0
- package/dist/mcp/api-holder.js +72 -0
- package/dist/mcp/api-holder.js.map +1 -0
- package/dist/mcp/bundle.js +99 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +36 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/prompts/templates.d.ts +3 -0
- package/dist/mcp/prompts/templates.d.ts.map +1 -0
- package/dist/mcp/prompts/templates.js +83 -0
- package/dist/mcp/prompts/templates.js.map +1 -0
- package/dist/mcp/resources/documentation.d.ts +3 -0
- package/dist/mcp/resources/documentation.d.ts.map +1 -0
- package/dist/mcp/resources/documentation.js +79 -0
- package/dist/mcp/resources/documentation.js.map +1 -0
- package/dist/mcp/tools/_fetch-current.d.ts +3 -0
- package/dist/mcp/tools/_fetch-current.d.ts.map +1 -0
- package/dist/mcp/tools/_fetch-current.js +67 -0
- package/dist/mcp/tools/_fetch-current.js.map +1 -0
- package/dist/mcp/tools/_merge.d.ts +2 -0
- package/dist/mcp/tools/_merge.d.ts.map +1 -0
- package/dist/mcp/tools/_merge.js +7 -0
- package/dist/mcp/tools/_merge.js.map +1 -0
- package/dist/mcp/tools/connect.d.ts +4 -0
- package/dist/mcp/tools/connect.d.ts.map +1 -0
- package/dist/mcp/tools/connect.js +44 -0
- package/dist/mcp/tools/connect.js.map +1 -0
- package/dist/mcp/tools/database.d.ts +4 -0
- package/dist/mcp/tools/database.d.ts.map +1 -0
- package/dist/mcp/tools/database.js +189 -0
- package/dist/mcp/tools/database.js.map +1 -0
- package/dist/mcp/tools/delete.d.ts +4 -0
- package/dist/mcp/tools/delete.d.ts.map +1 -0
- package/dist/mcp/tools/delete.js +97 -0
- package/dist/mcp/tools/delete.js.map +1 -0
- package/dist/mcp/tools/execute.d.ts +4 -0
- package/dist/mcp/tools/execute.d.ts.map +1 -0
- package/dist/mcp/tools/execute.js +84 -0
- package/dist/mcp/tools/execute.js.map +1 -0
- package/dist/mcp/tools/get.d.ts +4 -0
- package/dist/mcp/tools/get.d.ts.map +1 -0
- package/dist/mcp/tools/get.js +123 -0
- package/dist/mcp/tools/get.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +4 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +22 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/list.d.ts +4 -0
- package/dist/mcp/tools/list.d.ts.map +1 -0
- package/dist/mcp/tools/list.js +261 -0
- package/dist/mcp/tools/list.js.map +1 -0
- package/dist/mcp/tools/logs.d.ts +4 -0
- package/dist/mcp/tools/logs.d.ts.map +1 -0
- package/dist/mcp/tools/logs.js +50 -0
- package/dist/mcp/tools/logs.js.map +1 -0
- package/dist/mcp/tools/save.d.ts +4 -0
- package/dist/mcp/tools/save.d.ts.map +1 -0
- package/dist/mcp/tools/save.js +106 -0
- package/dist/mcp/tools/save.js.map +1 -0
- package/dist/mcp/tools/save.test.d.ts +2 -0
- package/dist/mcp/tools/save.test.d.ts.map +1 -0
- package/dist/mcp/tools/save.test.js +198 -0
- package/dist/mcp/tools/save.test.js.map +1 -0
- package/package.json +65 -0
- package/skills/funifier-create-action/SKILL.md +86 -0
- package/skills/funifier-create-aggregate/SKILL.md +87 -0
- package/skills/funifier-create-challenge/SKILL.md +87 -0
- package/skills/funifier-create-custom-page/SKILL.md +87 -0
- package/skills/funifier-create-leaderboard/SKILL.md +87 -0
- package/skills/funifier-create-level/SKILL.md +86 -0
- package/skills/funifier-create-point/SKILL.md +86 -0
- package/skills/funifier-create-quiz/SKILL.md +86 -0
- package/skills/funifier-create-scheduler/SKILL.md +87 -0
- package/skills/funifier-create-trigger/SKILL.md +88 -0
- package/skills/funifier-create-virtual-good/SKILL.md +86 -0
- package/skills/funifier-debug/SKILL.md +90 -0
- package/skills/funifier-help/SKILL.md +85 -0
- package/skills/funifier-implement-frontend/SKILL.md +89 -0
- package/skills/funifier-index/SKILL.md +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/logs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,QAkDvE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerLogsTool = registerLogsTool;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
function registerLogsTool(server, apiHolder) {
|
|
6
|
+
server.tool("funifier_logs", "Get execution logs for a Funifier resource (trigger or scheduler)", {
|
|
7
|
+
type: zod_1.z
|
|
8
|
+
.enum(["trigger", "scheduler"])
|
|
9
|
+
.describe("The resource type to get logs for"),
|
|
10
|
+
id: zod_1.z.string().describe("The resource ID"),
|
|
11
|
+
}, async ({ type, id }) => {
|
|
12
|
+
try {
|
|
13
|
+
const api = apiHolder.requireClient();
|
|
14
|
+
let logs;
|
|
15
|
+
switch (type) {
|
|
16
|
+
case "trigger":
|
|
17
|
+
logs = await api.getTriggerLogs(id);
|
|
18
|
+
break;
|
|
19
|
+
case "scheduler":
|
|
20
|
+
logs = await api.getSchedulerLogs(id);
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: "text",
|
|
27
|
+
text: `Logs are not supported for type: ${type}. Supported types: trigger, scheduler`,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
isError: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: JSON.stringify(logs, null, 2) }],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: `Error getting logs for ${type} ${id}: ${error.message}`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
isError: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/mcp/tools/logs.ts"],"names":[],"mappings":";;AAIA,4CAkDC;AAtDD,6BAAwB;AAIxB,SAAgB,gBAAgB,CAAC,MAAiB,EAAE,SAAoB;IACtE,MAAM,CAAC,IAAI,CACT,eAAe,EACf,mEAAmE,EACnE;QACE,IAAI,EAAE,OAAC;aACJ,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;aAC9B,QAAQ,CAAC,mCAAmC,CAAC;QAChD,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KAC3C,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC;YACtC,IAAI,IAAS,CAAC;YAEd,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,SAAS;oBACZ,IAAI,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;oBACpC,MAAM;gBACR,KAAK,WAAW;oBACd,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;oBACtC,MAAM;gBACR;oBACE,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,oCAAoC,IAAI,uCAAuC;6BACtF;yBACF;wBACD,OAAO,EAAE,IAAI;qBACd,CAAC;YACN,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,0BAA0B,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE;qBAC/D;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/save.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAoE1C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,QA2CvE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerSaveTool = registerSaveTool;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const _fetch_current_1 = require("./_fetch-current");
|
|
6
|
+
const _merge_1 = require("./_merge");
|
|
7
|
+
const RESOURCE_TYPES = [
|
|
8
|
+
"trigger",
|
|
9
|
+
"scheduler",
|
|
10
|
+
"aggregate",
|
|
11
|
+
"websocket",
|
|
12
|
+
"widget",
|
|
13
|
+
"custom-page",
|
|
14
|
+
"public-endpoint",
|
|
15
|
+
"challenge-aggregate",
|
|
16
|
+
"auth-module",
|
|
17
|
+
"ai-knowledge",
|
|
18
|
+
"action",
|
|
19
|
+
"challenge",
|
|
20
|
+
"point",
|
|
21
|
+
"level",
|
|
22
|
+
"leaderboard",
|
|
23
|
+
"quiz",
|
|
24
|
+
"virtual-good-catalog",
|
|
25
|
+
"virtual-good-item",
|
|
26
|
+
];
|
|
27
|
+
async function dispatchSave(api, type, data) {
|
|
28
|
+
switch (type) {
|
|
29
|
+
case "trigger":
|
|
30
|
+
return await api.saveTrigger(data);
|
|
31
|
+
case "scheduler":
|
|
32
|
+
return await api.saveScheduler(data);
|
|
33
|
+
case "aggregate":
|
|
34
|
+
return await api.saveAggregate(data);
|
|
35
|
+
case "websocket":
|
|
36
|
+
return await api.saveWebsocket(data, !data._id);
|
|
37
|
+
case "widget":
|
|
38
|
+
return await api.saveWidget(data);
|
|
39
|
+
case "custom-page":
|
|
40
|
+
return await api.saveCustomPage(data);
|
|
41
|
+
case "public-endpoint":
|
|
42
|
+
return await api.savePublicEndpoint(data);
|
|
43
|
+
case "challenge-aggregate":
|
|
44
|
+
return await api.saveChallengeAggregate(data);
|
|
45
|
+
case "auth-module":
|
|
46
|
+
return await api.saveAuthModule(data, !data._id);
|
|
47
|
+
case "ai-knowledge":
|
|
48
|
+
return await api.saveAiKnowledge(data);
|
|
49
|
+
case "action":
|
|
50
|
+
return await api.saveAction(data);
|
|
51
|
+
case "challenge":
|
|
52
|
+
return await api.saveChallenge(data);
|
|
53
|
+
case "point":
|
|
54
|
+
return await api.savePoint(data);
|
|
55
|
+
case "level":
|
|
56
|
+
return await api.saveLevel(data);
|
|
57
|
+
case "leaderboard":
|
|
58
|
+
return await api.saveLeaderboard(data);
|
|
59
|
+
case "quiz":
|
|
60
|
+
return await api.saveQuiz(data);
|
|
61
|
+
case "virtual-good-catalog":
|
|
62
|
+
return await api.saveVirtualGoodCatalog(data);
|
|
63
|
+
case "virtual-good-item":
|
|
64
|
+
return await api.saveVirtualGoodItem(data);
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unknown resource type: ${type}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function registerSaveTool(server, apiHolder) {
|
|
70
|
+
server.tool("funifier_save", "Create or update a Funifier resource. On update (when `_id` is present in the payload), the current resource is fetched and any fields missing from the payload are preserved — you only need to send the fields you want to change. To clear a field, send it explicitly as `null`. Array and object fields are replaced wholesale when present in the payload.", {
|
|
71
|
+
type: zod_1.z.enum(RESOURCE_TYPES).describe("The resource type"),
|
|
72
|
+
payload: zod_1.z.string().describe("JSON string of the resource payload. On update, send only the fields you want to change (plus `_id`)."),
|
|
73
|
+
}, async ({ type, payload }) => {
|
|
74
|
+
try {
|
|
75
|
+
const api = apiHolder.requireClient();
|
|
76
|
+
const data = JSON.parse(payload);
|
|
77
|
+
let toSave = data;
|
|
78
|
+
if (data._id) {
|
|
79
|
+
const current = await (0, _fetch_current_1.fetchCurrentById)(api, type, data._id);
|
|
80
|
+
if (!current) {
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: `Cannot update ${type} ${data._id}: resource not found`,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
isError: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
toSave = (0, _merge_1.mergeResource)(current, data);
|
|
92
|
+
}
|
|
93
|
+
const result = await dispatchSave(api, type, toSave);
|
|
94
|
+
return {
|
|
95
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return {
|
|
100
|
+
content: [{ type: "text", text: `Error saving ${type}: ${error.message}` }],
|
|
101
|
+
isError: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.js","sourceRoot":"","sources":["../../../src/mcp/tools/save.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.test.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/save.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const _merge_1 = require("./_merge");
|
|
5
|
+
(0, vitest_1.describe)("mergeResource", () => {
|
|
6
|
+
(0, vitest_1.it)("preserves fields present in current but missing from payload", () => {
|
|
7
|
+
const current = { _id: "a", title: "Old", display: true, html: "<p/>" };
|
|
8
|
+
const payload = { _id: "a", title: "New" };
|
|
9
|
+
(0, vitest_1.expect)((0, _merge_1.mergeResource)(current, payload)).toEqual({
|
|
10
|
+
_id: "a",
|
|
11
|
+
title: "New",
|
|
12
|
+
display: true,
|
|
13
|
+
html: "<p/>",
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.it)("lets payload override with null to unset a field", () => {
|
|
17
|
+
const current = { _id: "a", icon: "star.png", title: "T" };
|
|
18
|
+
const payload = { _id: "a", icon: null };
|
|
19
|
+
(0, vitest_1.expect)((0, _merge_1.mergeResource)(current, payload)).toEqual({
|
|
20
|
+
_id: "a",
|
|
21
|
+
icon: null,
|
|
22
|
+
title: "T",
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)("replaces arrays wholesale when present in payload", () => {
|
|
26
|
+
const current = { _id: "a", rules: [{ id: 1 }, { id: 2 }] };
|
|
27
|
+
const payload = { _id: "a", rules: [{ id: 3 }] };
|
|
28
|
+
(0, vitest_1.expect)((0, _merge_1.mergeResource)(current, payload)).toEqual({
|
|
29
|
+
_id: "a",
|
|
30
|
+
rules: [{ id: 3 }],
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
(0, vitest_1.it)("replaces nested objects wholesale when present in payload", () => {
|
|
34
|
+
const current = { _id: "a", action: { type: "add", value: 10 } };
|
|
35
|
+
const payload = { _id: "a", action: { type: "sub" } };
|
|
36
|
+
(0, vitest_1.expect)((0, _merge_1.mergeResource)(current, payload)).toEqual({
|
|
37
|
+
_id: "a",
|
|
38
|
+
action: { type: "sub" },
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)("carries created and updated over from current", () => {
|
|
42
|
+
const current = { _id: "a", created: 1, updated: 2, title: "T" };
|
|
43
|
+
const payload = { _id: "a", title: "U" };
|
|
44
|
+
const merged = (0, _merge_1.mergeResource)(current, payload);
|
|
45
|
+
(0, vitest_1.expect)(merged.created).toBe(1);
|
|
46
|
+
(0, vitest_1.expect)(merged.updated).toBe(2);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const _fetch_current_1 = require("./_fetch-current");
|
|
50
|
+
function makeFakeApi(overrides = {}) {
|
|
51
|
+
const listed = {
|
|
52
|
+
listCustomPages: [{ _id: "cp1", title: "Page One" }],
|
|
53
|
+
listTriggers: [{ _id: "t1", name: "Trig" }],
|
|
54
|
+
...overrides,
|
|
55
|
+
};
|
|
56
|
+
const api = {};
|
|
57
|
+
for (const key of Object.keys(listed)) {
|
|
58
|
+
api[key] = async () => listed[key];
|
|
59
|
+
}
|
|
60
|
+
return api;
|
|
61
|
+
}
|
|
62
|
+
(0, vitest_1.describe)("fetchCurrentById", () => {
|
|
63
|
+
(0, vitest_1.it)("finds a custom-page by _id", async () => {
|
|
64
|
+
const api = makeFakeApi();
|
|
65
|
+
const result = await (0, _fetch_current_1.fetchCurrentById)(api, "custom-page", "cp1");
|
|
66
|
+
(0, vitest_1.expect)(result).toEqual({ _id: "cp1", title: "Page One" });
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.it)("finds a trigger by _id", async () => {
|
|
69
|
+
const api = makeFakeApi();
|
|
70
|
+
const result = await (0, _fetch_current_1.fetchCurrentById)(api, "trigger", "t1");
|
|
71
|
+
(0, vitest_1.expect)(result).toEqual({ _id: "t1", name: "Trig" });
|
|
72
|
+
});
|
|
73
|
+
(0, vitest_1.it)("returns null when the resource is not found", async () => {
|
|
74
|
+
const api = makeFakeApi();
|
|
75
|
+
const result = await (0, _fetch_current_1.fetchCurrentById)(api, "custom-page", "missing");
|
|
76
|
+
(0, vitest_1.expect)(result).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.it)("returns null when the list is empty", async () => {
|
|
79
|
+
const api = makeFakeApi({ listCustomPages: [] });
|
|
80
|
+
const result = await (0, _fetch_current_1.fetchCurrentById)(api, "custom-page", "cp1");
|
|
81
|
+
(0, vitest_1.expect)(result).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
(0, vitest_1.it)("throws on unknown resource type", async () => {
|
|
84
|
+
const api = makeFakeApi();
|
|
85
|
+
await (0, vitest_1.expect)((0, _fetch_current_1.fetchCurrentById)(api, "nonsense", "x")).rejects.toThrow(/unknown resource type/i);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const save_1 = require("./save");
|
|
89
|
+
function makeHarness(fakeApi) {
|
|
90
|
+
const handlers = {};
|
|
91
|
+
const server = {
|
|
92
|
+
tool: (name, _desc, _schema, handler) => {
|
|
93
|
+
handlers[name] = handler;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const apiHolder = { requireClient: () => fakeApi };
|
|
97
|
+
(0, save_1.registerSaveTool)(server, apiHolder);
|
|
98
|
+
return async (type, payload) => handlers["funifier_save"]({ type, payload: JSON.stringify(payload) });
|
|
99
|
+
}
|
|
100
|
+
(0, vitest_1.describe)("funifier_save auto-merge", () => {
|
|
101
|
+
(0, vitest_1.it)("create path: no _id, dispatches payload unchanged and does not list", async () => {
|
|
102
|
+
const calls = [];
|
|
103
|
+
const fakeApi = {
|
|
104
|
+
listCustomPages: async () => {
|
|
105
|
+
calls.push("list");
|
|
106
|
+
return [];
|
|
107
|
+
},
|
|
108
|
+
saveCustomPage: async (data) => {
|
|
109
|
+
calls.push("save");
|
|
110
|
+
return data;
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
const invoke = makeHarness(fakeApi);
|
|
114
|
+
const payload = { title: "New", slug: "n", html: "", script: "", folder: "", display: true };
|
|
115
|
+
const result = await invoke("custom-page", payload);
|
|
116
|
+
(0, vitest_1.expect)(calls).toEqual(["save"]);
|
|
117
|
+
(0, vitest_1.expect)(result.isError).toBeUndefined();
|
|
118
|
+
const saved = JSON.parse(result.content[0].text);
|
|
119
|
+
(0, vitest_1.expect)(saved).toEqual(payload);
|
|
120
|
+
});
|
|
121
|
+
(0, vitest_1.it)("update path: partial payload merges with current before saving", async () => {
|
|
122
|
+
const current = {
|
|
123
|
+
_id: "cp1",
|
|
124
|
+
title: "Old",
|
|
125
|
+
slug: "old-slug",
|
|
126
|
+
html: "<big-html/>",
|
|
127
|
+
script: "console.log(1)",
|
|
128
|
+
folder: "root",
|
|
129
|
+
display: true,
|
|
130
|
+
};
|
|
131
|
+
let savedArg = null;
|
|
132
|
+
const fakeApi = {
|
|
133
|
+
listCustomPages: async () => [current],
|
|
134
|
+
saveCustomPage: async (data) => {
|
|
135
|
+
savedArg = data;
|
|
136
|
+
return data;
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const invoke = makeHarness(fakeApi);
|
|
140
|
+
const result = await invoke("custom-page", { _id: "cp1", title: "New" });
|
|
141
|
+
(0, vitest_1.expect)(result.isError).toBeUndefined();
|
|
142
|
+
(0, vitest_1.expect)(savedArg).toEqual({
|
|
143
|
+
_id: "cp1",
|
|
144
|
+
title: "New",
|
|
145
|
+
slug: "old-slug",
|
|
146
|
+
html: "<big-html/>",
|
|
147
|
+
script: "console.log(1)",
|
|
148
|
+
folder: "root",
|
|
149
|
+
display: true,
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
(0, vitest_1.it)("update path: explicit null in payload clears the field", async () => {
|
|
153
|
+
const current = { _id: "cp1", title: "T", icon: "old.png" };
|
|
154
|
+
let savedArg = null;
|
|
155
|
+
const fakeApi = {
|
|
156
|
+
listCustomPages: async () => [current],
|
|
157
|
+
saveCustomPage: async (data) => {
|
|
158
|
+
savedArg = data;
|
|
159
|
+
return data;
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
const invoke = makeHarness(fakeApi);
|
|
163
|
+
await invoke("custom-page", { _id: "cp1", icon: null });
|
|
164
|
+
(0, vitest_1.expect)(savedArg.icon).toBeNull();
|
|
165
|
+
(0, vitest_1.expect)(savedArg.title).toBe("T");
|
|
166
|
+
});
|
|
167
|
+
(0, vitest_1.it)("update path: _id not found returns isError and does not save", async () => {
|
|
168
|
+
let saveCalled = false;
|
|
169
|
+
const fakeApi = {
|
|
170
|
+
listCustomPages: async () => [{ _id: "other", title: "x" }],
|
|
171
|
+
saveCustomPage: async () => {
|
|
172
|
+
saveCalled = true;
|
|
173
|
+
return {};
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
const invoke = makeHarness(fakeApi);
|
|
177
|
+
const result = await invoke("custom-page", { _id: "cp1", title: "New" });
|
|
178
|
+
(0, vitest_1.expect)(result.isError).toBe(true);
|
|
179
|
+
(0, vitest_1.expect)(result.content[0].text).toMatch(/not found/i);
|
|
180
|
+
(0, vitest_1.expect)(saveCalled).toBe(false);
|
|
181
|
+
});
|
|
182
|
+
(0, vitest_1.it)("update path: nested array is replaced wholesale", async () => {
|
|
183
|
+
const current = { _id: "ch1", name: "C", rules: [{ id: "a" }, { id: "b" }] };
|
|
184
|
+
let savedArg = null;
|
|
185
|
+
const fakeApi = {
|
|
186
|
+
listChallenges: async () => [current],
|
|
187
|
+
saveChallenge: async (data) => {
|
|
188
|
+
savedArg = data;
|
|
189
|
+
return data;
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
const invoke = makeHarness(fakeApi);
|
|
193
|
+
await invoke("challenge", { _id: "ch1", rules: [{ id: "c" }] });
|
|
194
|
+
(0, vitest_1.expect)(savedArg.rules).toEqual([{ id: "c" }]);
|
|
195
|
+
(0, vitest_1.expect)(savedArg.name).toBe("C");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
//# sourceMappingURL=save.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.test.js","sourceRoot":"","sources":["../../../src/mcp/tools/save.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,qCAAyC;AAEzC,IAAA,iBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAA,WAAE,EAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACxE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC3C,IAAA,eAAM,EAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACzC,IAAA,eAAM,EAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACjD,IAAA,eAAM,EAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;QACjE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtD,IAAA,eAAM,EAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,GAAG,EAAE,GAAG;YACR,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;SACxB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACjE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAA,sBAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,qDAAoD;AAEpD,SAAS,WAAW,CAAC,YAAiC,EAAE;IACtD,MAAM,MAAM,GAA0B;QACpC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACpD,YAAY,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC3C,GAAG,SAAS;KACb,CAAC;IACF,MAAM,GAAG,GAAQ,EAAE,CAAC;IACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,IAAA,iBAAQ,EAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAA,WAAE,EAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAgB,EAAC,GAAG,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QACjE,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAgB,EAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAgB,EAAC,GAAG,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;QACrE,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAgB,EAAC,GAAG,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QACjE,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,IAAA,eAAM,EACV,IAAA,iCAAgB,EAAC,GAAG,EAAE,UAAiB,EAAE,GAAG,CAAC,CAC9C,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAGH,iCAA0C;AAE1C,SAAS,WAAW,CAAC,OAAY;IAC/B,MAAM,QAAQ,GAA6B,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,OAAY,EAAE,OAAiB,EAAE,EAAE;YACrE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QAC3B,CAAC;KACsB,CAAC;IAC1B,MAAM,SAAS,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,EAAS,CAAC;IAC1D,IAAA,uBAAgB,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,OAAO,KAAK,EAAE,IAAY,EAAE,OAAY,EAAE,EAAE,CAC1C,QAAQ,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,IAAA,iBAAQ,EAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,IAAA,WAAE,EAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG;YACd,eAAe,EAAE,KAAK,IAAI,EAAE;gBAC1B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,cAAc,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;gBAClC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7F,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACpD,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAChC,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjD,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,OAAO,GAAG;YACd,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,IAAI;SACd,CAAC;QACF,IAAI,QAAQ,GAAQ,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG;YACd,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC;YACtC,cAAc,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;gBAClC,QAAQ,GAAG,IAAI,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC5D,IAAI,QAAQ,GAAQ,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG;YACd,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC;YACtC,cAAc,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;gBAClC,QAAQ,GAAG,IAAI,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,IAAA,eAAM,EAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAA,eAAM,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,OAAO,GAAG;YACd,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YAC3D,cAAc,EAAE,KAAK,IAAI,EAAE;gBACzB,UAAU,GAAG,IAAI,CAAC;gBAClB,OAAO,EAAE,CAAC;YACZ,CAAC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACrD,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAC7E,IAAI,QAAQ,GAAQ,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG;YACd,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC;YACrC,aAAa,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;gBACjC,QAAQ,GAAG,IAAI,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,IAAA,eAAM,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC9C,IAAA,eAAM,EAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "funifier-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Funifier AI toolkit — MCP server, API client, and Claude Code skills for the Funifier gamification platform",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"funifier-mcp": "dist/mcp/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"skills",
|
|
13
|
+
"doc",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/funifierinc/funifier-mcp.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/funifierinc/funifier-mcp/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/funifierinc/funifier-mcp#readme",
|
|
25
|
+
"author": "Funifier",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"bundle": "npm run build && esbuild dist/mcp/index.js --bundle --outfile=dist/mcp/bundle.js --format=cjs --platform=node --minify",
|
|
32
|
+
"dev": "tsc --watch",
|
|
33
|
+
"prepublishOnly": "npm run bundle",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest watch",
|
|
36
|
+
"build:skills": "tsx scripts/build-skills.ts",
|
|
37
|
+
"build:skills:force": "tsx scripts/build-skills.ts --force",
|
|
38
|
+
"search:docs": "tsx scripts/search-docs.ts"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"funifier",
|
|
42
|
+
"gamification",
|
|
43
|
+
"mcp",
|
|
44
|
+
"model-context-protocol",
|
|
45
|
+
"claude",
|
|
46
|
+
"ai",
|
|
47
|
+
"api-client"
|
|
48
|
+
],
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
52
|
+
"axios": "^1.6.0",
|
|
53
|
+
"zod": "^3.25.76"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^25.5.0",
|
|
57
|
+
"esbuild": "^0.20.0",
|
|
58
|
+
"tsx": "^4.21.0",
|
|
59
|
+
"typescript": "^5.3.0",
|
|
60
|
+
"vitest": "^1.0.0"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: funifier-create-action
|
|
3
|
+
description: Create a Funifier action — define trackable player behaviors with attributes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# funifier-create-action
|
|
7
|
+
|
|
8
|
+
Create a Funifier action — define trackable player behaviors with attributes
|
|
9
|
+
|
|
10
|
+
## Persona e Qualidade de Código
|
|
11
|
+
|
|
12
|
+
A partir de agora, atue como um **desenvolvedor de software sênior altamente experiente**, especializado em **geração de código limpo, legível e de fácil manutenção**. Suas soluções devem seguir rigorosamente as **boas práticas da indústria**, **padrões de projeto** e **arquiteturas modernas**, sempre **evitando overengineering**.
|
|
13
|
+
|
|
14
|
+
### Ao lidar com qualquer código — seja refatorando ou criando do zero — siga este processo:
|
|
15
|
+
|
|
16
|
+
1. **Analise cuidadosamente o problema ou o código existente.**
|
|
17
|
+
2. **Raciocine passo a passo** antes de escrever qualquer linha de código.
|
|
18
|
+
3. **Identifique problemas (em caso de refatoração) ou requisitos (em caso de código novo).**
|
|
19
|
+
4. **Defina prioridades e estratégias com base em princípios sólidos de engenharia.**
|
|
20
|
+
5. **Justifique tecnicamente cada decisão**, com base em fundamentos como:
|
|
21
|
+
- **SOLID**
|
|
22
|
+
- **DRY (Don't Repeat Yourself)**
|
|
23
|
+
- **KISS (Keep It Simple, Stupid)**
|
|
24
|
+
- **YAGNI (You Aren't Gonna Need It)**
|
|
25
|
+
|
|
26
|
+
Só então prossiga com a implementação.
|
|
27
|
+
|
|
28
|
+
> **Nota:** Os exemplos de código na documentação Funifier são ilustrativos — podem usar nomes de variáveis genéricos ou scripts monolíticos. Sempre melhore-os: use nomes descritivos, extraia métodos especializados para lógicas complexas e mantenha cada função com responsabilidade única.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Before starting — find relevant docs
|
|
33
|
+
|
|
34
|
+
Run lexical search to load only what you need:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx tsx scripts/search-docs.ts "action track player behavior attributes log event" --skill funifier-create-action
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Read only files returned with score > 0.5 (this threshold is printed in the search output).
|
|
41
|
+
|
|
42
|
+
## Primary docs for this skill
|
|
43
|
+
|
|
44
|
+
If search returns insufficient results, read directly:
|
|
45
|
+
|
|
46
|
+
- `datasource-funifier-docs/knowledge/modules/action.md`
|
|
47
|
+
- `datasource-funifier-docs/knowledge/modules/action-log.md`
|
|
48
|
+
|
|
49
|
+
## Steps
|
|
50
|
+
|
|
51
|
+
### 1. Understand the requirement
|
|
52
|
+
|
|
53
|
+
Ask the user what they want to create or accomplish. Gather:
|
|
54
|
+
- The name/title
|
|
55
|
+
- The purpose and behavior
|
|
56
|
+
- Any specific configuration or constraints
|
|
57
|
+
|
|
58
|
+
### 2. Search for relevant documentation
|
|
59
|
+
|
|
60
|
+
Run the lexical search (command shown above) and read the returned files.
|
|
61
|
+
|
|
62
|
+
### 3. Check existing resources (if MCP available)
|
|
63
|
+
|
|
64
|
+
Use `funifier_list` with the relevant type and a `search` parameter to see
|
|
65
|
+
if a similar resource already exists. Never list all resources without a search term.
|
|
66
|
+
|
|
67
|
+
### 4. Design and confirm
|
|
68
|
+
|
|
69
|
+
Based on the docs, outline the configuration to the user and confirm before saving.
|
|
70
|
+
|
|
71
|
+
### 5. Create or update
|
|
72
|
+
|
|
73
|
+
Use `funifier_save` with the appropriate type and a JSON payload to create or
|
|
74
|
+
update the resource. If MCP is unavailable, show the complete JSON for manual use.
|
|
75
|
+
|
|
76
|
+
### 6. Validate
|
|
77
|
+
|
|
78
|
+
Use `funifier_logs` (for triggers/schedulers) or `funifier_get` to confirm
|
|
79
|
+
the resource was saved correctly and executed without errors.
|
|
80
|
+
|
|
81
|
+
## MCP
|
|
82
|
+
|
|
83
|
+
If Funifier MCP tools are available (`funifier_list`, `funifier_save`, `funifier_get`, `funifier_logs`):
|
|
84
|
+
- Use MCP for live server data
|
|
85
|
+
- Use docs for correct patterns and syntax
|
|
86
|
+
- Never learn patterns from existing live resources — docs are authoritative
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: funifier-create-aggregate
|
|
3
|
+
description: Create a Funifier prepared aggregate — guided workflow for building MongoDB aggregate pipelines for reports and dashboards
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# funifier-create-aggregate
|
|
7
|
+
|
|
8
|
+
Create a Funifier prepared aggregate — guided workflow for building MongoDB aggregate pipelines for reports and dashboards
|
|
9
|
+
|
|
10
|
+
## Persona e Qualidade de Código
|
|
11
|
+
|
|
12
|
+
A partir de agora, atue como um **desenvolvedor de software sênior altamente experiente**, especializado em **geração de código limpo, legível e de fácil manutenção**. Suas soluções devem seguir rigorosamente as **boas práticas da indústria**, **padrões de projeto** e **arquiteturas modernas**, sempre **evitando overengineering**.
|
|
13
|
+
|
|
14
|
+
### Ao lidar com qualquer código — seja refatorando ou criando do zero — siga este processo:
|
|
15
|
+
|
|
16
|
+
1. **Analise cuidadosamente o problema ou o código existente.**
|
|
17
|
+
2. **Raciocine passo a passo** antes de escrever qualquer linha de código.
|
|
18
|
+
3. **Identifique problemas (em caso de refatoração) ou requisitos (em caso de código novo).**
|
|
19
|
+
4. **Defina prioridades e estratégias com base em princípios sólidos de engenharia.**
|
|
20
|
+
5. **Justifique tecnicamente cada decisão**, com base em fundamentos como:
|
|
21
|
+
- **SOLID**
|
|
22
|
+
- **DRY (Don't Repeat Yourself)**
|
|
23
|
+
- **KISS (Keep It Simple, Stupid)**
|
|
24
|
+
- **YAGNI (You Aren't Gonna Need It)**
|
|
25
|
+
|
|
26
|
+
Só então prossiga com a implementação.
|
|
27
|
+
|
|
28
|
+
> **Nota:** Os exemplos de código na documentação Funifier são ilustrativos — podem usar nomes de variáveis genéricos ou scripts monolíticos. Sempre melhore-os: use nomes descritivos, extraia métodos especializados para lógicas complexas e mantenha cada função com responsabilidade única.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Before starting — find relevant docs
|
|
33
|
+
|
|
34
|
+
Run lexical search to load only what you need:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx tsx scripts/search-docs.ts "aggregate mongodb pipeline report dashboard query prepared" --skill funifier-create-aggregate
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Read only files returned with score > 0.5 (this threshold is printed in the search output).
|
|
41
|
+
|
|
42
|
+
## Primary docs for this skill
|
|
43
|
+
|
|
44
|
+
If search returns insufficient results, read directly:
|
|
45
|
+
|
|
46
|
+
- `datasource-funifier-docs/knowledge/guides/aggregates.md`
|
|
47
|
+
- `datasource-funifier-docs/knowledge/guides/database-access.md`
|
|
48
|
+
- `datasource-funifier-docs/knowledge/modules/database.md`
|
|
49
|
+
|
|
50
|
+
## Steps
|
|
51
|
+
|
|
52
|
+
### 1. Understand the requirement
|
|
53
|
+
|
|
54
|
+
Ask the user what they want to create or accomplish. Gather:
|
|
55
|
+
- The name/title
|
|
56
|
+
- The purpose and behavior
|
|
57
|
+
- Any specific configuration or constraints
|
|
58
|
+
|
|
59
|
+
### 2. Search for relevant documentation
|
|
60
|
+
|
|
61
|
+
Run the lexical search (command shown above) and read the returned files.
|
|
62
|
+
|
|
63
|
+
### 3. Check existing resources (if MCP available)
|
|
64
|
+
|
|
65
|
+
Use `funifier_list` with the relevant type and a `search` parameter to see
|
|
66
|
+
if a similar resource already exists. Never list all resources without a search term.
|
|
67
|
+
|
|
68
|
+
### 4. Design and confirm
|
|
69
|
+
|
|
70
|
+
Based on the docs, outline the configuration to the user and confirm before saving.
|
|
71
|
+
|
|
72
|
+
### 5. Create or update
|
|
73
|
+
|
|
74
|
+
Use `funifier_save` with the appropriate type and a JSON payload to create or
|
|
75
|
+
update the resource. If MCP is unavailable, show the complete JSON for manual use.
|
|
76
|
+
|
|
77
|
+
### 6. Validate
|
|
78
|
+
|
|
79
|
+
Use `funifier_logs` (for triggers/schedulers) or `funifier_get` to confirm
|
|
80
|
+
the resource was saved correctly and executed without errors.
|
|
81
|
+
|
|
82
|
+
## MCP
|
|
83
|
+
|
|
84
|
+
If Funifier MCP tools are available (`funifier_list`, `funifier_save`, `funifier_get`, `funifier_logs`):
|
|
85
|
+
- Use MCP for live server data
|
|
86
|
+
- Use docs for correct patterns and syntax
|
|
87
|
+
- Never learn patterns from existing live resources — docs are authoritative
|