@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,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const togglePluginTool = {
|
|
4
|
+
name: 'toggle_plugin',
|
|
5
|
+
description: "Active ou desactive un plug-in par son meta_type. Valeurs typiques : 'facebook' (Meta Pixel), 'google' (Google Ads).",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
meta_type: { type: 'string', description: 'facebook | google | ...' },
|
|
11
|
+
enabled: { type: 'boolean' },
|
|
12
|
+
},
|
|
13
|
+
required: ['lab', 'meta_type', 'enabled'],
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
},
|
|
16
|
+
zodSchema: z.object({ lab: z.string(), meta_type: z.string(), enabled: z.boolean() }),
|
|
17
|
+
async handler(args) {
|
|
18
|
+
const parsed = this.zodSchema.parse(args);
|
|
19
|
+
try {
|
|
20
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(parsed.lab)}/plugins/${encodeURIComponent(parsed.meta_type)}/toggle`, { enabled: parsed.enabled });
|
|
21
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const unbanMemberTool = {
|
|
4
|
+
name: 'unban_member',
|
|
5
|
+
description: "Restaure un membre banni : status 'blocked' -> 'approved'. Idempotent.",
|
|
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}/unban`);
|
|
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 unpublishPodcastEpisodeTool = {
|
|
4
|
+
name: 'unpublish_podcast_episode',
|
|
5
|
+
description: "Depublie un episode (published -> draft + published_at=null). Le retire de la vue publique.",
|
|
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}/unpublish`);
|
|
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,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateCategoryTool = {
|
|
4
|
+
name: 'update_category',
|
|
5
|
+
description: "Met a jour une categorie (nom, description, privee, niveau min). Champs optionnels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
category_id: { type: 'number' },
|
|
11
|
+
name: { type: 'string', maxLength: 30 },
|
|
12
|
+
description: { type: 'string', maxLength: 255 },
|
|
13
|
+
is_private: { type: 'boolean' },
|
|
14
|
+
min_user_level: { type: 'number', minimum: 0 },
|
|
15
|
+
},
|
|
16
|
+
required: ['lab', 'category_id'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
zodSchema: z.object({
|
|
20
|
+
lab: z.string(),
|
|
21
|
+
category_id: z.number().int().positive(),
|
|
22
|
+
name: z.string().max(30).optional(),
|
|
23
|
+
description: z.string().max(255).optional(),
|
|
24
|
+
is_private: z.boolean().optional(),
|
|
25
|
+
min_user_level: z.number().int().min(0).nullable().optional(),
|
|
26
|
+
}),
|
|
27
|
+
async handler(args) {
|
|
28
|
+
const parsed = this.zodSchema.parse(args);
|
|
29
|
+
const { lab, category_id, ...body } = parsed;
|
|
30
|
+
try {
|
|
31
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/categories/${category_id}`, 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
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateClassTool = {
|
|
4
|
+
name: 'update_class',
|
|
5
|
+
description: "Met a jour une classe/cours (nom, description, publication, prix, niveau min). Champs optionnels : n'envoie que ceux que tu veux changer. Toggle is_published pour publier/depublier.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
class_id: { type: 'number' },
|
|
11
|
+
name: { type: 'string', maxLength: 50 },
|
|
12
|
+
description: { type: 'string', maxLength: 400 },
|
|
13
|
+
access: { type: 'string', maxLength: 255, description: "'all' | 'paid' | autre valeur libre" },
|
|
14
|
+
min_user_level: { type: 'number', minimum: 0 },
|
|
15
|
+
is_published: { type: 'boolean' },
|
|
16
|
+
price: { type: 'string', description: "Prix en euros (chaine, ex '19.90'). null pour gratuit." },
|
|
17
|
+
},
|
|
18
|
+
required: ['lab', 'class_id'],
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
},
|
|
21
|
+
zodSchema: z.object({
|
|
22
|
+
lab: z.string(),
|
|
23
|
+
class_id: z.number().int().positive(),
|
|
24
|
+
name: z.string().max(50).optional(),
|
|
25
|
+
description: z.string().max(400).optional(),
|
|
26
|
+
access: z.string().max(255).optional(),
|
|
27
|
+
min_user_level: z.number().int().min(0).nullable().optional(),
|
|
28
|
+
is_published: z.boolean().optional(),
|
|
29
|
+
price: z.string().max(255).nullable().optional(),
|
|
30
|
+
}),
|
|
31
|
+
async handler(args) {
|
|
32
|
+
const parsed = this.zodSchema.parse(args);
|
|
33
|
+
const { lab, class_id, ...body } = parsed;
|
|
34
|
+
try {
|
|
35
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/classes/${class_id}`, body);
|
|
36
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateEventTool = {
|
|
4
|
+
name: 'update_event',
|
|
5
|
+
description: "Met a jour un evenement du calendrier (titre, description, date, duree, lien, reminder). Champs optionnels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
event_id: { type: 'number' },
|
|
11
|
+
title: { type: 'string', maxLength: 50 },
|
|
12
|
+
description: { type: 'string' },
|
|
13
|
+
event_date: { type: 'string', description: 'ISO 8601 date' },
|
|
14
|
+
timezone: { type: 'string' },
|
|
15
|
+
duration: { type: 'string' },
|
|
16
|
+
link: { type: 'string' },
|
|
17
|
+
reminder_enabled: { type: 'boolean' },
|
|
18
|
+
},
|
|
19
|
+
required: ['lab', 'event_id'],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
zodSchema: z.object({
|
|
23
|
+
lab: z.string(),
|
|
24
|
+
event_id: z.number().int().positive(),
|
|
25
|
+
title: z.string().max(50).optional(),
|
|
26
|
+
description: z.string().optional(),
|
|
27
|
+
event_date: z.string().optional(),
|
|
28
|
+
timezone: z.string().optional(),
|
|
29
|
+
duration: z.string().optional(),
|
|
30
|
+
link: z.string().nullable().optional(),
|
|
31
|
+
reminder_enabled: z.boolean().optional(),
|
|
32
|
+
}),
|
|
33
|
+
async handler(args) {
|
|
34
|
+
const parsed = this.zodSchema.parse(args);
|
|
35
|
+
const { lab, event_id, ...body } = parsed;
|
|
36
|
+
try {
|
|
37
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/events/${event_id}`, 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,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateLabLinkTool = {
|
|
4
|
+
name: 'update_lab_link',
|
|
5
|
+
description: "Met a jour un lien sidebar (label ou url). Champs optionnels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
link_id: { type: 'number' },
|
|
11
|
+
label: { type: 'string', maxLength: 30 },
|
|
12
|
+
url: { type: 'string', maxLength: 255 },
|
|
13
|
+
},
|
|
14
|
+
required: ['lab', 'link_id'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
},
|
|
17
|
+
zodSchema: z.object({
|
|
18
|
+
lab: z.string(),
|
|
19
|
+
link_id: z.number().int().positive(),
|
|
20
|
+
label: z.string().max(30).optional(),
|
|
21
|
+
url: z.string().max(255).optional(),
|
|
22
|
+
}),
|
|
23
|
+
async handler(args) {
|
|
24
|
+
const parsed = this.zodSchema.parse(args);
|
|
25
|
+
const { lab, link_id, ...body } = parsed;
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/links/${link_id}`, 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,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateLabSettingsTool = {
|
|
4
|
+
name: 'update_lab_settings',
|
|
5
|
+
description: "Met a jour les settings d'un Lab. Tous les champs sont optionnels — n'envoie que ceux que tu veux changer. Attention : changer is_free ou monthly_price_eur impacte les futurs paiements. Demande confirmation user.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
name: { type: 'string', maxLength: 255 },
|
|
11
|
+
description: { type: 'string' },
|
|
12
|
+
full_description: { type: 'string' },
|
|
13
|
+
is_free: { type: 'boolean' },
|
|
14
|
+
monthly_price_eur: { type: 'number', minimum: 0 },
|
|
15
|
+
trial_period_days: { type: 'number', minimum: 0 },
|
|
16
|
+
trial_enabled: { type: 'boolean' },
|
|
17
|
+
affiliation_enabled: { type: 'boolean' },
|
|
18
|
+
affiliation_percent: { type: 'number', minimum: 0, maximum: 100 },
|
|
19
|
+
},
|
|
20
|
+
required: ['lab'],
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
zodSchema: z.object({
|
|
24
|
+
lab: z.string(),
|
|
25
|
+
name: z.string().max(255).optional(),
|
|
26
|
+
description: z.string().optional(),
|
|
27
|
+
full_description: z.string().optional(),
|
|
28
|
+
is_free: z.boolean().optional(),
|
|
29
|
+
monthly_price_eur: z.number().min(0).optional(),
|
|
30
|
+
trial_period_days: z.number().int().min(0).optional(),
|
|
31
|
+
trial_enabled: z.boolean().optional(),
|
|
32
|
+
affiliation_enabled: z.boolean().optional(),
|
|
33
|
+
affiliation_percent: z.number().int().min(0).max(100).optional(),
|
|
34
|
+
}),
|
|
35
|
+
async handler(args) {
|
|
36
|
+
const parsed = this.zodSchema.parse(args);
|
|
37
|
+
const { lab, ...body } = parsed;
|
|
38
|
+
try {
|
|
39
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/settings`, body);
|
|
40
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateLevelTool = {
|
|
4
|
+
name: 'update_level',
|
|
5
|
+
description: "Renomme un niveau XP ou modifie le seuil de points requis pour l'atteindre. Champs optionnels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
level_id: { type: 'number' },
|
|
11
|
+
name: { type: 'string', maxLength: 255 },
|
|
12
|
+
points_threshold: { type: 'number', minimum: 0 },
|
|
13
|
+
},
|
|
14
|
+
required: ['lab', 'level_id'],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
},
|
|
17
|
+
zodSchema: z.object({
|
|
18
|
+
lab: z.string(),
|
|
19
|
+
level_id: z.number().int().positive(),
|
|
20
|
+
name: z.string().max(255).optional(),
|
|
21
|
+
points_threshold: z.number().int().min(0).optional(),
|
|
22
|
+
}),
|
|
23
|
+
async handler(args) {
|
|
24
|
+
const parsed = this.zodSchema.parse(args);
|
|
25
|
+
const { lab, level_id, ...body } = parsed;
|
|
26
|
+
try {
|
|
27
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/levels/${level_id}`, 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,40 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updatePodcastEpisodeTool = {
|
|
4
|
+
name: 'update_podcast_episode',
|
|
5
|
+
description: "Met a jour un episode podcast (titre, description, access, season). Champs optionnels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
show_id: { type: 'number' },
|
|
11
|
+
episode_id: { type: 'number' },
|
|
12
|
+
title: { type: 'string', maxLength: 255 },
|
|
13
|
+
description: { type: 'string' },
|
|
14
|
+
access: { type: 'string', enum: ['free', 'premium'] },
|
|
15
|
+
season: { type: 'number', minimum: 1 },
|
|
16
|
+
},
|
|
17
|
+
required: ['lab', 'show_id', 'episode_id'],
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
zodSchema: z.object({
|
|
21
|
+
lab: z.string(),
|
|
22
|
+
show_id: z.number().int().positive(),
|
|
23
|
+
episode_id: z.number().int().positive(),
|
|
24
|
+
title: z.string().max(255).optional(),
|
|
25
|
+
description: z.string().nullable().optional(),
|
|
26
|
+
access: z.enum(['free', 'premium']).optional(),
|
|
27
|
+
season: z.number().int().min(1).optional(),
|
|
28
|
+
}),
|
|
29
|
+
async handler(args) {
|
|
30
|
+
const p = this.zodSchema.parse(args);
|
|
31
|
+
const { lab, show_id, episode_id, ...body } = p;
|
|
32
|
+
try {
|
|
33
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/podcast/shows/${show_id}/episodes/${episode_id}`, body);
|
|
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,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updatePostTool = {
|
|
4
|
+
name: 'update_post',
|
|
5
|
+
description: "Modifie un post existant (titre / corps / categorie). Champs optionnels : n'envoie que ce que tu veux changer. IMPORTANT : action ecriture, demander confirmation.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
post_id: { type: 'number' },
|
|
11
|
+
title: { type: 'string', maxLength: 255 },
|
|
12
|
+
body: { type: 'string' },
|
|
13
|
+
category_id: { type: 'number' },
|
|
14
|
+
},
|
|
15
|
+
required: ['lab', 'post_id'],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
zodSchema: z.object({
|
|
19
|
+
lab: z.string(),
|
|
20
|
+
post_id: z.number().int().positive(),
|
|
21
|
+
title: z.string().max(255).optional(),
|
|
22
|
+
body: z.string().optional(),
|
|
23
|
+
category_id: z.number().int().positive().optional(),
|
|
24
|
+
}),
|
|
25
|
+
async handler(args) {
|
|
26
|
+
const parsed = this.zodSchema.parse(args);
|
|
27
|
+
const { lab, post_id, ...body } = parsed;
|
|
28
|
+
try {
|
|
29
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/posts/${post_id}`, body);
|
|
30
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateShopProductTool = {
|
|
4
|
+
name: 'update_shop_product',
|
|
5
|
+
description: "Modifie un produit boutique (titre, prix, description, publication). Champs optionnels. Prix en centimes.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
shop_id: { type: 'number' },
|
|
11
|
+
title: { type: 'string', maxLength: 255 },
|
|
12
|
+
short_description: { type: 'string' },
|
|
13
|
+
description: { type: 'string' },
|
|
14
|
+
price_cents: { type: 'number', minimum: 0 },
|
|
15
|
+
payment_mode: { type: 'string', enum: ['external', 'stripe'] },
|
|
16
|
+
payment_link_text: { type: 'string', maxLength: 255 },
|
|
17
|
+
support_email: { type: 'string', format: 'email' },
|
|
18
|
+
is_published: { type: 'boolean' },
|
|
19
|
+
},
|
|
20
|
+
required: ['lab', 'shop_id'],
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
zodSchema: z.object({
|
|
24
|
+
lab: z.string(),
|
|
25
|
+
shop_id: z.number().int().positive(),
|
|
26
|
+
title: z.string().max(255).optional(),
|
|
27
|
+
short_description: z.string().optional(),
|
|
28
|
+
description: z.string().optional(),
|
|
29
|
+
price_cents: z.number().int().min(0).nullable().optional(),
|
|
30
|
+
payment_mode: z.enum(['external', 'stripe']).optional(),
|
|
31
|
+
payment_link_text: z.string().max(255).nullable().optional(),
|
|
32
|
+
support_email: z.string().email().nullable().optional(),
|
|
33
|
+
is_published: z.boolean().optional(),
|
|
34
|
+
}),
|
|
35
|
+
async handler(args) {
|
|
36
|
+
const p = this.zodSchema.parse(args);
|
|
37
|
+
const { lab, shop_id, ...body } = p;
|
|
38
|
+
try {
|
|
39
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(lab)}/shops/${shop_id}`, body);
|
|
40
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return { isError: true, content: [{ type: 'text', text: formatApiError(err) }] };
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { http, formatApiError } from '../http.js';
|
|
3
|
+
export const updateSlugTool = {
|
|
4
|
+
name: 'update_slug',
|
|
5
|
+
description: "Change l'URL (slug) publique du Lab. Cooldown 30j entre 2 changements. IMPORTANT : les anciennes URLs partagees ne fonctionneront plus.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
lab: { type: 'string' },
|
|
10
|
+
new_slug: { type: 'string', pattern: '^[a-zA-Z0-9_-]+$', description: 'Nouveau slug (alphanumeric + tirets/underscores)' },
|
|
11
|
+
},
|
|
12
|
+
required: ['lab', 'new_slug'],
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
zodSchema: z.object({
|
|
16
|
+
lab: z.string(),
|
|
17
|
+
new_slug: z.string().max(255).regex(/^[a-zA-Z0-9_-]+$/),
|
|
18
|
+
}),
|
|
19
|
+
async handler(args) {
|
|
20
|
+
const p = this.zodSchema.parse(args);
|
|
21
|
+
try {
|
|
22
|
+
const { data } = await http.put(`/mcp/labs/${encodeURIComponent(p.lab)}/slug`, { new_slug: p.new_slug });
|
|
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
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@connect-xlab/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Serveur MCP pour piloter ton Lab ConnectXLab depuis Claude Desktop / Cursor / n'importe quel client MCP.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": { "connectxlab-mcp": "dist/index.js" },
|
|
8
|
+
"files": ["dist"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsx watch src/index.ts",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"engines": { "node": ">=20" },
|
|
16
|
+
"keywords": ["mcp", "model-context-protocol", "connectxlab", "claude"],
|
|
17
|
+
"author": "ConnectXLab",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
21
|
+
"axios": "^1.7.0",
|
|
22
|
+
"zod": "^3.23.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^22.0.0",
|
|
26
|
+
"tsx": "^4.19.0",
|
|
27
|
+
"typescript": "^5.5.0"
|
|
28
|
+
}
|
|
29
|
+
}
|