@lyrra/mcp-server 1.0.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/README.md +214 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +92 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/block-types.d.ts +318 -0
- package/dist/resources/block-types.d.ts.map +1 -0
- package/dist/resources/block-types.js +297 -0
- package/dist/resources/block-types.js.map +1 -0
- package/dist/resources/flow-schema.d.ts +147 -0
- package/dist/resources/flow-schema.d.ts.map +1 -0
- package/dist/resources/flow-schema.js +143 -0
- package/dist/resources/flow-schema.js.map +1 -0
- package/dist/tools/admin.d.ts +133 -0
- package/dist/tools/admin.d.ts.map +1 -0
- package/dist/tools/admin.js +114 -0
- package/dist/tools/admin.js.map +1 -0
- package/dist/tools/ai-designer.d.ts +149 -0
- package/dist/tools/ai-designer.d.ts.map +1 -0
- package/dist/tools/ai-designer.js +85 -0
- package/dist/tools/ai-designer.js.map +1 -0
- package/dist/tools/analytics.d.ts +48 -0
- package/dist/tools/analytics.d.ts.map +1 -0
- package/dist/tools/analytics.js +40 -0
- package/dist/tools/analytics.js.map +1 -0
- package/dist/tools/auth.d.ts +31 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +32 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/blocks.d.ts +201 -0
- package/dist/tools/blocks.d.ts.map +1 -0
- package/dist/tools/blocks.js +163 -0
- package/dist/tools/blocks.js.map +1 -0
- package/dist/tools/connections.d.ts +87 -0
- package/dist/tools/connections.d.ts.map +1 -0
- package/dist/tools/connections.js +77 -0
- package/dist/tools/connections.js.map +1 -0
- package/dist/tools/eduflow.d.ts +186 -0
- package/dist/tools/eduflow.d.ts.map +1 -0
- package/dist/tools/eduflow.js +104 -0
- package/dist/tools/eduflow.js.map +1 -0
- package/dist/tools/participants.d.ts +111 -0
- package/dist/tools/participants.d.ts.map +1 -0
- package/dist/tools/participants.js +66 -0
- package/dist/tools/participants.js.map +1 -0
- package/dist/tools/presentation.d.ts +117 -0
- package/dist/tools/presentation.d.ts.map +1 -0
- package/dist/tools/presentation.js +53 -0
- package/dist/tools/presentation.js.map +1 -0
- package/dist/tools/projects.d.ts +66 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +51 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/resources.d.ts +47 -0
- package/dist/tools/resources.d.ts.map +1 -0
- package/dist/tools/resources.js +33 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/store.d.ts +63 -0
- package/dist/tools/store.d.ts.map +1 -0
- package/dist/tools/store.js +62 -0
- package/dist/tools/store.js.map +1 -0
- package/mcp-config.example.json +15 -0
- package/package.json +24 -0
- package/src/client.ts +99 -0
- package/src/config.ts +6 -0
- package/src/index.ts +112 -0
- package/src/resources/block-types.ts +298 -0
- package/src/resources/flow-schema.ts +148 -0
- package/src/tools/admin.ts +122 -0
- package/src/tools/ai-designer.ts +91 -0
- package/src/tools/analytics.ts +43 -0
- package/src/tools/auth.ts +33 -0
- package/src/tools/blocks.ts +174 -0
- package/src/tools/connections.ts +77 -0
- package/src/tools/eduflow.ts +112 -0
- package/src/tools/participants.ts +71 -0
- package/src/tools/presentation.ts +55 -0
- package/src/tools/projects.ts +55 -0
- package/src/tools/resources.ts +35 -0
- package/src/tools/store.ts +61 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# LYRRA Studio MCP Server
|
|
2
|
+
|
|
3
|
+
Serveur MCP (Model Context Protocol) pour piloter **LYRRA Studio** depuis un outil IA externe (Claude Desktop, Cursor, Copilot CLI, etc.).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd backend/mcp-server
|
|
9
|
+
npm install
|
|
10
|
+
npm run build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
### 1. Obtenir vos identifiants
|
|
16
|
+
|
|
17
|
+
Connectez-vous à LYRRA Studio → Dashboard Entreprise → Serveur MCP → Onglet "Identifiants" → Créer un nouveau client.
|
|
18
|
+
|
|
19
|
+
Vous obtiendrez un **Client ID** et un **Client Secret** (affiché une seule fois).
|
|
20
|
+
|
|
21
|
+
### 2. Configurer Claude Desktop
|
|
22
|
+
|
|
23
|
+
Ajoutez dans `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) :
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"lyrra-studio": {
|
|
29
|
+
"command": "node",
|
|
30
|
+
"args": ["/chemin/vers/backend/mcp-server/dist/index.js"],
|
|
31
|
+
"env": {
|
|
32
|
+
"LYRRA_CLIENT_ID": "votre_client_id",
|
|
33
|
+
"LYRRA_CLIENT_SECRET": "rak_votre_client_secret",
|
|
34
|
+
"LYRRA_API_URL": "https://lyrrastudio.com/api",
|
|
35
|
+
"LYRRA_EDUFLOW_API_URL": "https://lyrrastudio.com/eduflow"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Configurer Cursor
|
|
43
|
+
|
|
44
|
+
Ajoutez dans `.cursor/mcp.json` :
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"lyrra-studio": {
|
|
50
|
+
"command": "node",
|
|
51
|
+
"args": ["backend/mcp-server/dist/index.js"],
|
|
52
|
+
"env": {
|
|
53
|
+
"LYRRA_CLIENT_ID": "votre_client_id",
|
|
54
|
+
"LYRRA_CLIENT_SECRET": "rak_votre_client_secret",
|
|
55
|
+
"LYRRA_API_URL": "https://lyrrastudio.com/api",
|
|
56
|
+
"LYRRA_EDUFLOW_API_URL": "https://lyrrastudio.com/eduflow"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Variables d'environnement
|
|
64
|
+
|
|
65
|
+
| Variable | Défaut | Description |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `LYRRA_CLIENT_ID` | - | Client ID (nom du client) |
|
|
68
|
+
| `LYRRA_CLIENT_SECRET` | - | Client Secret (clé secrète, préfixe `rak_`) |
|
|
69
|
+
| `LYRRA_API_URL` | `http://localhost:3001/api` | URL de l'API REST |
|
|
70
|
+
| `LYRRA_EDUFLOW_API_URL` | `http://localhost:3001/eduflow` | URL de l'API EduFlow |
|
|
71
|
+
|
|
72
|
+
## Tools disponibles (57)
|
|
73
|
+
|
|
74
|
+
### 🔐 Authentification
|
|
75
|
+
| Tool | Description |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `auth_login` | Se connecter avec email/mot de passe |
|
|
78
|
+
| `auth_get_profile` | Profil utilisateur connecté |
|
|
79
|
+
| `auth_list_api_keys` | Lister les clés API |
|
|
80
|
+
|
|
81
|
+
### 📚 Parcours EduFlow
|
|
82
|
+
| Tool | Description |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `eduflow_list` | Lister tous les parcours |
|
|
85
|
+
| `eduflow_get` | Détails d'un parcours |
|
|
86
|
+
| `eduflow_create` | Créer un parcours |
|
|
87
|
+
| `eduflow_update` | Mettre à jour un parcours |
|
|
88
|
+
| `eduflow_delete` | Supprimer un parcours |
|
|
89
|
+
| `eduflow_duplicate` | Dupliquer un parcours |
|
|
90
|
+
| `eduflow_change_status` | Changer le statut (draft/published/archived) |
|
|
91
|
+
| `eduflow_export` | Exporter un parcours |
|
|
92
|
+
| `eduflow_get_public` | Infos publiques d'un parcours |
|
|
93
|
+
|
|
94
|
+
### 🧱 Blocs
|
|
95
|
+
| Tool | Description |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `block_list_types` | Documentation des 29 types de blocs |
|
|
98
|
+
| `block_get` | Détails d'un bloc |
|
|
99
|
+
| `block_create` | Créer un bloc |
|
|
100
|
+
| `block_update` | Mettre à jour un bloc |
|
|
101
|
+
| `block_batch_update` | Mise à jour en lot |
|
|
102
|
+
| `block_delete` | Supprimer un bloc |
|
|
103
|
+
| `block_generate_tts` | Générer audio TTS |
|
|
104
|
+
|
|
105
|
+
### 🔗 Connexions
|
|
106
|
+
| Tool | Description |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `connection_list` | Lister les connexions |
|
|
109
|
+
| `connection_add` | Ajouter une connexion |
|
|
110
|
+
| `connection_remove` | Supprimer une connexion |
|
|
111
|
+
|
|
112
|
+
### 👥 Participants
|
|
113
|
+
| Tool | Description |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `participant_list` | Lister les participants |
|
|
116
|
+
| `participant_add` | Ajouter des participants |
|
|
117
|
+
| `participant_remove` | Retirer un participant |
|
|
118
|
+
| `participant_get_progress` | Progression d'un participant |
|
|
119
|
+
| `participant_get_overview` | Vue d'ensemble participant |
|
|
120
|
+
| `participant_get_flow_stats` | Stats de tous les participants |
|
|
121
|
+
|
|
122
|
+
### 📊 Analytics
|
|
123
|
+
| Tool | Description |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `analytics_overview` | Dashboard global |
|
|
126
|
+
| `analytics_flow_learners` | Stats apprenants par parcours |
|
|
127
|
+
| `analytics_flow_dashboard` | Dashboard analytics parcours |
|
|
128
|
+
| `analytics_my_stats` | Mes statistiques |
|
|
129
|
+
|
|
130
|
+
### 🤖 AI Designer
|
|
131
|
+
| Tool | Description |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `ai_generate_plan` | Générer un plan de parcours |
|
|
134
|
+
| `ai_generate_block` | Générer le contenu d'un bloc |
|
|
135
|
+
| `ai_generate_presentation` | Générer la page de présentation |
|
|
136
|
+
| `ai_generate_objectives` | Générer les objectifs pédagogiques |
|
|
137
|
+
| `ai_save_objectives` | Sauvegarder les objectifs |
|
|
138
|
+
| `ai_chat_message` | Discuter avec le designer IA |
|
|
139
|
+
| `ai_get_conversation` | Historique de conversation IA |
|
|
140
|
+
|
|
141
|
+
### 🎭 Présentation
|
|
142
|
+
| Tool | Description |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `presentation_get` | Page de présentation |
|
|
145
|
+
| `presentation_update` | Mettre à jour la présentation |
|
|
146
|
+
| `presentation_toggle` | Activer/désactiver |
|
|
147
|
+
|
|
148
|
+
### 🏪 Store
|
|
149
|
+
| Tool | Description |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `store_list_audiobooks` | Lister les audiobooks |
|
|
152
|
+
| `store_get_audiobook` | Détails d'un audiobook |
|
|
153
|
+
| `store_list_authors` | Auteurs en vedette |
|
|
154
|
+
| `store_my_library` | Ma bibliothèque |
|
|
155
|
+
| `store_search` | Rechercher dans le store |
|
|
156
|
+
|
|
157
|
+
### 🎵 Projets Audio
|
|
158
|
+
| Tool | Description |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `project_list` | Lister mes projets |
|
|
161
|
+
| `project_get` | Détails d'un projet |
|
|
162
|
+
| `project_create` | Créer un projet |
|
|
163
|
+
| `project_update` | Mettre à jour un projet |
|
|
164
|
+
| `project_delete` | Supprimer un projet |
|
|
165
|
+
|
|
166
|
+
### 📁 Ressources
|
|
167
|
+
| Tool | Description |
|
|
168
|
+
|---|---|
|
|
169
|
+
| `resource_list` | Lister les ressources |
|
|
170
|
+
| `resource_delete` | Supprimer une ressource |
|
|
171
|
+
| `resource_list_categories` | Catégories disponibles |
|
|
172
|
+
|
|
173
|
+
### 🔧 Versions, Gamification & Webhooks
|
|
174
|
+
| Tool | Description |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `version_list` | Versions d'un parcours |
|
|
177
|
+
| `version_create` | Créer une version |
|
|
178
|
+
| `version_activate` | Activer une version |
|
|
179
|
+
| `gamification_stats` | Stats de gamification |
|
|
180
|
+
| `gamification_objectives` | Objectifs à atteindre |
|
|
181
|
+
| `activity_history` | Historique d'activité |
|
|
182
|
+
| `activity_stats` | Stats d'utilisation |
|
|
183
|
+
| `webhook_list` | Lister les webhooks |
|
|
184
|
+
| `webhook_create` | Créer un webhook |
|
|
185
|
+
| `webhook_delete` | Supprimer un webhook |
|
|
186
|
+
| `webhook_test` | Tester un webhook |
|
|
187
|
+
|
|
188
|
+
## Resources MCP
|
|
189
|
+
|
|
190
|
+
| URI | Description |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `lyrra://block-types` | Documentation complète des 29 types de blocs |
|
|
193
|
+
| `lyrra://flow-construction-guide` | Guide de construction de parcours |
|
|
194
|
+
|
|
195
|
+
## Exemples d'utilisation avec Claude
|
|
196
|
+
|
|
197
|
+
### Créer un parcours complet
|
|
198
|
+
> "Crée un parcours EduFlow sur les fractions pour des élèves de CM2, avec 3 leçons en texte, un quiz après chaque leçon, et un certificat de réussite à la fin."
|
|
199
|
+
|
|
200
|
+
### Analyser les statistiques
|
|
201
|
+
> "Montre-moi les statistiques de mon parcours 'Introduction au Python'. Quels sont les blocs où les étudiants passent le plus de temps ?"
|
|
202
|
+
|
|
203
|
+
### Modifier un parcours existant
|
|
204
|
+
> "Dans mon parcours sur la photosynthèse, ajoute un bloc vidéo après le texte d'introduction et connecte-le au quiz."
|
|
205
|
+
|
|
206
|
+
## Développement
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Lancer en mode développement
|
|
210
|
+
npm run dev
|
|
211
|
+
|
|
212
|
+
# Rebuild après modifications
|
|
213
|
+
npm run build
|
|
214
|
+
```
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class LyrraClient {
|
|
2
|
+
private apiUrl;
|
|
3
|
+
private eduflowUrl;
|
|
4
|
+
private clientId;
|
|
5
|
+
private clientSecret;
|
|
6
|
+
private jwtToken;
|
|
7
|
+
constructor();
|
|
8
|
+
private get headers();
|
|
9
|
+
setToken(token: string): void;
|
|
10
|
+
get(path: string, base?: 'api' | 'eduflow'): Promise<any>;
|
|
11
|
+
post(path: string, data?: any, base?: 'api' | 'eduflow'): Promise<any>;
|
|
12
|
+
put(path: string, data?: any, base?: 'api' | 'eduflow'): Promise<any>;
|
|
13
|
+
patch(path: string, data?: any, base?: 'api' | 'eduflow'): Promise<any>;
|
|
14
|
+
delete(path: string, base?: 'api' | 'eduflow'): Promise<any>;
|
|
15
|
+
}
|
|
16
|
+
export declare const client: LyrraClient;
|
|
17
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAuB;;IASvC,OAAO,KAAK,OAAO,GAMlB;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAIhB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAUhE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAe7E,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAe5E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAe9E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;CAa1E;AAED,eAAO,MAAM,MAAM,aAAoB,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { config } from './config.js';
|
|
2
|
+
export class LyrraClient {
|
|
3
|
+
apiUrl;
|
|
4
|
+
eduflowUrl;
|
|
5
|
+
clientId;
|
|
6
|
+
clientSecret;
|
|
7
|
+
jwtToken = null;
|
|
8
|
+
constructor() {
|
|
9
|
+
this.apiUrl = config.apiUrl;
|
|
10
|
+
this.eduflowUrl = config.eduflowApiUrl;
|
|
11
|
+
this.clientId = config.clientId;
|
|
12
|
+
this.clientSecret = config.clientSecret;
|
|
13
|
+
}
|
|
14
|
+
get headers() {
|
|
15
|
+
const h = { 'Content-Type': 'application/json' };
|
|
16
|
+
// Client Secret is the API key used for X-API-Key header authentication
|
|
17
|
+
if (this.clientSecret)
|
|
18
|
+
h['X-API-Key'] = this.clientSecret;
|
|
19
|
+
if (this.jwtToken)
|
|
20
|
+
h['Authorization'] = `Bearer ${this.jwtToken}`;
|
|
21
|
+
return h;
|
|
22
|
+
}
|
|
23
|
+
setToken(token) {
|
|
24
|
+
this.jwtToken = token;
|
|
25
|
+
}
|
|
26
|
+
async get(path, base = 'api') {
|
|
27
|
+
const url = `${base === 'eduflow' ? this.eduflowUrl : this.apiUrl}${path}`;
|
|
28
|
+
const res = await fetch(url, { headers: this.headers });
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
const body = await res.text();
|
|
31
|
+
throw new Error(`GET ${path} failed (${res.status}): ${body}`);
|
|
32
|
+
}
|
|
33
|
+
return res.json();
|
|
34
|
+
}
|
|
35
|
+
async post(path, data, base = 'api') {
|
|
36
|
+
const url = `${base === 'eduflow' ? this.eduflowUrl : this.apiUrl}${path}`;
|
|
37
|
+
const res = await fetch(url, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: this.headers,
|
|
40
|
+
body: data ? JSON.stringify(data) : undefined,
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const body = await res.text();
|
|
44
|
+
throw new Error(`POST ${path} failed (${res.status}): ${body}`);
|
|
45
|
+
}
|
|
46
|
+
const text = await res.text();
|
|
47
|
+
return text ? JSON.parse(text) : {};
|
|
48
|
+
}
|
|
49
|
+
async put(path, data, base = 'api') {
|
|
50
|
+
const url = `${base === 'eduflow' ? this.eduflowUrl : this.apiUrl}${path}`;
|
|
51
|
+
const res = await fetch(url, {
|
|
52
|
+
method: 'PUT',
|
|
53
|
+
headers: this.headers,
|
|
54
|
+
body: data ? JSON.stringify(data) : undefined,
|
|
55
|
+
});
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
const body = await res.text();
|
|
58
|
+
throw new Error(`PUT ${path} failed (${res.status}): ${body}`);
|
|
59
|
+
}
|
|
60
|
+
const text = await res.text();
|
|
61
|
+
return text ? JSON.parse(text) : {};
|
|
62
|
+
}
|
|
63
|
+
async patch(path, data, base = 'api') {
|
|
64
|
+
const url = `${base === 'eduflow' ? this.eduflowUrl : this.apiUrl}${path}`;
|
|
65
|
+
const res = await fetch(url, {
|
|
66
|
+
method: 'PATCH',
|
|
67
|
+
headers: this.headers,
|
|
68
|
+
body: data ? JSON.stringify(data) : undefined,
|
|
69
|
+
});
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
const body = await res.text();
|
|
72
|
+
throw new Error(`PATCH ${path} failed (${res.status}): ${body}`);
|
|
73
|
+
}
|
|
74
|
+
const text = await res.text();
|
|
75
|
+
return text ? JSON.parse(text) : {};
|
|
76
|
+
}
|
|
77
|
+
async delete(path, base = 'api') {
|
|
78
|
+
const url = `${base === 'eduflow' ? this.eduflowUrl : this.apiUrl}${path}`;
|
|
79
|
+
const res = await fetch(url, {
|
|
80
|
+
method: 'DELETE',
|
|
81
|
+
headers: this.headers,
|
|
82
|
+
});
|
|
83
|
+
if (!res.ok) {
|
|
84
|
+
const body = await res.text();
|
|
85
|
+
throw new Error(`DELETE ${path} failed (${res.status}): ${body}`);
|
|
86
|
+
}
|
|
87
|
+
const text = await res.text();
|
|
88
|
+
return text ? JSON.parse(text) : {};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export const client = new LyrraClient();
|
|
92
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;CAKlB,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const config = {
|
|
2
|
+
apiUrl: process.env.LYRRA_API_URL || 'http://localhost:3001/api',
|
|
3
|
+
clientId: process.env.LYRRA_CLIENT_ID || '',
|
|
4
|
+
clientSecret: process.env.LYRRA_CLIENT_SECRET || '',
|
|
5
|
+
eduflowApiUrl: process.env.LYRRA_EDUFLOW_API_URL || 'http://localhost:3001/eduflow',
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,2BAA2B;IAChE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;IAC3C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE;IACnD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,+BAA+B;CACpF,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { config } from './config.js';
|
|
5
|
+
// Tools
|
|
6
|
+
import { authTools } from './tools/auth.js';
|
|
7
|
+
import { eduflowTools } from './tools/eduflow.js';
|
|
8
|
+
import { blocksTools } from './tools/blocks.js';
|
|
9
|
+
import { connectionsTools } from './tools/connections.js';
|
|
10
|
+
import { participantsTools } from './tools/participants.js';
|
|
11
|
+
import { analyticsTools } from './tools/analytics.js';
|
|
12
|
+
import { aiDesignerTools } from './tools/ai-designer.js';
|
|
13
|
+
import { presentationTools } from './tools/presentation.js';
|
|
14
|
+
import { storeTools } from './tools/store.js';
|
|
15
|
+
import { projectsTools } from './tools/projects.js';
|
|
16
|
+
import { resourcesTools } from './tools/resources.js';
|
|
17
|
+
import { adminTools } from './tools/admin.js';
|
|
18
|
+
// Resources
|
|
19
|
+
import { BLOCK_TYPES_RESOURCE } from './resources/block-types.js';
|
|
20
|
+
import { FLOW_SCHEMA_RESOURCE } from './resources/flow-schema.js';
|
|
21
|
+
const server = new McpServer({
|
|
22
|
+
name: 'lyrra-studio',
|
|
23
|
+
version: '1.0.0',
|
|
24
|
+
description: 'Serveur MCP pour piloter LYRRA Studio - Plateforme EdTech de création de parcours pédagogiques, conversion PDF→Audio, et store d\'audiobooks.',
|
|
25
|
+
});
|
|
26
|
+
// --- Register all tools ---
|
|
27
|
+
const allTools = {
|
|
28
|
+
...authTools,
|
|
29
|
+
...eduflowTools,
|
|
30
|
+
...blocksTools,
|
|
31
|
+
...connectionsTools,
|
|
32
|
+
...participantsTools,
|
|
33
|
+
...analyticsTools,
|
|
34
|
+
...aiDesignerTools,
|
|
35
|
+
...presentationTools,
|
|
36
|
+
...storeTools,
|
|
37
|
+
...projectsTools,
|
|
38
|
+
...resourcesTools,
|
|
39
|
+
...adminTools,
|
|
40
|
+
};
|
|
41
|
+
for (const [name, tool] of Object.entries(allTools)) {
|
|
42
|
+
server.tool(name, tool.description, tool.inputSchema.shape ? Object.fromEntries(Object.entries(tool.inputSchema.shape).map(([key, schema]) => [key, schema])) : {}, async (args) => {
|
|
43
|
+
try {
|
|
44
|
+
const result = await tool.handler(args);
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: 'text', text: `Erreur: ${error.message}` }],
|
|
52
|
+
isError: true,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// --- Register resources ---
|
|
58
|
+
server.resource('block-types', BLOCK_TYPES_RESOURCE.uri, { description: BLOCK_TYPES_RESOURCE.description, mimeType: BLOCK_TYPES_RESOURCE.mimeType }, async () => ({
|
|
59
|
+
contents: [{
|
|
60
|
+
uri: BLOCK_TYPES_RESOURCE.uri,
|
|
61
|
+
mimeType: BLOCK_TYPES_RESOURCE.mimeType,
|
|
62
|
+
text: JSON.stringify(BLOCK_TYPES_RESOURCE.content, null, 2),
|
|
63
|
+
}],
|
|
64
|
+
}));
|
|
65
|
+
server.resource('flow-construction-guide', FLOW_SCHEMA_RESOURCE.uri, { description: FLOW_SCHEMA_RESOURCE.description, mimeType: FLOW_SCHEMA_RESOURCE.mimeType }, async () => ({
|
|
66
|
+
contents: [{
|
|
67
|
+
uri: FLOW_SCHEMA_RESOURCE.uri,
|
|
68
|
+
mimeType: FLOW_SCHEMA_RESOURCE.mimeType,
|
|
69
|
+
text: JSON.stringify(FLOW_SCHEMA_RESOURCE.content, null, 2),
|
|
70
|
+
}],
|
|
71
|
+
}));
|
|
72
|
+
// --- Start server ---
|
|
73
|
+
async function main() {
|
|
74
|
+
if (!config.clientSecret && !process.env.LYRRA_CLIENT_SECRET) {
|
|
75
|
+
console.error('⚠️ LYRRA_CLIENT_SECRET non défini. Utilisez auth_login ou définissez les variables d\'environnement LYRRA_CLIENT_ID et LYRRA_CLIENT_SECRET.');
|
|
76
|
+
}
|
|
77
|
+
const transport = new StdioServerTransport();
|
|
78
|
+
await server.connect(transport);
|
|
79
|
+
}
|
|
80
|
+
main().catch((error) => {
|
|
81
|
+
console.error('Erreur fatale:', error);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|