@connect-xlab/mcp-server 0.1.2 → 0.2.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/index.js +128 -0
- package/dist/tools/addCalendarQuestion.js +41 -0
- package/dist/tools/addSmartJoinQuestion.js +38 -0
- package/dist/tools/addSubscriptionPrice.js +33 -0
- package/dist/tools/clearSmartJoinResponses.js +26 -0
- package/dist/tools/createCompany.js +48 -0
- package/dist/tools/createCompanyCategory.js +29 -0
- package/dist/tools/createFunnel.js +40 -0
- package/dist/tools/createPost.js +4 -1
- package/dist/tools/createShopProduct.js +5 -3
- package/dist/tools/deleteCalendarQuestion.js +29 -0
- package/dist/tools/deleteCompany.js +29 -0
- package/dist/tools/deleteCompanyCategory.js +29 -0
- package/dist/tools/deleteFunnel.js +29 -0
- package/dist/tools/deleteFunnelItem.js +34 -0
- package/dist/tools/deleteNewsletterEdition.js +29 -0
- package/dist/tools/deleteNewsletterSubscriber.js +29 -0
- package/dist/tools/deleteSmartJoinQuestion.js +29 -0
- package/dist/tools/deleteSubscriptionPrice.js +29 -0
- package/dist/tools/duplicateSmartJoinQuestion.js +29 -0
- package/dist/tools/getCalendar.js +26 -0
- package/dist/tools/getCalendarPipeline.js +26 -0
- package/dist/tools/getFunnel.js +35 -0
- package/dist/tools/getFunnelStats.js +35 -0
- package/dist/tools/getLabAffiliationConfig.js +29 -0
- package/dist/tools/getNewsletterEdition.js +29 -0
- package/dist/tools/getNewsletterRevenue.js +28 -0
- package/dist/tools/getNewsletterSettings.js +28 -0
- package/dist/tools/getProductAffiliationConfig.js +36 -0
- package/dist/tools/getSmartJoin.js +26 -0
- package/dist/tools/getSubscriptionSettings.js +29 -0
- package/dist/tools/listCompanies.js +34 -0
- package/dist/tools/listCompanyCategories.js +28 -0
- package/dist/tools/listFunnelOffers.js +29 -0
- package/dist/tools/listLabAffiliates.js +40 -0
- package/dist/tools/listPixelRequests.js +45 -0
- package/dist/tools/listProductAffiliates.js +49 -0
- package/dist/tools/listSmartJoinResponses.js +40 -0
- package/dist/tools/manageLabAffiliate.js +41 -0
- package/dist/tools/managePixelRequest.js +35 -0
- package/dist/tools/manageProductAffiliate.js +45 -0
- package/dist/tools/reactivateNewsletter.js +28 -0
- package/dist/tools/reorderClass.js +34 -0
- package/dist/tools/reorderSmartJoinQuestions.js +32 -0
- package/dist/tools/scheduleNewsletterEdition.js +34 -0
- package/dist/tools/setCurrentSubscriptionPrice.js +34 -0
- package/dist/tools/setFunnelItem.js +94 -0
- package/dist/tools/stopNewsletter.js +28 -0
- package/dist/tools/updateCalendar.js +70 -0
- package/dist/tools/updateCalendarAvailability.js +51 -0
- package/dist/tools/updateCalendarDisqualifRules.js +48 -0
- package/dist/tools/updateCalendarFollowupConfig.js +51 -0
- package/dist/tools/updateCalendarQuestion.js +43 -0
- package/dist/tools/updateCompany.js +49 -0
- package/dist/tools/updateCompanyCategory.js +34 -0
- package/dist/tools/updateFunnel.js +37 -0
- package/dist/tools/updateLabAffiliationConfig.js +44 -0
- package/dist/tools/updateLinkInBio.js +13 -13
- package/dist/tools/updateNewsletterEdition.js +43 -0
- package/dist/tools/updateNewsletterSettings.js +63 -0
- package/dist/tools/updatePost.js +3 -1
- package/dist/tools/updateProductAffiliationConfig.js +43 -0
- package/dist/tools/updateShopProduct.js +5 -1
- package/dist/tools/updateSmartJoinQuestion.js +40 -0
- package/dist/tools/updateSmartJoinSettings.js +29 -0
- package/dist/tools/updateTrialSettings.js +34 -0
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `list_product_affiliates` — liste les affiliés d'un produit + KPIs.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
const PRODUCT_TYPES = ['shop_product', 'agent_ai'];
|
|
7
|
+
export const listProductAffiliatesTool = {
|
|
8
|
+
name: 'list_product_affiliates',
|
|
9
|
+
description: "Liste les affilies d'un produit (boutique ou agent IA) avec KPIs : nb de referrals, commission payee / en attente, pourcentage effectif, custom_percent, statut (approuve / revoque). Filtre optionnel status = pending | active | revoked. Pagine.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
product_type: { type: 'string', enum: [...PRODUCT_TYPES] },
|
|
15
|
+
product_id: { type: 'number' },
|
|
16
|
+
status: { type: 'string', enum: ['pending', 'active', 'revoked'] },
|
|
17
|
+
page: { type: 'number', minimum: 1 },
|
|
18
|
+
per_page: { type: 'number', minimum: 1, maximum: 100 },
|
|
19
|
+
},
|
|
20
|
+
required: ['lab', 'product_type', 'product_id'],
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
zodSchema: z.object({
|
|
24
|
+
lab: z.string(),
|
|
25
|
+
product_type: z.enum(PRODUCT_TYPES),
|
|
26
|
+
product_id: z.number().int().positive(),
|
|
27
|
+
status: z.enum(['pending', 'active', 'revoked']).optional(),
|
|
28
|
+
page: z.number().int().min(1).optional(),
|
|
29
|
+
per_page: z.number().int().min(1).max(100).optional(),
|
|
30
|
+
}),
|
|
31
|
+
async handler(args) {
|
|
32
|
+
const p = this.zodSchema.parse(args);
|
|
33
|
+
const qs = new URLSearchParams();
|
|
34
|
+
if (p.status !== undefined)
|
|
35
|
+
qs.set('status', p.status);
|
|
36
|
+
if (p.page !== undefined)
|
|
37
|
+
qs.set('page', String(p.page));
|
|
38
|
+
if (p.per_page !== undefined)
|
|
39
|
+
qs.set('per_page', String(p.per_page));
|
|
40
|
+
const query = qs.toString() ? `?${qs.toString()}` : '';
|
|
41
|
+
try {
|
|
42
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/affiliation/products/${p.product_type}/${p.product_id}/affiliates${query}`);
|
|
43
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `list_smart_join_responses` — réponses des prospects Smart Join (mini-CRM).
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const listSmartJoinResponsesTool = {
|
|
7
|
+
name: 'list_smart_join_responses',
|
|
8
|
+
description: "Liste les reponses des prospects au questionnaire Smart Join (mini-CRM : qui a repondu quoi avant de rejoindre le Lab). Pagine.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
page: { type: 'number', minimum: 1 },
|
|
14
|
+
per_page: { type: 'number', minimum: 1, maximum: 100 },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
page: z.number().int().min(1).optional(),
|
|
22
|
+
per_page: z.number().int().min(1).max(100).optional(),
|
|
23
|
+
}),
|
|
24
|
+
async handler(args) {
|
|
25
|
+
const p = this.zodSchema.parse(args);
|
|
26
|
+
const qs = new URLSearchParams();
|
|
27
|
+
if (p.page !== undefined)
|
|
28
|
+
qs.set('page', String(p.page));
|
|
29
|
+
if (p.per_page !== undefined)
|
|
30
|
+
qs.set('per_page', String(p.per_page));
|
|
31
|
+
const query = qs.toString() ? `?${qs.toString()}` : '';
|
|
32
|
+
try {
|
|
33
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/smart-join/responses${query}`);
|
|
34
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `manage_lab_affiliate` — revoque / restaure un affilié du Lab, ou fixe
|
|
3
|
+
* son pourcentage custom. (Pas d'approbation au niveau Lab : le programme est
|
|
4
|
+
* on/off.)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { http, formatApiError } from '../http.js';
|
|
8
|
+
export const manageLabAffiliateTool = {
|
|
9
|
+
name: 'manage_lab_affiliate',
|
|
10
|
+
description: "Gere un affilie du Lab (lab-level). action : revoke (coupe l'affiliation), restore (annule la revocation), set_percent (fixe un pourcentage custom — fournir custom_percent, ou null pour repasser au % du Lab). user_id = id de l'affilie (list_lab_affiliates). IMPORTANT : action ecriture, demander confirmation.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
lab: { type: 'string' },
|
|
15
|
+
user_id: { type: 'number' },
|
|
16
|
+
action: { type: 'string', enum: ['revoke', 'restore', 'set_percent'] },
|
|
17
|
+
custom_percent: { type: ['number', 'null'], minimum: 0, maximum: 100, description: 'Requis si action=set_percent (null = % du Lab).' },
|
|
18
|
+
},
|
|
19
|
+
required: ['lab', 'user_id', 'action'],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
zodSchema: z.object({
|
|
23
|
+
lab: z.string(),
|
|
24
|
+
user_id: z.number().int().positive(),
|
|
25
|
+
action: z.enum(['revoke', 'restore', 'set_percent']),
|
|
26
|
+
custom_percent: z.number().min(0).max(100).nullable().optional(),
|
|
27
|
+
}),
|
|
28
|
+
async handler(args) {
|
|
29
|
+
const p = this.zodSchema.parse(args);
|
|
30
|
+
const body = { action: p.action };
|
|
31
|
+
if (p.action === 'set_percent')
|
|
32
|
+
body.custom_percent = p.custom_percent ?? null;
|
|
33
|
+
try {
|
|
34
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/affiliation/lab/affiliates/${p.user_id}`, body);
|
|
35
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `manage_pixel_request` — approuve / rejette / révoque une demande de
|
|
3
|
+
* Meta Pixel d'un affilié.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const managePixelRequestTool = {
|
|
8
|
+
name: 'manage_pixel_request',
|
|
9
|
+
description: "Gere une demande de Meta Pixel d'un affilie. action : approve (autorise l'installation du pixel sur la page A propos), reject (refuse une demande en attente), revoke (retire un pixel deja approuve). id = id de la demande (list_pixel_requests). IMPORTANT : action ecriture, demander confirmation.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
id: { type: 'number', description: 'Id de la demande (list_pixel_requests)' },
|
|
15
|
+
action: { type: 'string', enum: ['approve', 'reject', 'revoke'] },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab', 'id', 'action'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
id: z.number().int().positive(),
|
|
23
|
+
action: z.enum(['approve', 'reject', 'revoke']),
|
|
24
|
+
}),
|
|
25
|
+
async handler(args) {
|
|
26
|
+
const p = this.zodSchema.parse(args);
|
|
27
|
+
try {
|
|
28
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/subscriptions/pixel-requests/${p.id}`, { action: p.action });
|
|
29
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `manage_product_affiliate` — approuve / revoque / restaure un affilié
|
|
3
|
+
* d'un produit, ou fixe son pourcentage custom.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
const PRODUCT_TYPES = ['shop_product', 'agent_ai'];
|
|
8
|
+
export const manageProductAffiliateTool = {
|
|
9
|
+
name: 'manage_product_affiliate',
|
|
10
|
+
description: "Gere un affilie d'un produit. action : approve (valide une demande en attente), revoke (coupe l'affiliation), restore (annule une revocation), set_percent (fixe un pourcentage custom pour cet affilie — fournir custom_percent, ou null pour repasser au % du produit). user_id = id de l'affilie (list_product_affiliates). IMPORTANT : action ecriture, demander confirmation.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
lab: { type: 'string' },
|
|
15
|
+
product_type: { type: 'string', enum: [...PRODUCT_TYPES] },
|
|
16
|
+
product_id: { type: 'number' },
|
|
17
|
+
user_id: { type: 'number' },
|
|
18
|
+
action: { type: 'string', enum: ['approve', 'revoke', 'restore', 'set_percent'] },
|
|
19
|
+
custom_percent: { type: ['number', 'null'], minimum: 0, maximum: 100, description: 'Requis si action=set_percent (null = % du produit).' },
|
|
20
|
+
},
|
|
21
|
+
required: ['lab', 'product_type', 'product_id', 'user_id', 'action'],
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
},
|
|
24
|
+
zodSchema: z.object({
|
|
25
|
+
lab: z.string(),
|
|
26
|
+
product_type: z.enum(PRODUCT_TYPES),
|
|
27
|
+
product_id: z.number().int().positive(),
|
|
28
|
+
user_id: z.number().int().positive(),
|
|
29
|
+
action: z.enum(['approve', 'revoke', 'restore', 'set_percent']),
|
|
30
|
+
custom_percent: z.number().min(0).max(100).nullable().optional(),
|
|
31
|
+
}),
|
|
32
|
+
async handler(args) {
|
|
33
|
+
const p = this.zodSchema.parse(args);
|
|
34
|
+
const body = { action: p.action };
|
|
35
|
+
if (p.action === 'set_percent')
|
|
36
|
+
body.custom_percent = p.custom_percent ?? null;
|
|
37
|
+
try {
|
|
38
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/affiliation/products/${p.product_type}/${p.product_id}/affiliates/${p.user_id}`, body);
|
|
39
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `reactivate_newsletter` — relance une newsletter arrêtée.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const reactivateNewsletterTool = {
|
|
7
|
+
name: 'reactivate_newsletter',
|
|
8
|
+
description: "Relance une newsletter precedemment arretee : la reactive et de-resilie les abonnements premium.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
},
|
|
14
|
+
required: ['lab'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
},
|
|
17
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
18
|
+
async handler(args) {
|
|
19
|
+
const p = this.zodSchema.parse(args);
|
|
20
|
+
try {
|
|
21
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/reactivate`, {});
|
|
22
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `reorder_class` — déplace un cours à une position d'affichage donnée.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const reorderClassTool = {
|
|
7
|
+
name: 'reorder_class',
|
|
8
|
+
description: "Deplace un cours a une position d'affichage donnee dans le Lab (0 = premier). class_id vient de list_classes.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
class_id: { type: 'number' },
|
|
14
|
+
position: { type: 'number', minimum: 0, description: "Position cible (0 = premier)" },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab', 'class_id', 'position'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
class_id: z.number().int().positive(),
|
|
22
|
+
position: z.number().int().min(0),
|
|
23
|
+
}),
|
|
24
|
+
async handler(args) {
|
|
25
|
+
const p = this.zodSchema.parse(args);
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(p.lab)}/classes/${p.class_id}/reorder`, { position: p.position });
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `reorder_smart_join_questions` — réordonne les questions Smart Join.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const reorderSmartJoinQuestionsTool = {
|
|
7
|
+
name: 'reorder_smart_join_questions',
|
|
8
|
+
description: "Reordonne les questions Smart Join. order est la liste des question_id dans l'ordre souhaite (tous doivent appartenir au Lab).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
order: { type: 'array', items: { type: 'number' }, minItems: 1 },
|
|
14
|
+
},
|
|
15
|
+
required: ['lab', 'order'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
zodSchema: z.object({
|
|
19
|
+
lab: z.string(),
|
|
20
|
+
order: z.array(z.number().int().positive()).min(1),
|
|
21
|
+
}),
|
|
22
|
+
async handler(args) {
|
|
23
|
+
const p = this.zodSchema.parse(args);
|
|
24
|
+
try {
|
|
25
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(p.lab)}/smart-join/questions/reorder`, { order: p.order });
|
|
26
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `schedule_newsletter_edition` — programme l'envoi d'une édition.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const scheduleNewsletterEditionTool = {
|
|
7
|
+
name: 'schedule_newsletter_edition',
|
|
8
|
+
description: "Programme l'envoi d'une edition de newsletter a une date/heure future. scheduled_at est interprete dans le fuseau configure de la newsletter (ex '2026-09-01T11:00:00'). Une edition deja envoyee ne peut pas etre programmee. edition_id vient de list_newsletter_editions.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
edition_id: { type: 'number' },
|
|
14
|
+
scheduled_at: { type: 'string', description: "Date/heure d'envoi (ISO local, ex 2026-09-01T11:00:00), dans le futur" },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab', 'edition_id', 'scheduled_at'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
edition_id: z.number().int().positive(),
|
|
22
|
+
scheduled_at: z.string().min(1),
|
|
23
|
+
}),
|
|
24
|
+
async handler(args) {
|
|
25
|
+
const p = this.zodSchema.parse(args);
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/editions/${p.edition_id}/schedule`, { scheduled_at: p.scheduled_at });
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `set_current_subscription_price` — choisit le prix courant d'un Lab
|
|
3
|
+
* parmi ses tiers, ou repasse le Lab en gratuit.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const setCurrentSubscriptionPriceTool = {
|
|
8
|
+
name: 'set_current_subscription_price',
|
|
9
|
+
description: "Definit le prix d'abonnement courant d'un Lab parmi ses tiers existants (price_id, cf get_subscription_settings). Omets price_id (ou passe null) pour desactiver tous les prix et repasser le Lab en gratuit. IMPORTANT : action ecriture, demander confirmation.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
price_id: { type: ['number', 'null'], description: "Id du tier a rendre courant (get_subscription_settings). null = repasse gratuit." },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
price_id: z.number().int().positive().nullable().optional(),
|
|
22
|
+
}),
|
|
23
|
+
async handler(args) {
|
|
24
|
+
const p = this.zodSchema.parse(args);
|
|
25
|
+
const body = { price_id: p.price_id ?? null };
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/subscriptions/prices/set-current`, body);
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `set_funnel_item` — cree / remplace un item de tunnel (order bump,
|
|
3
|
+
* upsell ou downsell). 1 seul item par kind : re-appeler remplace l'existant.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
const SELLABLE_TYPES = ['agent_ai', 'group_shop', 'course', 'newsletter', 'podcast_show', 'lab_channel'];
|
|
8
|
+
export const setFunnelItemTool = {
|
|
9
|
+
name: 'set_funnel_item',
|
|
10
|
+
description: "Cree ou remplace un item de tunnel : order_bump (case a cocher au checkout), upsell (offre apres achat) ou downsell (offre de repli si upsell refuse). 1 seul item par kind. offer_type + offer_id = le produit propose (list_funnel_offers). Pour un order_bump, l'offre doit avoir le meme type de paiement (one-shot / abonnement) que le produit principal. price_cents override le prix (sinon prix courant du produit). Les champs riches (kicker, subtitle, video_url, original_price_cents (prix barre), timer_minutes, bullets, faq, testimonial) servent surtout aux pages upsell/downsell.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
lab: { type: 'string' },
|
|
15
|
+
funnel_id: { type: 'number' },
|
|
16
|
+
kind: { type: 'string', enum: ['order_bump', 'upsell', 'downsell'] },
|
|
17
|
+
offer_type: { type: 'string', enum: [...SELLABLE_TYPES], description: 'Type du produit propose (list_funnel_offers)' },
|
|
18
|
+
offer_id: { type: 'number', description: 'Id du produit propose' },
|
|
19
|
+
title: { type: 'string', maxLength: 200 },
|
|
20
|
+
description: { type: 'string', maxLength: 2000 },
|
|
21
|
+
image_url: { type: 'string', maxLength: 500 },
|
|
22
|
+
accept_cta: { type: 'string', maxLength: 100, description: "Libelle du bouton d'acceptation" },
|
|
23
|
+
decline_cta: { type: 'string', maxLength: 100, description: 'Libelle du bouton de refus' },
|
|
24
|
+
design_variant: { type: 'string', maxLength: 40, description: 'Variante visuelle (order bump) : simple / bordered / card / highlighted' },
|
|
25
|
+
accent_color: { type: 'string', maxLength: 20, description: 'Couleur hex' },
|
|
26
|
+
price_cents: { type: 'number', minimum: 0, description: 'Prix override en centimes (sinon prix courant du produit propose)' },
|
|
27
|
+
currency: { type: 'string', description: 'Code devise 3 lettres (defaut eur)' },
|
|
28
|
+
// Pages upsell / downsell riches.
|
|
29
|
+
kicker: { type: 'string', maxLength: 120 },
|
|
30
|
+
subtitle: { type: 'string', maxLength: 2000 },
|
|
31
|
+
confirmation_message: { type: 'string', maxLength: 500 },
|
|
32
|
+
video_url: { type: 'string', maxLength: 500 },
|
|
33
|
+
original_price_cents: { type: 'number', minimum: 0, description: 'Prix barre (marketing) en centimes' },
|
|
34
|
+
timer_minutes: { type: 'number', minimum: 0, maximum: 1440, description: 'Compte a rebours en minutes' },
|
|
35
|
+
bullets: {
|
|
36
|
+
type: 'array', maxItems: 6,
|
|
37
|
+
items: { type: 'object', properties: { title: { type: 'string' }, description: { type: 'string' } }, additionalProperties: false },
|
|
38
|
+
},
|
|
39
|
+
bullets_title: { type: 'string', maxLength: 200 },
|
|
40
|
+
faq: {
|
|
41
|
+
type: 'array', maxItems: 6,
|
|
42
|
+
items: { type: 'object', properties: { question: { type: 'string' }, answer: { type: 'string' } }, additionalProperties: false },
|
|
43
|
+
},
|
|
44
|
+
testimonial_quote: { type: 'string', maxLength: 1000 },
|
|
45
|
+
testimonial_author: { type: 'string', maxLength: 200 },
|
|
46
|
+
},
|
|
47
|
+
required: ['lab', 'funnel_id', 'kind', 'offer_type', 'offer_id'],
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
},
|
|
50
|
+
zodSchema: z.object({
|
|
51
|
+
lab: z.string(),
|
|
52
|
+
funnel_id: z.number().int().positive(),
|
|
53
|
+
kind: z.enum(['order_bump', 'upsell', 'downsell']),
|
|
54
|
+
offer_type: z.enum(SELLABLE_TYPES),
|
|
55
|
+
offer_id: z.number().int().positive(),
|
|
56
|
+
title: z.string().max(200).nullable().optional(),
|
|
57
|
+
description: z.string().max(2000).nullable().optional(),
|
|
58
|
+
image_url: z.string().max(500).nullable().optional(),
|
|
59
|
+
accept_cta: z.string().max(100).nullable().optional(),
|
|
60
|
+
decline_cta: z.string().max(100).nullable().optional(),
|
|
61
|
+
design_variant: z.string().max(40).nullable().optional(),
|
|
62
|
+
accent_color: z.string().max(20).nullable().optional(),
|
|
63
|
+
price_cents: z.number().int().min(0).nullable().optional(),
|
|
64
|
+
currency: z.string().length(3).nullable().optional(),
|
|
65
|
+
kicker: z.string().max(120).nullable().optional(),
|
|
66
|
+
subtitle: z.string().max(2000).nullable().optional(),
|
|
67
|
+
confirmation_message: z.string().max(500).nullable().optional(),
|
|
68
|
+
video_url: z.string().max(500).nullable().optional(),
|
|
69
|
+
original_price_cents: z.number().int().min(0).nullable().optional(),
|
|
70
|
+
timer_minutes: z.number().int().min(0).max(1440).nullable().optional(),
|
|
71
|
+
bullets: z.array(z.object({
|
|
72
|
+
title: z.string().max(200).nullable().optional(),
|
|
73
|
+
description: z.string().max(600).nullable().optional(),
|
|
74
|
+
})).max(6).nullable().optional(),
|
|
75
|
+
bullets_title: z.string().max(200).nullable().optional(),
|
|
76
|
+
faq: z.array(z.object({
|
|
77
|
+
question: z.string().max(200).nullable().optional(),
|
|
78
|
+
answer: z.string().max(800).nullable().optional(),
|
|
79
|
+
})).max(6).nullable().optional(),
|
|
80
|
+
testimonial_quote: z.string().max(1000).nullable().optional(),
|
|
81
|
+
testimonial_author: z.string().max(200).nullable().optional(),
|
|
82
|
+
}),
|
|
83
|
+
async handler(args) {
|
|
84
|
+
const p = this.zodSchema.parse(args);
|
|
85
|
+
const { lab, funnel_id, ...body } = p;
|
|
86
|
+
try {
|
|
87
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(lab)}/funnels/${funnel_id}/items`, body);
|
|
88
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `stop_newsletter` — arrête la newsletter (annule les abos premium).
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const stopNewsletterTool = {
|
|
7
|
+
name: 'stop_newsletter',
|
|
8
|
+
description: "Arrete la newsletter du Lab : les abonnements premium sont annules en fin de cycle. Reversible via reactivate_newsletter. IMPORTANT : action sensible, demander confirmation.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
},
|
|
14
|
+
required: ['lab'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
},
|
|
17
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
18
|
+
async handler(args) {
|
|
19
|
+
const p = this.zodSchema.parse(args);
|
|
20
|
+
try {
|
|
21
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/stop`, {});
|
|
22
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_calendar` — met à jour la config du Calendrier IA (sous-ensemble
|
|
3
|
+
* curé ; les fenêtres horaires hot/warm par jour restent gérées via le front).
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const updateCalendarTool = {
|
|
8
|
+
name: 'update_calendar',
|
|
9
|
+
description: "Met a jour la config du Calendrier IA. N'envoie que ce que tu veux changer. Les fenetres horaires hot/warm par jour (scoring) restent gerees via le front.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
name: { type: 'string', maxLength: 200 },
|
|
15
|
+
location_type: { type: 'string', enum: ['google_meet', 'zoom', 'phone', 'in_person'] },
|
|
16
|
+
description: { type: 'string' },
|
|
17
|
+
internal_note: { type: 'string' },
|
|
18
|
+
notify_email: { type: 'string', format: 'email' },
|
|
19
|
+
event_type: { type: 'string', enum: ['free', 'paid'] },
|
|
20
|
+
price_cents: { type: 'number', minimum: 0 },
|
|
21
|
+
duration_minutes: { type: 'number', enum: [30, 60] },
|
|
22
|
+
date_range_days: { type: 'number', minimum: 1, maximum: 365 },
|
|
23
|
+
date_range_enabled: { type: 'boolean' },
|
|
24
|
+
auto_extend: { type: 'boolean' },
|
|
25
|
+
timezone: { type: 'string', maxLength: 50 },
|
|
26
|
+
ai_scoring_enabled: { type: 'boolean' },
|
|
27
|
+
ideal_client_description: { type: 'string' },
|
|
28
|
+
offer_name: { type: 'string', maxLength: 200 },
|
|
29
|
+
offer_price_cents: { type: 'number', minimum: 0 },
|
|
30
|
+
cold_offer_label: { type: 'string', maxLength: 200 },
|
|
31
|
+
cold_offer_url: { type: 'string', maxLength: 500 },
|
|
32
|
+
cold_offer_description: { type: 'string', maxLength: 500 },
|
|
33
|
+
},
|
|
34
|
+
required: ['lab'],
|
|
35
|
+
additionalProperties: false,
|
|
36
|
+
},
|
|
37
|
+
zodSchema: z.object({
|
|
38
|
+
lab: z.string(),
|
|
39
|
+
name: z.string().max(200).optional(),
|
|
40
|
+
location_type: z.enum(['google_meet', 'zoom', 'phone', 'in_person']).optional(),
|
|
41
|
+
description: z.string().nullable().optional(),
|
|
42
|
+
internal_note: z.string().nullable().optional(),
|
|
43
|
+
notify_email: z.string().email().nullable().optional(),
|
|
44
|
+
event_type: z.enum(['free', 'paid']).optional(),
|
|
45
|
+
price_cents: z.number().int().min(0).nullable().optional(),
|
|
46
|
+
duration_minutes: z.union([z.literal(30), z.literal(60)]).optional(),
|
|
47
|
+
date_range_days: z.number().int().min(1).max(365).optional(),
|
|
48
|
+
date_range_enabled: z.boolean().optional(),
|
|
49
|
+
auto_extend: z.boolean().optional(),
|
|
50
|
+
timezone: z.string().max(50).optional(),
|
|
51
|
+
ai_scoring_enabled: z.boolean().optional(),
|
|
52
|
+
ideal_client_description: z.string().nullable().optional(),
|
|
53
|
+
offer_name: z.string().max(200).nullable().optional(),
|
|
54
|
+
offer_price_cents: z.number().int().min(0).nullable().optional(),
|
|
55
|
+
cold_offer_label: z.string().max(200).nullable().optional(),
|
|
56
|
+
cold_offer_url: z.string().max(500).nullable().optional(),
|
|
57
|
+
cold_offer_description: z.string().max(500).nullable().optional(),
|
|
58
|
+
}),
|
|
59
|
+
async handler(args) {
|
|
60
|
+
const p = this.zodSchema.parse(args);
|
|
61
|
+
const { lab, ...body } = p;
|
|
62
|
+
try {
|
|
63
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/calendar`, body);
|
|
64
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_calendar_availability` — disponibilités hebdomadaires du calendrier.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCalendarAvailabilityTool = {
|
|
7
|
+
name: 'update_calendar_availability',
|
|
8
|
+
description: "Definit les disponibilites hebdomadaires du Calendrier IA. days est un tableau (max 7) d'un objet par jour : day_of_week (0=dimanche..6=samedi), is_available, start_time et end_time au format HH:MM (end > start).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
days: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
maxItems: 7,
|
|
16
|
+
items: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
day_of_week: { type: 'number', minimum: 0, maximum: 6 },
|
|
20
|
+
is_available: { type: 'boolean' },
|
|
21
|
+
start_time: { type: 'string', description: 'HH:MM' },
|
|
22
|
+
end_time: { type: 'string', description: 'HH:MM' },
|
|
23
|
+
},
|
|
24
|
+
required: ['day_of_week', 'is_available', 'start_time', 'end_time'],
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ['lab', 'days'],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
zodSchema: z.object({
|
|
33
|
+
lab: z.string(),
|
|
34
|
+
days: z.array(z.object({
|
|
35
|
+
day_of_week: z.number().int().min(0).max(6),
|
|
36
|
+
is_available: z.boolean(),
|
|
37
|
+
start_time: z.string(),
|
|
38
|
+
end_time: z.string(),
|
|
39
|
+
})).max(7),
|
|
40
|
+
}),
|
|
41
|
+
async handler(args) {
|
|
42
|
+
const p = this.zodSchema.parse(args);
|
|
43
|
+
try {
|
|
44
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(p.lab)}/calendar/availability`, { days: p.days });
|
|
45
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
};
|