@open-loyalty/mcp-server 1.7.0 → 1.12.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/dist/instructions.d.ts +1 -1
- package/dist/instructions.js +58 -22
- package/dist/server.js +3 -0
- package/dist/tools/apps/campaign-builder/handlers.d.ts +25 -0
- package/dist/tools/apps/campaign-builder/handlers.js +47 -0
- package/dist/tools/apps/campaign-builder/tool.d.ts +2 -0
- package/dist/tools/apps/campaign-builder/tool.js +36 -0
- package/dist/tools/apps/dashboard/handlers.d.ts +13 -0
- package/dist/tools/apps/dashboard/handlers.js +23 -0
- package/dist/tools/apps/dashboard/tool.d.ts +2 -0
- package/dist/tools/apps/dashboard/tool.js +48 -0
- package/dist/tools/apps/index.d.ts +6 -0
- package/dist/tools/apps/index.js +18 -0
- package/dist/tools/apps/member-profile/handlers.d.ts +49 -0
- package/dist/tools/apps/member-profile/handlers.js +48 -0
- package/dist/tools/apps/member-profile/tool.d.ts +2 -0
- package/dist/tools/apps/member-profile/tool.js +37 -0
- package/dist/tools/apps/rewards-catalog/handlers.d.ts +29 -0
- package/dist/tools/apps/rewards-catalog/handlers.js +25 -0
- package/dist/tools/apps/rewards-catalog/tool.d.ts +2 -0
- package/dist/tools/apps/rewards-catalog/tool.js +40 -0
- package/dist/tools/apps/tier-visualizer/handlers.d.ts +27 -0
- package/dist/tools/apps/tier-visualizer/handlers.js +60 -0
- package/dist/tools/apps/tier-visualizer/tool.d.ts +2 -0
- package/dist/tools/apps/tier-visualizer/tool.js +39 -0
- package/dist/tools/apps/transaction-timeline/handlers.d.ts +27 -0
- package/dist/tools/apps/transaction-timeline/handlers.js +64 -0
- package/dist/tools/apps/transaction-timeline/tool.d.ts +2 -0
- package/dist/tools/apps/transaction-timeline/tool.js +37 -0
- package/dist/tools/campaign/index.d.ts +16 -3
- package/dist/tools/campaign/index.js +15 -4
- package/dist/tools/campaign/member-handlers.d.ts +12 -0
- package/dist/tools/campaign/member-handlers.js +33 -0
- package/dist/tools/campaign/schemas.d.ts +6 -0
- package/dist/tools/campaign/schemas.js +6 -0
- package/dist/tools/channel/handlers.d.ts +32 -0
- package/dist/tools/channel/handlers.js +130 -0
- package/dist/tools/channel/index.d.ts +68 -0
- package/dist/tools/channel/index.js +59 -0
- package/dist/tools/channel/schemas.d.ts +29 -0
- package/dist/tools/channel/schemas.js +30 -0
- package/dist/tools/context/handlers.d.ts +49 -0
- package/dist/tools/context/handlers.js +131 -0
- package/dist/tools/context/index.d.ts +15 -0
- package/dist/tools/context/index.js +20 -0
- package/dist/tools/context/schemas.d.ts +7 -0
- package/dist/tools/context/schemas.js +4 -0
- package/dist/tools/group-of-values/handlers.d.ts +39 -0
- package/dist/tools/group-of-values/handlers.js +133 -0
- package/dist/tools/group-of-values/index.d.ts +82 -0
- package/dist/tools/group-of-values/index.js +72 -0
- package/dist/tools/group-of-values/schemas.d.ts +36 -0
- package/dist/tools/group-of-values/schemas.js +39 -0
- package/dist/tools/index.js +12 -0
- package/dist/tools/language/handlers.d.ts +24 -0
- package/dist/tools/language/handlers.js +127 -0
- package/dist/tools/language/index.d.ts +64 -0
- package/dist/tools/language/index.js +60 -0
- package/dist/tools/language/schemas.d.ts +25 -0
- package/dist/tools/language/schemas.js +25 -0
- package/dist/tools/member/handlers.d.ts +4 -0
- package/dist/tools/member/handlers.js +27 -0
- package/dist/tools/member/index.d.ts +14 -2
- package/dist/tools/member/index.js +15 -2
- package/dist/tools/points/fraud-handlers.d.ts +21 -0
- package/dist/tools/points/fraud-handlers.js +96 -0
- package/dist/tools/points/index.d.ts +50 -1
- package/dist/tools/points/index.js +45 -2
- package/dist/tools/points/schemas.d.ts +11 -0
- package/dist/tools/points/schemas.js +11 -0
- package/dist/tools/reward/category-handlers.d.ts +27 -0
- package/dist/tools/reward/category-handlers.js +70 -0
- package/dist/tools/reward/handlers.d.ts +0 -12
- package/dist/tools/reward/handlers.js +0 -28
- package/dist/tools/reward/index.d.ts +76 -3
- package/dist/tools/reward/index.js +63 -4
- package/dist/tools/reward/photo-handlers.d.ts +10 -0
- package/dist/tools/reward/photo-handlers.js +97 -0
- package/dist/tools/reward/redemption-handlers.d.ts +23 -0
- package/dist/tools/reward/redemption-handlers.js +50 -0
- package/dist/tools/reward/schemas.d.ts +31 -0
- package/dist/tools/reward/schemas.js +33 -0
- package/dist/tools/segment/handlers.js +14 -10
- package/dist/tools/segment/index.js +1 -1
- package/dist/tools/segment/schemas.js +3 -3
- package/dist/tools/store/handlers.d.ts +24 -0
- package/dist/tools/store/handlers.js +29 -1
- package/dist/tools/store/index.d.ts +41 -3
- package/dist/tools/store/index.js +27 -4
- package/dist/tools/store/schemas.d.ts +24 -0
- package/dist/tools/store/schemas.js +24 -0
- package/dist/ui/campaign-builder.html +648 -0
- package/dist/ui/dashboard.html +299 -0
- package/dist/ui/member-profile.html +592 -0
- package/dist/ui/rewards-catalog.html +274 -0
- package/dist/ui/tier-visualizer.html +393 -0
- package/dist/ui/transaction-timeline.html +360 -0
- package/package.json +7 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "../../client/http.js";
|
|
2
|
+
import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
import { getStoreCode } from "../../config.js";
|
|
5
|
+
export async function channelList(input) {
|
|
6
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
if (input.page)
|
|
9
|
+
params.append("_page", String(input.page));
|
|
10
|
+
if (input.perPage)
|
|
11
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
12
|
+
if (input.name)
|
|
13
|
+
params.append("name", input.name);
|
|
14
|
+
if (input.identifier)
|
|
15
|
+
params.append("identifier", input.identifier);
|
|
16
|
+
const queryString = params.toString();
|
|
17
|
+
const url = `/${storeCode}/channel${queryString ? `?${queryString}` : ""}`;
|
|
18
|
+
try {
|
|
19
|
+
const response = await apiGet(url);
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw formatApiError(error, "ol_channel_list");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function channelCreate(input) {
|
|
27
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
28
|
+
const payload = {
|
|
29
|
+
name: input.name,
|
|
30
|
+
identifier: input.identifier,
|
|
31
|
+
};
|
|
32
|
+
if (input.description)
|
|
33
|
+
payload.description = input.description;
|
|
34
|
+
try {
|
|
35
|
+
const response = await apiPost(`/${storeCode}/channel`, { channel: payload });
|
|
36
|
+
return response;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (axios.isAxiosError(error) && error.response?.status === 400) {
|
|
40
|
+
const allMessages = [
|
|
41
|
+
error.response?.data?.message || "",
|
|
42
|
+
...(error.response?.data?.errors || []).map((e) => e.message),
|
|
43
|
+
].join(" ").toLowerCase();
|
|
44
|
+
if (allMessages.includes("identifier") && (allMessages.includes("unique") || allMessages.includes("exists") || allMessages.includes("already"))) {
|
|
45
|
+
throw new OpenLoyaltyError({
|
|
46
|
+
code: "DUPLICATE_IDENTIFIER",
|
|
47
|
+
message: `Channel with identifier '${input.identifier}' already exists`,
|
|
48
|
+
hint: `Use ol_channel_list() to find the existing channel, or choose a different identifier.`,
|
|
49
|
+
relatedTool: "ol_channel_create",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
throw formatApiError(error, "ol_channel_create");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function channelGet(input) {
|
|
57
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
58
|
+
try {
|
|
59
|
+
const response = await apiGet(`/${storeCode}/channel/${input.channelId}`);
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
64
|
+
throw new OpenLoyaltyError({
|
|
65
|
+
code: "NOT_FOUND",
|
|
66
|
+
message: `Channel '${input.channelId}' not found`,
|
|
67
|
+
hint: "Use ol_channel_list() to find existing channels and their IDs.",
|
|
68
|
+
relatedTool: "ol_channel_get",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
throw formatApiError(error, "ol_channel_get");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export async function channelUpdate(input) {
|
|
75
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
76
|
+
const payload = {
|
|
77
|
+
name: input.name,
|
|
78
|
+
identifier: input.identifier,
|
|
79
|
+
};
|
|
80
|
+
if (input.description !== undefined)
|
|
81
|
+
payload.description = input.description;
|
|
82
|
+
try {
|
|
83
|
+
const response = await apiPut(`/${storeCode}/channel/${input.channelId}`, { channel: payload });
|
|
84
|
+
return response;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (axios.isAxiosError(error)) {
|
|
88
|
+
if (error.response?.status === 404) {
|
|
89
|
+
throw new OpenLoyaltyError({
|
|
90
|
+
code: "NOT_FOUND",
|
|
91
|
+
message: `Channel '${input.channelId}' not found`,
|
|
92
|
+
hint: "Use ol_channel_list() to find existing channels and their IDs.",
|
|
93
|
+
relatedTool: "ol_channel_update",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (error.response?.status === 400) {
|
|
97
|
+
const allMessages = [
|
|
98
|
+
error.response?.data?.message || "",
|
|
99
|
+
...(error.response?.data?.errors || []).map((e) => e.message),
|
|
100
|
+
].join(" ").toLowerCase();
|
|
101
|
+
if (allMessages.includes("identifier") && (allMessages.includes("unique") || allMessages.includes("exists") || allMessages.includes("already"))) {
|
|
102
|
+
throw new OpenLoyaltyError({
|
|
103
|
+
code: "DUPLICATE_IDENTIFIER",
|
|
104
|
+
message: `Channel with identifier '${input.identifier}' already exists`,
|
|
105
|
+
hint: `Use ol_channel_list() to find channels with that identifier, or choose a different identifier.`,
|
|
106
|
+
relatedTool: "ol_channel_update",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw formatApiError(error, "ol_channel_update");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function channelDelete(input) {
|
|
115
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
116
|
+
try {
|
|
117
|
+
await apiDelete(`/${storeCode}/channel/${input.channelId}`);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
121
|
+
throw new OpenLoyaltyError({
|
|
122
|
+
code: "NOT_FOUND",
|
|
123
|
+
message: `Channel '${input.channelId}' not found`,
|
|
124
|
+
hint: "Use ol_channel_list() to find existing channels and their IDs.",
|
|
125
|
+
relatedTool: "ol_channel_delete",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
throw formatApiError(error, "ol_channel_delete");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export { ChannelListInputSchema, ChannelCreateInputSchema, ChannelGetInputSchema, ChannelUpdateInputSchema, ChannelDeleteInputSchema, } from "./schemas.js";
|
|
2
|
+
export { channelList, channelCreate, channelGet, channelUpdate, channelDelete, } from "./handlers.js";
|
|
3
|
+
import { channelList, channelCreate, channelGet, channelUpdate, channelDelete } from "./handlers.js";
|
|
4
|
+
export declare const channelToolDefinitions: readonly [{
|
|
5
|
+
readonly name: "ol_channel_list";
|
|
6
|
+
readonly title: "List Channels";
|
|
7
|
+
readonly description: string;
|
|
8
|
+
readonly readOnly: true;
|
|
9
|
+
readonly idempotent: true;
|
|
10
|
+
readonly inputSchema: {
|
|
11
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
12
|
+
page: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
13
|
+
perPage: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
14
|
+
name: import("zod").ZodOptional<import("zod").ZodString>;
|
|
15
|
+
identifier: import("zod").ZodOptional<import("zod").ZodString>;
|
|
16
|
+
};
|
|
17
|
+
readonly handler: typeof channelList;
|
|
18
|
+
}, {
|
|
19
|
+
readonly name: "ol_channel_create";
|
|
20
|
+
readonly title: "Create Channel";
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly readOnly: false;
|
|
23
|
+
readonly idempotent: false;
|
|
24
|
+
readonly inputSchema: {
|
|
25
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
26
|
+
name: import("zod").ZodString;
|
|
27
|
+
identifier: import("zod").ZodString;
|
|
28
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
29
|
+
};
|
|
30
|
+
readonly handler: typeof channelCreate;
|
|
31
|
+
}, {
|
|
32
|
+
readonly name: "ol_channel_get";
|
|
33
|
+
readonly title: "Get Channel Details";
|
|
34
|
+
readonly description: "Get full details of a specific channel by channelId.";
|
|
35
|
+
readonly readOnly: true;
|
|
36
|
+
readonly idempotent: true;
|
|
37
|
+
readonly inputSchema: {
|
|
38
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
39
|
+
channelId: import("zod").ZodString;
|
|
40
|
+
};
|
|
41
|
+
readonly handler: typeof channelGet;
|
|
42
|
+
}, {
|
|
43
|
+
readonly name: "ol_channel_update";
|
|
44
|
+
readonly title: "Update Channel";
|
|
45
|
+
readonly description: string;
|
|
46
|
+
readonly readOnly: false;
|
|
47
|
+
readonly idempotent: true;
|
|
48
|
+
readonly inputSchema: {
|
|
49
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
50
|
+
channelId: import("zod").ZodString;
|
|
51
|
+
name: import("zod").ZodString;
|
|
52
|
+
identifier: import("zod").ZodString;
|
|
53
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
54
|
+
};
|
|
55
|
+
readonly handler: typeof channelUpdate;
|
|
56
|
+
}, {
|
|
57
|
+
readonly name: "ol_channel_delete";
|
|
58
|
+
readonly title: "Delete Channel (Permanent)";
|
|
59
|
+
readonly description: "Permanently delete a channel. This cannot be undone. Use ol_channel_list to find the channelId first.";
|
|
60
|
+
readonly readOnly: false;
|
|
61
|
+
readonly destructive: true;
|
|
62
|
+
readonly idempotent: true;
|
|
63
|
+
readonly inputSchema: {
|
|
64
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
65
|
+
channelId: import("zod").ZodString;
|
|
66
|
+
};
|
|
67
|
+
readonly handler: typeof channelDelete;
|
|
68
|
+
}];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Re-export schemas
|
|
2
|
+
export { ChannelListInputSchema, ChannelCreateInputSchema, ChannelGetInputSchema, ChannelUpdateInputSchema, ChannelDeleteInputSchema, } from "./schemas.js";
|
|
3
|
+
// Re-export handlers
|
|
4
|
+
export { channelList, channelCreate, channelGet, channelUpdate, channelDelete, } from "./handlers.js";
|
|
5
|
+
// Imports for tool definitions
|
|
6
|
+
import { ChannelListInputSchema, ChannelCreateInputSchema, ChannelGetInputSchema, ChannelUpdateInputSchema, ChannelDeleteInputSchema, } from "./schemas.js";
|
|
7
|
+
import { channelList, channelCreate, channelGet, channelUpdate, channelDelete, } from "./handlers.js";
|
|
8
|
+
// Tool definitions
|
|
9
|
+
export const channelToolDefinitions = [
|
|
10
|
+
{
|
|
11
|
+
name: "ol_channel_list",
|
|
12
|
+
title: "List Channels",
|
|
13
|
+
description: "List sales channels (e.g. Mobile App, Point of Sale, Web). Returns channelId, name, identifier, description. " +
|
|
14
|
+
"Filter by name or identifier.",
|
|
15
|
+
readOnly: true,
|
|
16
|
+
idempotent: true,
|
|
17
|
+
inputSchema: ChannelListInputSchema,
|
|
18
|
+
handler: channelList,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "ol_channel_create",
|
|
22
|
+
title: "Create Channel",
|
|
23
|
+
description: "Create a new sales channel. REQUIRED: name and identifier (must be unique within the store). " +
|
|
24
|
+
"Returns channelId on success.",
|
|
25
|
+
readOnly: false,
|
|
26
|
+
idempotent: false,
|
|
27
|
+
inputSchema: ChannelCreateInputSchema,
|
|
28
|
+
handler: channelCreate,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "ol_channel_get",
|
|
32
|
+
title: "Get Channel Details",
|
|
33
|
+
description: "Get full details of a specific channel by channelId.",
|
|
34
|
+
readOnly: true,
|
|
35
|
+
idempotent: true,
|
|
36
|
+
inputSchema: ChannelGetInputSchema,
|
|
37
|
+
handler: channelGet,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "ol_channel_update",
|
|
41
|
+
title: "Update Channel",
|
|
42
|
+
description: "Update a channel's name, identifier, or description. Both name and identifier are required (PUT replaces the full object). " +
|
|
43
|
+
"Returns channelId on success.",
|
|
44
|
+
readOnly: false,
|
|
45
|
+
idempotent: true,
|
|
46
|
+
inputSchema: ChannelUpdateInputSchema,
|
|
47
|
+
handler: channelUpdate,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "ol_channel_delete",
|
|
51
|
+
title: "Delete Channel (Permanent)",
|
|
52
|
+
description: "Permanently delete a channel. This cannot be undone. Use ol_channel_list to find the channelId first.",
|
|
53
|
+
readOnly: false,
|
|
54
|
+
destructive: true,
|
|
55
|
+
idempotent: true,
|
|
56
|
+
inputSchema: ChannelDeleteInputSchema,
|
|
57
|
+
handler: channelDelete,
|
|
58
|
+
},
|
|
59
|
+
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ChannelListInputSchema: {
|
|
3
|
+
storeCode: z.ZodOptional<z.ZodString>;
|
|
4
|
+
page: z.ZodOptional<z.ZodNumber>;
|
|
5
|
+
perPage: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
name: z.ZodOptional<z.ZodString>;
|
|
7
|
+
identifier: z.ZodOptional<z.ZodString>;
|
|
8
|
+
};
|
|
9
|
+
export declare const ChannelCreateInputSchema: {
|
|
10
|
+
storeCode: z.ZodOptional<z.ZodString>;
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
identifier: z.ZodString;
|
|
13
|
+
description: z.ZodOptional<z.ZodString>;
|
|
14
|
+
};
|
|
15
|
+
export declare const ChannelGetInputSchema: {
|
|
16
|
+
storeCode: z.ZodOptional<z.ZodString>;
|
|
17
|
+
channelId: z.ZodString;
|
|
18
|
+
};
|
|
19
|
+
export declare const ChannelUpdateInputSchema: {
|
|
20
|
+
storeCode: z.ZodOptional<z.ZodString>;
|
|
21
|
+
channelId: z.ZodString;
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
identifier: z.ZodString;
|
|
24
|
+
description: z.ZodOptional<z.ZodString>;
|
|
25
|
+
};
|
|
26
|
+
export declare const ChannelDeleteInputSchema: {
|
|
27
|
+
storeCode: z.ZodOptional<z.ZodString>;
|
|
28
|
+
channelId: z.ZodString;
|
|
29
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const STORE_CODE = z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store.");
|
|
3
|
+
export const ChannelListInputSchema = {
|
|
4
|
+
storeCode: STORE_CODE,
|
|
5
|
+
page: z.number().optional().describe("Page number (default: 1)."),
|
|
6
|
+
perPage: z.number().optional().describe("Items per page (default: 25)."),
|
|
7
|
+
name: z.string().optional().describe("Filter by channel name."),
|
|
8
|
+
identifier: z.string().optional().describe("Filter by channel identifier."),
|
|
9
|
+
};
|
|
10
|
+
export const ChannelCreateInputSchema = {
|
|
11
|
+
storeCode: STORE_CODE,
|
|
12
|
+
name: z.string().describe("Channel name (required). E.g. 'Mobile App', 'Point of Sale'."),
|
|
13
|
+
identifier: z.string().describe("Unique channel identifier (required). E.g. 'mobile', 'pos', 'web'."),
|
|
14
|
+
description: z.string().optional().describe("Channel description."),
|
|
15
|
+
};
|
|
16
|
+
export const ChannelGetInputSchema = {
|
|
17
|
+
storeCode: STORE_CODE,
|
|
18
|
+
channelId: z.string().describe("Channel ID (UUID) to retrieve."),
|
|
19
|
+
};
|
|
20
|
+
export const ChannelUpdateInputSchema = {
|
|
21
|
+
storeCode: STORE_CODE,
|
|
22
|
+
channelId: z.string().describe("Channel ID (UUID) to update."),
|
|
23
|
+
name: z.string().describe("Channel name."),
|
|
24
|
+
identifier: z.string().describe("Channel identifier (unique)."),
|
|
25
|
+
description: z.string().optional().describe("Channel description."),
|
|
26
|
+
};
|
|
27
|
+
export const ChannelDeleteInputSchema = {
|
|
28
|
+
storeCode: STORE_CODE,
|
|
29
|
+
channelId: z.string().describe("Channel ID (UUID) to delete."),
|
|
30
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ContextGetInput } from "./schemas.js";
|
|
2
|
+
interface TierSummary {
|
|
3
|
+
levelId: string;
|
|
4
|
+
name: string;
|
|
5
|
+
active: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface TierSetSummary {
|
|
8
|
+
tierSetId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
active: boolean;
|
|
11
|
+
tiers: TierSummary[];
|
|
12
|
+
}
|
|
13
|
+
interface ContextResult {
|
|
14
|
+
storeCode: string;
|
|
15
|
+
store?: {
|
|
16
|
+
code: string;
|
|
17
|
+
name: string;
|
|
18
|
+
currency?: string;
|
|
19
|
+
};
|
|
20
|
+
walletTypes: Array<{
|
|
21
|
+
code: string;
|
|
22
|
+
name: string;
|
|
23
|
+
unitSingularName?: string;
|
|
24
|
+
}>;
|
|
25
|
+
tierSets: TierSetSummary[];
|
|
26
|
+
activeSegments: Array<{
|
|
27
|
+
segmentId: string;
|
|
28
|
+
name: string;
|
|
29
|
+
customersCount?: number;
|
|
30
|
+
}>;
|
|
31
|
+
activeCampaigns: Array<{
|
|
32
|
+
campaignId: string;
|
|
33
|
+
name: string;
|
|
34
|
+
type: string;
|
|
35
|
+
trigger: string;
|
|
36
|
+
}>;
|
|
37
|
+
activeRewards: Array<{
|
|
38
|
+
rewardId: string;
|
|
39
|
+
name: string;
|
|
40
|
+
type: string;
|
|
41
|
+
costInPoints?: number;
|
|
42
|
+
}>;
|
|
43
|
+
rewardCategories: Array<{
|
|
44
|
+
categoryId: string;
|
|
45
|
+
name: string;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
export declare function contextGet(input: ContextGetInput): Promise<ContextResult>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { apiGet } from "../../client/http.js";
|
|
2
|
+
import { getStoreCode } from "../../config.js";
|
|
3
|
+
function extractCampaignName(campaign) {
|
|
4
|
+
const translations = campaign.translations;
|
|
5
|
+
if (Array.isArray(translations)) {
|
|
6
|
+
const enT = translations.find((t) => t.locale === "en" || (t.locale ?? "").startsWith("en"));
|
|
7
|
+
return enT?.name || translations[0]?.name || campaign.name || "";
|
|
8
|
+
}
|
|
9
|
+
if (translations && typeof translations === "object") {
|
|
10
|
+
return translations.en?.name || campaign.name || "";
|
|
11
|
+
}
|
|
12
|
+
return campaign.name || "";
|
|
13
|
+
}
|
|
14
|
+
export async function contextGet(input) {
|
|
15
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
16
|
+
// Parallel batch 1: fetch all list data simultaneously
|
|
17
|
+
const [walletTypesResult, tierSetsResult, segmentsResult, campaignsResult, rewardsResult, rewardCategoriesResult, storeResult,] = await Promise.allSettled([
|
|
18
|
+
apiGet(`/${storeCode}/walletType`),
|
|
19
|
+
apiGet(`/${storeCode}/tierSet?_itemsOnPage=10`),
|
|
20
|
+
apiGet(`/${storeCode}/segment?active=true&_itemsOnPage=50`),
|
|
21
|
+
apiGet(`/${storeCode}/campaign?active=true&_itemsOnPage=50`),
|
|
22
|
+
apiGet(`/${storeCode}/reward?active=true&_itemsOnPage=50`),
|
|
23
|
+
apiGet(`/${storeCode}/rewardCategory?_itemsOnPage=50`),
|
|
24
|
+
// Store info: best-effort — may fail if user lacks STORE:VIEW permission
|
|
25
|
+
apiGet(`/store?code=${encodeURIComponent(storeCode)}`),
|
|
26
|
+
]);
|
|
27
|
+
// Process wallet types
|
|
28
|
+
const walletTypes = [];
|
|
29
|
+
if (walletTypesResult.status === "fulfilled") {
|
|
30
|
+
const rawList = walletTypesResult.value;
|
|
31
|
+
const items = Array.isArray(rawList) ? rawList : rawList.items ?? [];
|
|
32
|
+
for (const wt of items) {
|
|
33
|
+
const w = wt;
|
|
34
|
+
walletTypes.push({
|
|
35
|
+
code: w.code,
|
|
36
|
+
name: w.name,
|
|
37
|
+
unitSingularName: w.unitSingularName,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Process tier sets — fetch each individually to get embedded tiers (max 3 per API limit)
|
|
42
|
+
const tierSets = [];
|
|
43
|
+
if (tierSetsResult.status === "fulfilled") {
|
|
44
|
+
const tierSetItems = tierSetsResult.value.items ?? [];
|
|
45
|
+
const tierSetDetails = await Promise.allSettled(tierSetItems.map((ts) => apiGet(`/${storeCode}/tierSet/${ts.tierSetId}`)));
|
|
46
|
+
for (let i = 0; i < tierSetItems.length; i++) {
|
|
47
|
+
const ts = tierSetItems[i];
|
|
48
|
+
const detail = tierSetDetails[i];
|
|
49
|
+
const tiers = [];
|
|
50
|
+
if (detail.status === "fulfilled" && detail.value.tiers) {
|
|
51
|
+
for (const tier of detail.value.tiers) {
|
|
52
|
+
tiers.push({
|
|
53
|
+
levelId: tier.levelId,
|
|
54
|
+
name: tier.name,
|
|
55
|
+
active: typeof tier.active === "boolean" ? tier.active : true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
tierSets.push({ tierSetId: ts.tierSetId, name: ts.name, active: ts.active, tiers });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Process active segments
|
|
63
|
+
const activeSegments = [];
|
|
64
|
+
if (segmentsResult.status === "fulfilled") {
|
|
65
|
+
for (const seg of segmentsResult.value.items ?? []) {
|
|
66
|
+
activeSegments.push({
|
|
67
|
+
segmentId: seg.segmentId,
|
|
68
|
+
name: seg.name,
|
|
69
|
+
customersCount: seg.customersCount,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Process active campaigns
|
|
74
|
+
const activeCampaigns = [];
|
|
75
|
+
if (campaignsResult.status === "fulfilled") {
|
|
76
|
+
for (const c of campaignsResult.value.items ?? []) {
|
|
77
|
+
const campaign = c;
|
|
78
|
+
activeCampaigns.push({
|
|
79
|
+
campaignId: campaign.campaignId,
|
|
80
|
+
name: extractCampaignName(campaign),
|
|
81
|
+
type: campaign.type,
|
|
82
|
+
trigger: campaign.trigger,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Process active rewards
|
|
87
|
+
const activeRewards = [];
|
|
88
|
+
if (rewardsResult.status === "fulfilled") {
|
|
89
|
+
for (const r of rewardsResult.value.items ?? []) {
|
|
90
|
+
const reward = r;
|
|
91
|
+
activeRewards.push({
|
|
92
|
+
rewardId: reward.rewardId,
|
|
93
|
+
name: reward.name,
|
|
94
|
+
type: (reward.reward || reward.type) ?? "",
|
|
95
|
+
costInPoints: reward.costInPoints,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Process reward categories
|
|
100
|
+
const rewardCategories = [];
|
|
101
|
+
if (rewardCategoriesResult.status === "fulfilled") {
|
|
102
|
+
const rawCats = rewardCategoriesResult.value;
|
|
103
|
+
const catItems = (rawCats.items || rawCats.categories || []);
|
|
104
|
+
for (const c of catItems) {
|
|
105
|
+
const cat = c;
|
|
106
|
+
rewardCategories.push({
|
|
107
|
+
categoryId: (cat.rewardCategoryId || cat.categoryId) ?? "",
|
|
108
|
+
name: cat.name,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Process store info (best-effort)
|
|
113
|
+
let store;
|
|
114
|
+
if (storeResult.status === "fulfilled") {
|
|
115
|
+
const storeItems = storeResult.value.items;
|
|
116
|
+
if (storeItems && storeItems.length > 0) {
|
|
117
|
+
const s = storeItems[0];
|
|
118
|
+
store = { code: s.code, name: s.name, currency: s.currency };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
storeCode,
|
|
123
|
+
store,
|
|
124
|
+
walletTypes,
|
|
125
|
+
tierSets,
|
|
126
|
+
activeSegments,
|
|
127
|
+
activeCampaigns,
|
|
128
|
+
activeRewards,
|
|
129
|
+
rewardCategories,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { ContextGetInputSchema } from "./schemas.js";
|
|
2
|
+
export type { ContextGetInput } from "./schemas.js";
|
|
3
|
+
export { contextGet } from "./handlers.js";
|
|
4
|
+
import { contextGet } from "./handlers.js";
|
|
5
|
+
export declare const contextToolDefinitions: readonly [{
|
|
6
|
+
readonly name: "ol_context_get";
|
|
7
|
+
readonly title: "Get Store Context";
|
|
8
|
+
readonly description: string;
|
|
9
|
+
readonly readOnly: true;
|
|
10
|
+
readonly idempotent: true;
|
|
11
|
+
readonly inputSchema: {
|
|
12
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
13
|
+
};
|
|
14
|
+
readonly handler: typeof contextGet;
|
|
15
|
+
}];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { ContextGetInputSchema } from "./schemas.js";
|
|
2
|
+
export { contextGet } from "./handlers.js";
|
|
3
|
+
import { ContextGetInputSchema } from "./schemas.js";
|
|
4
|
+
import { contextGet } from "./handlers.js";
|
|
5
|
+
export const contextToolDefinitions = [
|
|
6
|
+
{
|
|
7
|
+
name: "ol_context_get",
|
|
8
|
+
title: "Get Store Context",
|
|
9
|
+
description: "Get current store state in a single call: wallet types, tier sets (with tier IDs), " +
|
|
10
|
+
"active segments, active campaigns, active rewards, and reward categories. " +
|
|
11
|
+
"Call this FIRST at the start of every session to surface IDs for targeting, " +
|
|
12
|
+
"prevent duplicate creation, and avoid 5+ individual discovery calls. " +
|
|
13
|
+
"Results contain the levelId values needed for reward/campaign tier targeting, " +
|
|
14
|
+
"segmentId values for audience targeting, and categoryId values for reward categorization.",
|
|
15
|
+
readOnly: true,
|
|
16
|
+
idempotent: true,
|
|
17
|
+
inputSchema: ContextGetInputSchema,
|
|
18
|
+
handler: contextGet,
|
|
19
|
+
},
|
|
20
|
+
];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare function groupOfValuesList(input: {
|
|
2
|
+
storeCode?: string;
|
|
3
|
+
page?: number;
|
|
4
|
+
perPage?: number;
|
|
5
|
+
active?: boolean;
|
|
6
|
+
}): Promise<Record<string, unknown>>;
|
|
7
|
+
export declare function groupOfValuesCreate(input: {
|
|
8
|
+
storeCode?: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
active?: boolean;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
groupOfValuesId: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function groupOfValuesUpdate(input: {
|
|
16
|
+
storeCode?: string;
|
|
17
|
+
groupOfValuesId: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
active?: boolean;
|
|
21
|
+
}): Promise<Record<string, unknown>>;
|
|
22
|
+
export declare function groupValueAdd(input: {
|
|
23
|
+
storeCode?: string;
|
|
24
|
+
groupOfValuesId: string;
|
|
25
|
+
value: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
valueId: string;
|
|
29
|
+
}>;
|
|
30
|
+
export declare function groupValueUpdate(input: {
|
|
31
|
+
storeCode?: string;
|
|
32
|
+
valueId: string;
|
|
33
|
+
value: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
}): Promise<Record<string, unknown>>;
|
|
36
|
+
export declare function groupValueDelete(input: {
|
|
37
|
+
storeCode?: string;
|
|
38
|
+
valueId: string;
|
|
39
|
+
}): Promise<void>;
|