@connect-xlab/mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.js +18 -0
- package/dist/http.js +30 -0
- package/dist/index.js +178 -0
- package/dist/tools/addComment.js +31 -0
- package/dist/tools/approveMember.js +29 -0
- package/dist/tools/banMember.js +26 -0
- package/dist/tools/createCategory.js +36 -0
- package/dist/tools/createClass.js +37 -0
- package/dist/tools/createEvent.js +39 -0
- package/dist/tools/createLabLink.js +28 -0
- package/dist/tools/createNewsletterEdition.js +38 -0
- package/dist/tools/createPodcastEpisode.js +38 -0
- package/dist/tools/createPodcastShow.js +34 -0
- package/dist/tools/createPost.js +41 -0
- package/dist/tools/createShopProduct.js +46 -0
- package/dist/tools/deleteCategory.js +26 -0
- package/dist/tools/deleteClass.js +26 -0
- package/dist/tools/deleteEvent.js +26 -0
- package/dist/tools/deleteLabLink.js +26 -0
- package/dist/tools/deletePost.js +26 -0
- package/dist/tools/deleteShopProduct.js +23 -0
- package/dist/tools/demoteAdmin.js +26 -0
- package/dist/tools/getEarnings.js +28 -0
- package/dist/tools/getLabSettings.js +23 -0
- package/dist/tools/getShopSales.js +35 -0
- package/dist/tools/getStats.js +23 -0
- package/dist/tools/kickMember.js +29 -0
- package/dist/tools/listAdmins.js +23 -0
- package/dist/tools/listCategories.js +29 -0
- package/dist/tools/listChannelSubscribers.js +35 -0
- package/dist/tools/listClasses.js +23 -0
- package/dist/tools/listComments.js +31 -0
- package/dist/tools/listEvents.js +33 -0
- package/dist/tools/listInvitations.js +23 -0
- package/dist/tools/listLabLinks.js +23 -0
- package/dist/tools/listLabs.js +32 -0
- package/dist/tools/listLevels.js +23 -0
- package/dist/tools/listMembers.js +49 -0
- package/dist/tools/listNewsletterEditions.js +18 -0
- package/dist/tools/listNewsletterSubscribers.js +31 -0
- package/dist/tools/listPlugins.js +23 -0
- package/dist/tools/listPodcastEpisodes.js +31 -0
- package/dist/tools/listPodcastShows.js +18 -0
- package/dist/tools/listPodcastSubscribers.js +26 -0
- package/dist/tools/listPosts.js +49 -0
- package/dist/tools/listShops.js +28 -0
- package/dist/tools/newsletterDashboard.js +18 -0
- package/dist/tools/pinPost.js +31 -0
- package/dist/tools/promoteAdmin.js +26 -0
- package/dist/tools/publishPodcastEpisode.js +31 -0
- package/dist/tools/rejectMember.js +29 -0
- package/dist/tools/revokeInvitation.js +26 -0
- package/dist/tools/searchMembers.js +33 -0
- package/dist/tools/sendDm.js +35 -0
- package/dist/tools/sendInvitation.js +34 -0
- package/dist/tools/sendNewsletterEdition.js +23 -0
- package/dist/tools/setMetaPixel.js +34 -0
- package/dist/tools/setWelcomeDm.js +38 -0
- package/dist/tools/togglePlugin.js +27 -0
- package/dist/tools/unbanMember.js +26 -0
- package/dist/tools/unpublishPodcastEpisode.js +31 -0
- package/dist/tools/updateCategory.js +38 -0
- package/dist/tools/updateClass.js +42 -0
- package/dist/tools/updateEvent.js +44 -0
- package/dist/tools/updateLabLink.js +34 -0
- package/dist/tools/updateLabSettings.js +46 -0
- package/dist/tools/updateLevel.js +34 -0
- package/dist/tools/updatePodcastEpisode.js +40 -0
- package/dist/tools/updatePost.js +36 -0
- package/dist/tools/updateShopProduct.js +46 -0
- package/dist/tools/updateSlug.js +29 -0
- package/package.json +29 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `list_members` — liste les membres d'un Lab.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const listMembersTool = {
|
|
7
|
+
name: 'list_members',
|
|
8
|
+
description: "Liste les membres d'un Lab. Utilise l'id ou l'url du Lab (recupere avec list_labs). Filtre par status (approved/pending/rejected/left).",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string', description: "Id numerique OU url (group_url) du Lab" },
|
|
13
|
+
status: { type: 'string', enum: ['approved', 'pending', 'rejected', 'left'], default: 'approved' },
|
|
14
|
+
limit: { type: 'number', minimum: 1, maximum: 100, default: 50 },
|
|
15
|
+
offset: { type: 'number', minimum: 0, default: 0 },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
status: z.enum(['approved', 'pending', 'rejected', 'left']).optional(),
|
|
23
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
24
|
+
offset: z.number().int().min(0).optional(),
|
|
25
|
+
}),
|
|
26
|
+
async handler(args) {
|
|
27
|
+
const parsed = this.zodSchema.parse(args);
|
|
28
|
+
try {
|
|
29
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/members`, {
|
|
30
|
+
params: {
|
|
31
|
+
status: parsed.status,
|
|
32
|
+
limit: parsed.limit,
|
|
33
|
+
offset: parsed.offset,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{ type: 'text', text: JSON.stringify(data, null, 2) },
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return {
|
|
44
|
+
isError: true,
|
|
45
|
+
content: [{ type: 'text', text: formatApiError(err) }],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listNewsletterEditionsTool = {
|
|
4
|
+
name: 'list_newsletter_editions',
|
|
5
|
+
description: "Liste les editions de la newsletter du Lab (drafts + scheduled + sent).",
|
|
6
|
+
inputSchema: { type: 'object', properties: { lab: { type: 'string' }, limit: { type: 'number', minimum: 1, maximum: 50 } }, required: ['lab'], additionalProperties: false },
|
|
7
|
+
zodSchema: z.object({ lab: z.string(), limit: z.number().int().min(1).max(50).optional() }),
|
|
8
|
+
async handler(args) {
|
|
9
|
+
const p = this.zodSchema.parse(args);
|
|
10
|
+
try {
|
|
11
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/editions`, { params: { limit: p.limit } });
|
|
12
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listNewsletterSubscribersTool = {
|
|
4
|
+
name: 'list_newsletter_subscribers',
|
|
5
|
+
description: "Liste les abonnes de la newsletter du Lab. Filtrable par access (free / premium).",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
plan: { type: 'string', enum: ['free', 'monthly', 'yearly', 'lab_member'] },
|
|
11
|
+
limit: { type: 'number', minimum: 1, maximum: 200 },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
plan: z.enum(['free', 'monthly', 'yearly', 'lab_member']).optional(),
|
|
19
|
+
limit: z.number().int().min(1).max(200).optional(),
|
|
20
|
+
}),
|
|
21
|
+
async handler(args) {
|
|
22
|
+
const p = this.zodSchema.parse(args);
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/subscribers`, { params: { plan: p.plan, limit: p.limit } });
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listPluginsTool = {
|
|
4
|
+
name: 'list_plugins',
|
|
5
|
+
description: "Liste l'etat des plug-ins du Lab : Meta Pixel, Google Ads (via meta_google), Welcome DM, langue du Lab.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: { lab: { type: 'string' } },
|
|
9
|
+
required: ['lab'],
|
|
10
|
+
additionalProperties: false,
|
|
11
|
+
},
|
|
12
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
13
|
+
async handler(args) {
|
|
14
|
+
const parsed = this.zodSchema.parse(args);
|
|
15
|
+
try {
|
|
16
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/plugins`);
|
|
17
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listPodcastEpisodesTool = {
|
|
4
|
+
name: 'list_podcast_episodes',
|
|
5
|
+
description: "Liste les episodes d'un show podcast (drafts + publies). show_id vient de list_podcast_shows.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
show_id: { type: 'number' },
|
|
11
|
+
limit: { type: 'number', minimum: 1, maximum: 100 },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab', 'show_id'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
show_id: z.number().int().positive(),
|
|
19
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
20
|
+
}),
|
|
21
|
+
async handler(args) {
|
|
22
|
+
const p = this.zodSchema.parse(args);
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/podcast/shows/${p.show_id}/episodes`, { params: { limit: p.limit } });
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listPodcastShowsTool = {
|
|
4
|
+
name: 'list_podcast_shows',
|
|
5
|
+
description: "Liste les shows podcast d'un Lab (Podcast Studio, modele multi-shows).",
|
|
6
|
+
inputSchema: { type: 'object', properties: { lab: { type: 'string' } }, required: ['lab'], additionalProperties: false },
|
|
7
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
8
|
+
async handler(args) {
|
|
9
|
+
const p = this.zodSchema.parse(args);
|
|
10
|
+
try {
|
|
11
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/podcast/shows`);
|
|
12
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const listPodcastSubscribersTool = {
|
|
4
|
+
name: 'list_podcast_subscribers',
|
|
5
|
+
description: "Liste les abonnes premium podcast d'un Lab (1 abo debloque tous les shows).",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
limit: { type: 'number', minimum: 1, maximum: 200 },
|
|
11
|
+
},
|
|
12
|
+
required: ['lab'],
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
zodSchema: z.object({ lab: z.string(), limit: z.number().int().min(1).max(200).optional() }),
|
|
16
|
+
async handler(args) {
|
|
17
|
+
const p = this.zodSchema.parse(args);
|
|
18
|
+
try {
|
|
19
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/podcast/subscribers`, { params: { limit: p.limit } });
|
|
20
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `list_posts` — liste les posts d'un Lab.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const listPostsTool = {
|
|
7
|
+
name: 'list_posts',
|
|
8
|
+
description: "Liste les posts d'un Lab (les plus recents d'abord). Option `pinned_only: true` pour ne renvoyer que les posts epingles.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string', description: "Id ou url du Lab" },
|
|
13
|
+
limit: { type: 'number', minimum: 1, maximum: 100, default: 20 },
|
|
14
|
+
offset: { type: 'number', minimum: 0, default: 0 },
|
|
15
|
+
pinned_only: { type: 'boolean', default: false },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
23
|
+
offset: z.number().int().min(0).optional(),
|
|
24
|
+
pinned_only: z.boolean().optional(),
|
|
25
|
+
}),
|
|
26
|
+
async handler(args) {
|
|
27
|
+
const parsed = this.zodSchema.parse(args);
|
|
28
|
+
try {
|
|
29
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/posts`, {
|
|
30
|
+
params: {
|
|
31
|
+
limit: parsed.limit,
|
|
32
|
+
offset: parsed.offset,
|
|
33
|
+
pinned: parsed.pinned_only ? '1' : undefined,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{ type: 'text', text: JSON.stringify(data, null, 2) },
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return {
|
|
44
|
+
isError: true,
|
|
45
|
+
content: [{ type: 'text', text: formatApiError(err) }],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `list_shops` — liste les produits/offres de la boutique d'un Lab.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const listShopsTool = {
|
|
7
|
+
name: 'list_shops',
|
|
8
|
+
description: "Liste les produits/offres de la boutique d'un Lab. Renvoie id, shop_url, titre, description courte, offer_type (digital/calendar/etc), prix, publie/visible.",
|
|
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)}/shops`);
|
|
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,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const newsletterDashboardTool = {
|
|
4
|
+
name: 'newsletter_dashboard',
|
|
5
|
+
description: "Snapshot du plug-in Newsletter d'un Lab : abonnes (total/premium/free), editions (total/sent/draft/scheduled), etat actif.",
|
|
6
|
+
inputSchema: { type: 'object', properties: { lab: { type: 'string' } }, required: ['lab'], additionalProperties: false },
|
|
7
|
+
zodSchema: z.object({ lab: z.string() }),
|
|
8
|
+
async handler(args) {
|
|
9
|
+
const p = this.zodSchema.parse(args);
|
|
10
|
+
try {
|
|
11
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/dashboard`);
|
|
12
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const pinPostTool = {
|
|
4
|
+
name: 'pin_post',
|
|
5
|
+
description: "Epingle ou desepingle un post du Lab. Passer pinned=false pour desepingler.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
post_id: { type: 'number' },
|
|
11
|
+
pinned: { type: 'boolean', default: true, description: 'true pour epingler, false pour retirer' },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab', 'post_id'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
post_id: z.number().int().positive(),
|
|
19
|
+
pinned: z.boolean().optional(),
|
|
20
|
+
}),
|
|
21
|
+
async handler(args) {
|
|
22
|
+
const parsed = this.zodSchema.parse(args);
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/posts/${parsed.post_id}/pin`, { pinned: parsed.pinned ?? true });
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const promoteAdminTool = {
|
|
4
|
+
name: 'promote_admin',
|
|
5
|
+
description: "Promeut un membre en admin (type 'basic' -> 'admin'). Un admin peut moderer, poster, gerer les autres membres. Idempotent. Un super-admin ne peut pas etre modifie via MCP.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
member_id: { type: 'number' },
|
|
11
|
+
},
|
|
12
|
+
required: ['lab', 'member_id'],
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
zodSchema: z.object({ lab: z.string(), member_id: z.number().int().positive() }),
|
|
16
|
+
async handler(args) {
|
|
17
|
+
const parsed = this.zodSchema.parse(args);
|
|
18
|
+
try {
|
|
19
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/members/${parsed.member_id}/promote`);
|
|
20
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const publishPodcastEpisodeTool = {
|
|
4
|
+
name: 'publish_podcast_episode',
|
|
5
|
+
description: "Publie un episode podcast (draft -> published + published_at=now). Rendu accessible aux membres/abonnes.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
show_id: { type: 'number' },
|
|
11
|
+
episode_id: { type: 'number' },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab', 'show_id', 'episode_id'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
show_id: z.number().int().positive(),
|
|
19
|
+
episode_id: z.number().int().positive(),
|
|
20
|
+
}),
|
|
21
|
+
async handler(args) {
|
|
22
|
+
const p = this.zodSchema.parse(args);
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await http.patch(`/mcp/labs/${encodeURIComponent(p.lab)}/podcast/shows/${p.show_id}/episodes/${p.episode_id}/publish`);
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `reject_member` — refuse une demande d'adhesion pending.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { http, formatApiError } from '../http.js';
|
|
6
|
+
export const rejectMemberTool = {
|
|
7
|
+
name: 'reject_member',
|
|
8
|
+
description: "Refuse une demande d'adhesion en attente (pending -> rejected). L'id est celui de list_members data[].id.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
lab: { type: 'string', description: 'Id ou url du Lab' },
|
|
13
|
+
member_id: { type: 'number', description: 'Id du membre' },
|
|
14
|
+
},
|
|
15
|
+
required: ['lab', 'member_id'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
zodSchema: z.object({ lab: z.string(), member_id: z.number().int().positive() }),
|
|
19
|
+
async handler(args) {
|
|
20
|
+
const parsed = this.zodSchema.parse(args);
|
|
21
|
+
try {
|
|
22
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/members/${parsed.member_id}/reject`);
|
|
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,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const revokeInvitationTool = {
|
|
4
|
+
name: 'revoke_invitation',
|
|
5
|
+
description: "Revoque une invitation en attente. L'id est celui renvoye par list_invitations.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
invitation_id: { type: 'number' },
|
|
11
|
+
},
|
|
12
|
+
required: ['lab', 'invitation_id'],
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
zodSchema: z.object({ lab: z.string(), invitation_id: z.number().int().positive() }),
|
|
16
|
+
async handler(args) {
|
|
17
|
+
const parsed = this.zodSchema.parse(args);
|
|
18
|
+
try {
|
|
19
|
+
const { data } = await http.delete(`/mcp/labs/${encodeURIComponent(parsed.lab)}/invitations/${parsed.invitation_id}`);
|
|
20
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const searchMembersTool = {
|
|
4
|
+
name: 'search_members',
|
|
5
|
+
description: "Recherche des membres du Lab par firstname/lastname/email (min 2 caracteres). Utile quand tu veux trouver un membre precis dans un Lab qui en a beaucoup.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
q: { type: 'string', description: 'Terme de recherche (min 2 car)' },
|
|
11
|
+
limit: { type: 'number', minimum: 1, maximum: 50, default: 20 },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab', 'q'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
q: z.string().min(2),
|
|
19
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
20
|
+
}),
|
|
21
|
+
async handler(args) {
|
|
22
|
+
const parsed = this.zodSchema.parse(args);
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await http.get(`/mcp/labs/${encodeURIComponent(parsed.lab)}/members/search`, {
|
|
25
|
+
params: { q: parsed.q, limit: parsed.limit },
|
|
26
|
+
});
|
|
27
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool `send_dm` — envoie un message direct a un membre du Lab.
|
|
3
|
+
* L'id membre est celui retourne par list_members (`data[].id`, pas user_id).
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { http, formatApiError } from '../http.js';
|
|
7
|
+
export const sendDmTool = {
|
|
8
|
+
name: 'send_dm',
|
|
9
|
+
description: "Envoie un message direct a un membre du Lab. L'id du membre est celui retourne par list_members (colonne `id`, PAS user_id).",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
lab: { type: 'string', description: 'Id ou url du Lab' },
|
|
14
|
+
member_id: { type: 'number', description: 'Id de la ligne membre (list_members data[].id)' },
|
|
15
|
+
message: { type: 'string', description: 'Contenu du message (max 5000 char)' },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab', 'member_id', 'message'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
member_id: z.number().int().positive(),
|
|
23
|
+
message: z.string().min(1).max(5000),
|
|
24
|
+
}),
|
|
25
|
+
async handler(args) {
|
|
26
|
+
const parsed = this.zodSchema.parse(args);
|
|
27
|
+
try {
|
|
28
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(parsed.lab)}/members/${parsed.member_id}/dm`, { message: parsed.message });
|
|
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,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const sendInvitationTool = {
|
|
4
|
+
name: 'send_invitation',
|
|
5
|
+
description: "Envoie une invitation par email a rejoindre le Lab. Accepte un seul email ou une liste. Ignore les emails deja invites.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
email: { type: 'string', format: 'email' },
|
|
11
|
+
emails: { type: 'array', items: { type: 'string', format: 'email' } },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({
|
|
17
|
+
lab: z.string(),
|
|
18
|
+
email: z.string().email().optional(),
|
|
19
|
+
emails: z.array(z.string().email()).optional(),
|
|
20
|
+
}).refine(d => d.email || (d.emails && d.emails.length > 0), {
|
|
21
|
+
message: 'Fournir au moins un email (email ou emails[]).',
|
|
22
|
+
}),
|
|
23
|
+
async handler(args) {
|
|
24
|
+
const parsed = this.zodSchema.parse(args);
|
|
25
|
+
const { lab, ...body } = parsed;
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(lab)}/invitations`, 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,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const sendNewsletterEditionTool = {
|
|
4
|
+
name: 'send_newsletter_edition',
|
|
5
|
+
description: "Marque une edition draft comme envoyee. NOTE : cet appel MCP flag l'edition en 'sent' — l'envoi email reel se fait via l'endpoint xlab standard. Demander confirmation.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: { lab: { type: 'string' }, edition_id: { type: 'number' } },
|
|
9
|
+
required: ['lab', 'edition_id'],
|
|
10
|
+
additionalProperties: false,
|
|
11
|
+
},
|
|
12
|
+
zodSchema: z.object({ lab: z.string(), edition_id: z.number().int().positive() }),
|
|
13
|
+
async handler(args) {
|
|
14
|
+
const p = this.zodSchema.parse(args);
|
|
15
|
+
try {
|
|
16
|
+
const { data } = await http.post(`/mcp/labs/${encodeURIComponent(p.lab)}/newsletter/editions/${p.edition_id}/send`);
|
|
17
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const setMetaPixelTool = {
|
|
4
|
+
name: 'set_meta_pixel',
|
|
5
|
+
description: "Configure le pixel Meta (Facebook/Instagram) sur le Lab : id du pixel + access token optionnel.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
meta_id: { type: 'string', description: 'Id du pixel Meta' },
|
|
11
|
+
token: { type: 'string', description: 'Access token Meta (optionnel)' },
|
|
12
|
+
enabled: { type: 'boolean' },
|
|
13
|
+
},
|
|
14
|
+
required: ['lab', 'meta_id'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
},
|
|
17
|
+
zodSchema: z.object({
|
|
18
|
+
lab: z.string(),
|
|
19
|
+
meta_id: z.string().max(255),
|
|
20
|
+
token: z.string().nullable().optional(),
|
|
21
|
+
enabled: z.boolean().optional(),
|
|
22
|
+
}),
|
|
23
|
+
async handler(args) {
|
|
24
|
+
const parsed = this.zodSchema.parse(args);
|
|
25
|
+
const { lab, ...body } = parsed;
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/plugins/meta-pixel`, 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,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const setWelcomeDmTool = {
|
|
4
|
+
name: 'set_welcome_dm',
|
|
5
|
+
description: "Configure le DM de bienvenue envoye automatiquement aux nouveaux membres. Champs optionnels : n'envoie que ce que tu veux changer.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
enabled: { type: 'boolean' },
|
|
11
|
+
title: { type: 'string', maxLength: 500 },
|
|
12
|
+
text: { type: 'string' },
|
|
13
|
+
cta_text: { type: 'string', maxLength: 255 },
|
|
14
|
+
cta_url: { type: 'string', maxLength: 255 },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
enabled: z.boolean().optional(),
|
|
22
|
+
title: z.string().max(500).nullable().optional(),
|
|
23
|
+
text: z.string().nullable().optional(),
|
|
24
|
+
cta_text: z.string().max(255).nullable().optional(),
|
|
25
|
+
cta_url: z.string().max(255).nullable().optional(),
|
|
26
|
+
}),
|
|
27
|
+
async handler(args) {
|
|
28
|
+
const parsed = this.zodSchema.parse(args);
|
|
29
|
+
const { lab, ...body } = parsed;
|
|
30
|
+
try {
|
|
31
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/plugins/welcome-dm`, body);
|
|
32
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|