@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.
Files changed (74) hide show
  1. package/dist/index.js +146 -0
  2. package/dist/tools/addCalendarQuestion.js +41 -0
  3. package/dist/tools/addSmartJoinQuestion.js +38 -0
  4. package/dist/tools/addSubscriptionPrice.js +33 -0
  5. package/dist/tools/clearSmartJoinResponses.js +26 -0
  6. package/dist/tools/createCompany.js +48 -0
  7. package/dist/tools/createCompanyCategory.js +29 -0
  8. package/dist/tools/createFunnel.js +40 -0
  9. package/dist/tools/createLinkInBioBlock.js +55 -0
  10. package/dist/tools/createPost.js +4 -1
  11. package/dist/tools/createShopProduct.js +5 -3
  12. package/dist/tools/deleteCalendarQuestion.js +29 -0
  13. package/dist/tools/deleteCompany.js +29 -0
  14. package/dist/tools/deleteCompanyCategory.js +29 -0
  15. package/dist/tools/deleteFunnel.js +29 -0
  16. package/dist/tools/deleteFunnelItem.js +34 -0
  17. package/dist/tools/deleteLinkInBioBlock.js +31 -0
  18. package/dist/tools/deleteNewsletterEdition.js +29 -0
  19. package/dist/tools/deleteNewsletterSubscriber.js +29 -0
  20. package/dist/tools/deleteSmartJoinQuestion.js +29 -0
  21. package/dist/tools/deleteSubscriptionPrice.js +29 -0
  22. package/dist/tools/duplicateSmartJoinQuestion.js +29 -0
  23. package/dist/tools/getCalendar.js +26 -0
  24. package/dist/tools/getCalendarPipeline.js +26 -0
  25. package/dist/tools/getFunnel.js +35 -0
  26. package/dist/tools/getFunnelStats.js +35 -0
  27. package/dist/tools/getLabAffiliationConfig.js +29 -0
  28. package/dist/tools/getLinkInBio.js +29 -0
  29. package/dist/tools/getNewsletterEdition.js +29 -0
  30. package/dist/tools/getNewsletterRevenue.js +28 -0
  31. package/dist/tools/getNewsletterSettings.js +28 -0
  32. package/dist/tools/getProductAffiliationConfig.js +36 -0
  33. package/dist/tools/getSmartJoin.js +26 -0
  34. package/dist/tools/getStripeConnectStatus.js +32 -0
  35. package/dist/tools/getSubscriptionSettings.js +29 -0
  36. package/dist/tools/listCompanies.js +34 -0
  37. package/dist/tools/listCompanyCategories.js +28 -0
  38. package/dist/tools/listFunnelOffers.js +29 -0
  39. package/dist/tools/listLabAffiliates.js +40 -0
  40. package/dist/tools/listPixelRequests.js +45 -0
  41. package/dist/tools/listProductAffiliates.js +49 -0
  42. package/dist/tools/listSmartJoinResponses.js +40 -0
  43. package/dist/tools/manageLabAffiliate.js +41 -0
  44. package/dist/tools/managePixelRequest.js +35 -0
  45. package/dist/tools/manageProductAffiliate.js +45 -0
  46. package/dist/tools/reactivateNewsletter.js +28 -0
  47. package/dist/tools/reorderClass.js +34 -0
  48. package/dist/tools/reorderLinkInBioBlocks.js +37 -0
  49. package/dist/tools/reorderSmartJoinQuestions.js +32 -0
  50. package/dist/tools/scheduleNewsletterEdition.js +34 -0
  51. package/dist/tools/setCurrentSubscriptionPrice.js +34 -0
  52. package/dist/tools/setFunnelItem.js +94 -0
  53. package/dist/tools/stopNewsletter.js +28 -0
  54. package/dist/tools/toggleLinkInBioPublish.js +29 -0
  55. package/dist/tools/updateCalendar.js +70 -0
  56. package/dist/tools/updateCalendarAvailability.js +51 -0
  57. package/dist/tools/updateCalendarDisqualifRules.js +48 -0
  58. package/dist/tools/updateCalendarFollowupConfig.js +51 -0
  59. package/dist/tools/updateCalendarQuestion.js +43 -0
  60. package/dist/tools/updateCompany.js +49 -0
  61. package/dist/tools/updateCompanyCategory.js +34 -0
  62. package/dist/tools/updateFunnel.js +37 -0
  63. package/dist/tools/updateLabAffiliationConfig.js +44 -0
  64. package/dist/tools/updateLinkInBio.js +61 -0
  65. package/dist/tools/updateLinkInBioBlock.js +44 -0
  66. package/dist/tools/updateNewsletterEdition.js +43 -0
  67. package/dist/tools/updateNewsletterSettings.js +63 -0
  68. package/dist/tools/updatePost.js +3 -1
  69. package/dist/tools/updateProductAffiliationConfig.js +43 -0
  70. package/dist/tools/updateShopProduct.js +5 -1
  71. package/dist/tools/updateSmartJoinQuestion.js +40 -0
  72. package/dist/tools/updateSmartJoinSettings.js +29 -0
  73. package/dist/tools/updateTrialSettings.js +34 -0
  74. package/package.json +19 -6
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tool `list_companies` — liste les societes du Marketplace d'un Lab (annuaire
3
+ * de mentors / partenaires). Distinct de la Boutique (list_shops).
4
+ */
5
+ import { z } from 'zod';
6
+ import { http, formatApiError } from '../http.js';
7
+ export const listCompaniesTool = {
8
+ name: 'list_companies',
9
+ description: "Liste les societes du Marketplace d'un Lab (annuaire de mentors/partenaires) — distinct de la Boutique. Renvoie uuid, nom, description courte, site, CTA, categorie, position. Filtre optionnel par category_id (list_company_categories).",
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ lab: { type: 'string', description: 'Id ou url du Lab' },
14
+ category_id: { type: 'number', description: 'Optionnel — filtre par categorie Marketplace' },
15
+ },
16
+ required: ['lab'],
17
+ additionalProperties: false,
18
+ },
19
+ zodSchema: z.object({
20
+ lab: z.string(),
21
+ category_id: z.number().int().positive().optional(),
22
+ }),
23
+ async handler(args) {
24
+ const parsed = this.zodSchema.parse(args);
25
+ const query = parsed.category_id !== undefined ? `?category_id=${parsed.category_id}` : '';
26
+ try {
27
+ const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/companies${query}`);
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,28 @@
1
+ /**
2
+ * Tool `list_company_categories` — liste les categories du Marketplace d'un Lab.
3
+ */
4
+ import { z } from 'zod';
5
+ import { http, formatApiError } from '../http.js';
6
+ export const listCompanyCategoriesTool = {
7
+ name: 'list_company_categories',
8
+ description: "Liste les categories du Marketplace d'un Lab (utilisees pour classer les societes). Renvoie id + nom. Recupere l'id ici avant create_company / list_companies.",
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ lab: { type: 'string', description: 'Id ou url du Lab' },
13
+ },
14
+ required: ['lab'],
15
+ additionalProperties: false,
16
+ },
17
+ zodSchema: z.object({ lab: z.string() }),
18
+ async handler(args) {
19
+ const parsed = this.zodSchema.parse(args);
20
+ try {
21
+ const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/company-categories`);
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 `list_funnel_offers` — liste les produits d'un Lab utilisables comme
3
+ * order bump / upsell / downsell dans un tunnel de vente.
4
+ */
5
+ import { z } from 'zod';
6
+ import { http, formatApiError } from '../http.js';
7
+ export const listFunnelOffersTool = {
8
+ name: 'list_funnel_offers',
9
+ description: "Liste les produits vendables du Lab utilisables comme order bump / upsell / downsell (agents IA payants, produits boutique Stripe, canaux payants, newsletters et podcasts premium). Renvoie type, id, titre, prix, kind (one_shot / recurring_monthly). Utilise-le pour recuperer offer_type + offer_id avant set_funnel_item.",
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ lab: { type: 'string', description: 'Id ou url du Lab' },
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.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/funnels/offers`);
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,40 @@
1
+ /**
2
+ * Tool `list_lab_affiliates` — liste les affiliés du Lab (niveau Lab) + KPIs.
3
+ */
4
+ import { z } from 'zod';
5
+ import { http, formatApiError } from '../http.js';
6
+ export const listLabAffiliatesTool = {
7
+ name: 'list_lab_affiliates',
8
+ description: "Liste les membres qui promeuvent le Lab (affiliation lab-level) avec KPIs : nb de filleuls, commission payee / en attente, pourcentage effectif, custom_percent, revoque ?. 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)}/affiliation/lab/affiliates${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,45 @@
1
+ /**
2
+ * Tool `list_pixel_requests` — demandes d'installation de Meta Pixel par les
3
+ * affiliés du Lab (sur la page À propos).
4
+ */
5
+ import { z } from 'zod';
6
+ import { http, formatApiError } from '../http.js';
7
+ export const listPixelRequestsTool = {
8
+ name: 'list_pixel_requests',
9
+ description: "Liste les demandes d'installation de Meta Pixel envoyees par les affilies du Lab (pour retargeter les visiteurs qu'ils envoient). Filtre optionnel status = pending | approved | rejected | revoked. Pagine.",
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ lab: { type: 'string' },
14
+ status: { type: 'string', enum: ['pending', 'approved', 'rejected', 'revoked'] },
15
+ page: { type: 'number', minimum: 1 },
16
+ per_page: { type: 'number', minimum: 1, maximum: 100 },
17
+ },
18
+ required: ['lab'],
19
+ additionalProperties: false,
20
+ },
21
+ zodSchema: z.object({
22
+ lab: z.string(),
23
+ status: z.enum(['pending', 'approved', 'rejected', 'revoked']).optional(),
24
+ page: z.number().int().min(1).optional(),
25
+ per_page: z.number().int().min(1).max(100).optional(),
26
+ }),
27
+ async handler(args) {
28
+ const p = this.zodSchema.parse(args);
29
+ const qs = new URLSearchParams();
30
+ if (p.status !== undefined)
31
+ qs.set('status', p.status);
32
+ if (p.page !== undefined)
33
+ qs.set('page', String(p.page));
34
+ if (p.per_page !== undefined)
35
+ qs.set('per_page', String(p.per_page));
36
+ const query = qs.toString() ? `?${qs.toString()}` : '';
37
+ try {
38
+ const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/subscriptions/pixel-requests${query}`);
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,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,37 @@
1
+ /**
2
+ * Tool `reorder_link_in_bio_blocks` — reordonne les blocs. Passer la liste
3
+ * complete des block_ids dans l'ordre voulu (top → bottom).
4
+ */
5
+ import { z } from 'zod';
6
+ import { http, formatApiError } from '../http.js';
7
+ export const reorderLinkInBioBlocksTool = {
8
+ name: 'reorder_link_in_bio_blocks',
9
+ description: "Reordonne les blocs de la page Link in Bio. Passer la liste complete des block_ids dans l'ordre souhaite (premier = top de la page). Le back rejette si la liste ne matche pas exactement les blocs existants.",
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ lab: { type: 'string' },
14
+ block_ids: {
15
+ type: 'array',
16
+ items: { type: 'number', minimum: 1 },
17
+ minItems: 1,
18
+ },
19
+ },
20
+ required: ['lab', 'block_ids'],
21
+ additionalProperties: false,
22
+ },
23
+ zodSchema: z.object({
24
+ lab: z.string(),
25
+ block_ids: z.array(z.number().int().positive()).min(1),
26
+ }),
27
+ async handler(args) {
28
+ const parsed = this.zodSchema.parse(args);
29
+ try {
30
+ const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/link-in-bio/blocks/reorder`, { block_ids: parsed.block_ids });
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,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
+ };