@connect-xlab/mcp-server 0.1.1 → 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 +146 -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/createLinkInBioBlock.js +55 -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/deleteLinkInBioBlock.js +31 -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/getLinkInBio.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/getStripeConnectStatus.js +32 -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/reorderLinkInBioBlocks.js +37 -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/toggleLinkInBioPublish.js +29 -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 +61 -0
- package/dist/tools/updateLinkInBioBlock.js +44 -0
- 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 +19 -6
|
@@ -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,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `toggle_link_in_bio_publish` — publie / depublie la page. Une page
|
|
3
|
+
* depubliee reste editable mais n'est plus accessible via son slug public.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const toggleLinkInBioPublishTool = {
|
|
8
|
+
name: 'toggle_link_in_bio_publish',
|
|
9
|
+
description: "Publie ou depublie la page Link in Bio. Le back bascule automatiquement l'etat (pas besoin de passer publish=true/false). Retourne l'etat resultant.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
},
|
|
15
|
+
required: ['lab'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
19
|
+
async handler(args) {
|
|
20
|
+
const parsed = this.zodSchema.parse(args);
|
|
21
|
+
try {
|
|
22
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(parsed.lab)}/link-in-bio/publish`, {});
|
|
23
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_calendar_disqualif_rules` — règles de disqualification des leads.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCalendarDisqualifRulesTool = {
|
|
7
|
+
name: 'update_calendar_disqualif_rules',
|
|
8
|
+
description: "Remplace les regles de disqualification automatique des leads du Calendrier IA. rules est le jeu complet de regles : condition_type = phone_country (indicatif telephonique) ou question_answer (reponse a une question, question_id requis), disqualifying_values = valeurs qui disqualifient. Envoyer un tableau vide efface toutes les regles.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
rules: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
items: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
condition_type: { type: 'string', enum: ['phone_country', 'question_answer'] },
|
|
19
|
+
question_id: { type: ['number', 'null'], description: 'Requis si condition_type=question_answer' },
|
|
20
|
+
disqualifying_values: { type: 'array', items: { type: 'string' } },
|
|
21
|
+
},
|
|
22
|
+
required: ['condition_type'],
|
|
23
|
+
additionalProperties: false,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ['lab', 'rules'],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
},
|
|
30
|
+
zodSchema: z.object({
|
|
31
|
+
lab: z.string(),
|
|
32
|
+
rules: z.array(z.object({
|
|
33
|
+
condition_type: z.enum(['phone_country', 'question_answer']),
|
|
34
|
+
question_id: z.number().int().positive().nullable().optional(),
|
|
35
|
+
disqualifying_values: z.array(z.string()).optional(),
|
|
36
|
+
})),
|
|
37
|
+
}),
|
|
38
|
+
async handler(args) {
|
|
39
|
+
const p = this.zodSchema.parse(args);
|
|
40
|
+
try {
|
|
41
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(p.lab)}/calendar/disqualif-rules`, { rules: p.rules });
|
|
42
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_calendar_followup_config` — relances automatiques des prospects.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCalendarFollowupConfigTool = {
|
|
7
|
+
name: 'update_calendar_followup_config',
|
|
8
|
+
description: "Configure les relances automatiques des prospects du Calendrier IA (max 2). trigger_type = abandon_step1 (a quitte au formulaire) ou no_booking (n'a pas reserve). Pour chaque : enabled, delay_hours (1..720), message_template optionnel.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
configs: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
maxItems: 2,
|
|
16
|
+
items: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
trigger_type: { type: 'string', enum: ['abandon_step1', 'no_booking'] },
|
|
20
|
+
enabled: { type: 'boolean' },
|
|
21
|
+
delay_hours: { type: 'number', minimum: 1, maximum: 720 },
|
|
22
|
+
message_template: { type: 'string' },
|
|
23
|
+
},
|
|
24
|
+
required: ['trigger_type', 'enabled', 'delay_hours'],
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ['lab', 'configs'],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
zodSchema: z.object({
|
|
33
|
+
lab: z.string(),
|
|
34
|
+
configs: z.array(z.object({
|
|
35
|
+
trigger_type: z.enum(['abandon_step1', 'no_booking']),
|
|
36
|
+
enabled: z.boolean(),
|
|
37
|
+
delay_hours: z.number().int().min(1).max(720),
|
|
38
|
+
message_template: z.string().nullable().optional(),
|
|
39
|
+
})).max(2),
|
|
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/followup-config`, { configs: p.configs });
|
|
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
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_calendar_question` — modifie une question du calendrier.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCalendarQuestionTool = {
|
|
7
|
+
name: 'update_calendar_question',
|
|
8
|
+
description: "Modifie une question de qualification du Calendrier IA. question_id vient de get_calendar. question_type = text ou qcm (options requises si qcm).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
question_id: { type: 'number' },
|
|
14
|
+
label: { type: 'string', maxLength: 500 },
|
|
15
|
+
question_type: { type: 'string', enum: ['text', 'qcm'] },
|
|
16
|
+
icon: { type: 'string', maxLength: 40 },
|
|
17
|
+
required: { type: 'boolean' },
|
|
18
|
+
options: { type: 'array', items: { type: 'string', maxLength: 200 } },
|
|
19
|
+
},
|
|
20
|
+
required: ['lab', 'question_id', 'label', 'question_type'],
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
zodSchema: z.object({
|
|
24
|
+
lab: z.string(),
|
|
25
|
+
question_id: z.number().int().positive(),
|
|
26
|
+
label: z.string().min(1).max(500),
|
|
27
|
+
question_type: z.enum(['text', 'qcm']),
|
|
28
|
+
icon: z.string().max(40).nullable().optional(),
|
|
29
|
+
required: z.boolean().optional(),
|
|
30
|
+
options: z.array(z.string().max(200)).optional(),
|
|
31
|
+
}),
|
|
32
|
+
async handler(args) {
|
|
33
|
+
const p = this.zodSchema.parse(args);
|
|
34
|
+
const { lab, question_id, ...body } = p;
|
|
35
|
+
try {
|
|
36
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/calendar/questions/${question_id}`, body);
|
|
37
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_company` — modifie une societe du Marketplace (par uuid).
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCompanyTool = {
|
|
7
|
+
name: 'update_company',
|
|
8
|
+
description: "Modifie une societe du Marketplace (identifiee par son uuid, cf list_companies). Champs optionnels : n'envoie que ce qui change. IMPORTANT : action ecriture, demander confirmation.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
uuid: { type: 'string', description: 'uuid de la societe (list_companies)' },
|
|
14
|
+
name: { type: 'string', maxLength: 255 },
|
|
15
|
+
website: { type: 'string' },
|
|
16
|
+
description: { type: 'string' },
|
|
17
|
+
short_description: { type: 'string' },
|
|
18
|
+
cta_link: { type: 'string' },
|
|
19
|
+
text_cta: { type: 'string', maxLength: 255 },
|
|
20
|
+
color: { type: 'string' },
|
|
21
|
+
company_category_id: { type: 'number', description: 'Nouvelle categorie (list_company_categories)' },
|
|
22
|
+
},
|
|
23
|
+
required: ['lab', 'uuid'],
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
},
|
|
26
|
+
zodSchema: z.object({
|
|
27
|
+
lab: z.string(),
|
|
28
|
+
uuid: z.string(),
|
|
29
|
+
name: z.string().max(255).optional(),
|
|
30
|
+
website: z.string().url().optional(),
|
|
31
|
+
description: z.string().optional(),
|
|
32
|
+
short_description: z.string().optional(),
|
|
33
|
+
cta_link: z.string().url().optional(),
|
|
34
|
+
text_cta: z.string().max(255).nullable().optional(),
|
|
35
|
+
color: z.string().max(20).optional(),
|
|
36
|
+
company_category_id: z.number().int().positive().optional(),
|
|
37
|
+
}),
|
|
38
|
+
async handler(args) {
|
|
39
|
+
const parsed = this.zodSchema.parse(args);
|
|
40
|
+
const { lab, uuid, ...body } = parsed;
|
|
41
|
+
try {
|
|
42
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/companies/${encodeURIComponent(uuid)}`, body);
|
|
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,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_company_category` — renomme une categorie Marketplace.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateCompanyCategoryTool = {
|
|
7
|
+
name: 'update_company_category',
|
|
8
|
+
description: "Renomme une categorie du Marketplace (identifiee par son id, cf list_company_categories).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
category_id: { type: 'number', description: 'Id de la categorie (list_company_categories)' },
|
|
14
|
+
name: { type: 'string', maxLength: 255 },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab', 'category_id', 'name'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
category_id: z.number().int().positive(),
|
|
22
|
+
name: z.string().min(1).max(255),
|
|
23
|
+
}),
|
|
24
|
+
async handler(args) {
|
|
25
|
+
const parsed = this.zodSchema.parse(args);
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/company-categories/${parsed.category_id}`, { name: parsed.name });
|
|
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,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_funnel` — modifie le nom / l'activation d'un tunnel de vente.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const updateFunnelTool = {
|
|
7
|
+
name: 'update_funnel',
|
|
8
|
+
description: "Modifie un tunnel de vente (nom, activation). funnel_id vient de get_funnel / create_funnel. Passe is_active=false pour desactiver le tunnel sans le supprimer.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string' },
|
|
13
|
+
funnel_id: { type: 'number' },
|
|
14
|
+
name: { type: 'string', maxLength: 120 },
|
|
15
|
+
is_active: { type: 'boolean' },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab', 'funnel_id'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
funnel_id: z.number().int().positive(),
|
|
23
|
+
name: z.string().max(120).nullable().optional(),
|
|
24
|
+
is_active: z.boolean().optional(),
|
|
25
|
+
}),
|
|
26
|
+
async handler(args) {
|
|
27
|
+
const p = this.zodSchema.parse(args);
|
|
28
|
+
const { lab, funnel_id, ...body } = p;
|
|
29
|
+
try {
|
|
30
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/funnels/${funnel_id}`, body);
|
|
31
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_lab_affiliation_config` — configure le programme d'affiliation
|
|
3
|
+
* au niveau du Lab entier.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const updateLabAffiliationConfigTool = {
|
|
8
|
+
name: 'update_lab_affiliation_config',
|
|
9
|
+
description: "Configure le programme d'affiliation du Lab entier. affiliation_status = '1' actif / '0' inactif. affiliation_percent = commission %. Les 3 scopes activent l'affiliation sur : paiements one-shot, abonnement au Lab, abonnements internes. affiliation_badge_status = affiche le badge affilie.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string' },
|
|
14
|
+
affiliation_status: { type: 'string', enum: ['0', '1'] },
|
|
15
|
+
affiliation_percent: { type: 'number', minimum: 0, maximum: 100 },
|
|
16
|
+
affiliation_scope_paid_one_shot: { type: 'boolean' },
|
|
17
|
+
affiliation_scope_lab_subscription: { type: 'boolean' },
|
|
18
|
+
affiliation_scope_internal_subscription: { type: 'boolean' },
|
|
19
|
+
affiliation_badge_status: { type: 'string', enum: ['0', '1'] },
|
|
20
|
+
},
|
|
21
|
+
required: ['lab'],
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
},
|
|
24
|
+
zodSchema: z.object({
|
|
25
|
+
lab: z.string(),
|
|
26
|
+
affiliation_status: z.enum(['0', '1']).optional(),
|
|
27
|
+
affiliation_percent: z.number().min(0).max(100).optional(),
|
|
28
|
+
affiliation_scope_paid_one_shot: z.boolean().optional(),
|
|
29
|
+
affiliation_scope_lab_subscription: z.boolean().optional(),
|
|
30
|
+
affiliation_scope_internal_subscription: z.boolean().optional(),
|
|
31
|
+
affiliation_badge_status: z.enum(['0', '1']).optional(),
|
|
32
|
+
}),
|
|
33
|
+
async handler(args) {
|
|
34
|
+
const p = this.zodSchema.parse(args);
|
|
35
|
+
const { lab, ...body } = p;
|
|
36
|
+
try {
|
|
37
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/affiliation/lab/config`, body);
|
|
38
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `update_link_in_bio` — upsert des meta de la page (slug, display_name,
|
|
3
|
+
* bio, theme, layout, socials, URLs de photos). Si la page n'existe pas
|
|
4
|
+
* encore, elle est creee. Tous les champs sont optionnels : on ne modifie
|
|
5
|
+
* que ce qui est fourni.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { http, formatApiError } from '../http.js';
|
|
9
|
+
const SOCIAL_KEYS = ['instagram', 'tiktok', 'youtube', 'x', 'linkedin', 'facebook', 'whatsapp', 'telegram'];
|
|
10
|
+
export const updateLinkInBioTool = {
|
|
11
|
+
name: 'update_link_in_bio',
|
|
12
|
+
description: "Upsert (remplacement) de la page Link in Bio. Cree la page si absente. C'est un upsert COMPLET : tu dois TOUJOURS fournir slug, display_name, photo_layout et theme (fais get_link_in_bio d'abord pour recuperer les valeurs actuelles, puis renvoie-les avec tes modifs). Autres champs : bio, accent_color (#RRGGBB), desktop_layout (split/centered), avatar_url, banner_url, portrait_url, socials{instagram, tiktok, youtube, x, linkedin, facebook, whatsapp, telegram}. theme = light | dark | violet | yellow. photo_layout = avatar | banner | portrait. Les uploads d'images (avatar/banniere) se font via le front — ici on passe des URLs. Attention : changer le slug a un cooldown de 30 jours.",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
lab: { type: 'string' },
|
|
17
|
+
slug: { type: 'string', minLength: 3, maxLength: 60, description: 'minuscule, ^[a-z][a-z0-9_-]{2,59}$' },
|
|
18
|
+
display_name: { type: 'string', maxLength: 100 },
|
|
19
|
+
bio: { type: 'string', maxLength: 500 },
|
|
20
|
+
theme: { type: 'string', enum: ['light', 'dark', 'violet', 'yellow'] },
|
|
21
|
+
accent_color: { type: 'string', pattern: '^#[0-9A-Fa-f]{6}$' },
|
|
22
|
+
photo_layout: { type: 'string', enum: ['avatar', 'banner', 'portrait'] },
|
|
23
|
+
desktop_layout: { type: 'string', enum: ['split', 'centered'] },
|
|
24
|
+
avatar_url: { type: 'string' },
|
|
25
|
+
banner_url: { type: 'string' },
|
|
26
|
+
portrait_url: { type: 'string' },
|
|
27
|
+
socials: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: Object.fromEntries(SOCIAL_KEYS.map((k) => [k, { type: 'string', maxLength: 200 }])),
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ['lab', 'slug', 'display_name', 'photo_layout', 'theme'],
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
},
|
|
36
|
+
zodSchema: z.object({
|
|
37
|
+
lab: z.string(),
|
|
38
|
+
slug: z.string().min(3).max(60),
|
|
39
|
+
display_name: z.string().max(100),
|
|
40
|
+
bio: z.string().max(500).optional(),
|
|
41
|
+
theme: z.enum(['light', 'dark', 'violet', 'yellow']),
|
|
42
|
+
accent_color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
43
|
+
photo_layout: z.enum(['avatar', 'banner', 'portrait']),
|
|
44
|
+
desktop_layout: z.enum(['split', 'centered']).optional(),
|
|
45
|
+
avatar_url: z.string().optional(),
|
|
46
|
+
banner_url: z.string().optional(),
|
|
47
|
+
portrait_url: z.string().optional(),
|
|
48
|
+
socials: z.record(z.string().max(200)).optional(),
|
|
49
|
+
}),
|
|
50
|
+
async handler(args) {
|
|
51
|
+
const parsed = this.zodSchema.parse(args);
|
|
52
|
+
const { lab, ...body } = parsed;
|
|
53
|
+
try {
|
|
54
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(lab)}/link-in-bio`, body);
|
|
55
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
};
|