@supersoniks/concorde 3.3.2 → 3.3.3

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.
@@ -1,859 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Serveur MCP pour Concorde - Framework de composants Web
5
- * Version Node.js
6
- * Permet à l'IA de Cursor d'accéder facilement à toute la documentation et au code de Concorde
7
- */
8
-
9
- import { promises as fs } from 'fs';
10
- import path from 'path';
11
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
- import {
14
- CallToolRequestSchema,
15
- ListResourcesRequestSchema,
16
- ListToolsRequestSchema,
17
- ReadResourceRequestSchema,
18
- } from '@modelcontextprotocol/sdk/types.js';
19
-
20
- // Configuration du projet Concorde
21
- const CONCORDE_ROOT = path.dirname(path.dirname(new URL(import.meta.url).pathname));
22
- const SRC_PATH = path.join(CONCORDE_ROOT, 'src');
23
- const DOCS_PATH = path.join(CONCORDE_ROOT, 'docs');
24
- const CORE_PATH = path.join(SRC_PATH, 'core');
25
- const COMPONENTS_PATH = path.join(CORE_PATH, 'components');
26
-
27
- class ComponentInfo {
28
- constructor(name, tagName, category, filePath, docPath, description, props, examples) {
29
- this.name = name;
30
- this.tagName = tagName;
31
- this.category = category;
32
- this.filePath = filePath;
33
- this.docPath = docPath;
34
- this.description = description;
35
- this.props = props;
36
- this.examples = examples;
37
- }
38
- }
39
-
40
- class ConcordeMCPServer {
41
- constructor() {
42
- this.server = new Server(
43
- {
44
- name: 'concorde-mcp',
45
- version: '1.0.0',
46
- },
47
- {
48
- capabilities: {
49
- resources: {},
50
- tools: {},
51
- },
52
- }
53
- );
54
-
55
- this.components = new Map();
56
- this.documentation = new Map();
57
-
58
- this.setupHandlers();
59
- }
60
-
61
- async initialize() {
62
- await this.loadComponents();
63
- await this.loadDocumentation();
64
- }
65
-
66
- setupHandlers() {
67
- // Handler pour lister les ressources
68
- this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
69
- const resources = [];
70
-
71
- // Ressources de composants
72
- for (const [compName, compInfo] of this.components) {
73
- resources.push({
74
- uri: `concorde://component/${compName}`,
75
- name: `Composant ${compName}`,
76
- description: compInfo.description,
77
- mimeType: 'text/markdown'
78
- });
79
- }
80
-
81
- // Ressources de documentation
82
- for (const [docName, docContent] of this.documentation) {
83
- resources.push({
84
- uri: `concorde://docs/${docName}`,
85
- name: `Documentation ${docName}`,
86
- description: `Documentation Concorde: ${docName}`,
87
- mimeType: 'text/markdown'
88
- });
89
- }
90
-
91
- // Ressources d'exemples
92
- resources.push({
93
- uri: 'concorde://examples/ui-components',
94
- name: 'Exemples composants UI',
95
- description: 'Exemples d\'utilisation des composants UI',
96
- mimeType: 'text/markdown'
97
- });
98
-
99
- resources.push({
100
- uri: 'concorde://examples/functional-components',
101
- name: 'Exemples composants fonctionnels',
102
- description: 'Exemples d\'utilisation des composants fonctionnels',
103
- mimeType: 'text/markdown'
104
- });
105
-
106
- return { resources };
107
- });
108
-
109
- // Handler pour lire les ressources
110
- this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
111
- const { uri } = request.params;
112
-
113
- if (uri.startsWith('concorde://component/')) {
114
- const compName = uri.replace('concorde://component/', '');
115
- if (this.components.has(compName)) {
116
- const compInfo = this.components.get(compName);
117
- const content = this.generateComponentDoc(compInfo);
118
- return {
119
- contents: [{
120
- type: 'text',
121
- text: content
122
- }]
123
- };
124
- }
125
- }
126
-
127
- if (uri.startsWith('concorde://docs/')) {
128
- const docName = uri.replace('concorde://docs/', '');
129
- if (this.documentation.has(docName)) {
130
- return {
131
- contents: [{
132
- type: 'text',
133
- text: this.documentation.get(docName)
134
- }]
135
- };
136
- }
137
- }
138
-
139
- if (uri === 'concorde://examples/ui-components') {
140
- const content = this.generateUIExamples();
141
- return {
142
- contents: [{
143
- type: 'text',
144
- text: content
145
- }]
146
- };
147
- }
148
-
149
- if (uri === 'concorde://examples/functional-components') {
150
- const content = this.generateFunctionalExamples();
151
- return {
152
- contents: [{
153
- type: 'text',
154
- text: content
155
- }]
156
- };
157
- }
158
-
159
- return {
160
- contents: [{
161
- type: 'text',
162
- text: 'Ressource non trouvée'
163
- }]
164
- };
165
- });
166
-
167
- // Handler pour lister les outils
168
- this.server.setRequestHandler(ListToolsRequestSchema, async () => {
169
- const tools = [
170
- {
171
- name: 'search_component',
172
- description: 'Recherche un composant Concorde par nom ou fonctionnalité',
173
- inputSchema: {
174
- type: 'object',
175
- properties: {
176
- query: {
177
- type: 'string',
178
- description: 'Terme de recherche (nom du composant, fonctionnalité, etc.)'
179
- }
180
- },
181
- required: ['query']
182
- }
183
- },
184
- {
185
- name: 'get_component_info',
186
- description: 'Obtient des informations détaillées sur un composant spécifique',
187
- inputSchema: {
188
- type: 'object',
189
- properties: {
190
- component_name: {
191
- type: 'string',
192
- description: 'Nom du composant (ex: button, modal, input)'
193
- }
194
- },
195
- required: ['component_name']
196
- }
197
- },
198
- {
199
- name: 'generate_component_code',
200
- description: 'Génère du code HTML pour un composant Concorde avec ses propriétés',
201
- inputSchema: {
202
- type: 'object',
203
- properties: {
204
- component_name: {
205
- type: 'string',
206
- description: 'Nom du composant'
207
- },
208
- properties: {
209
- type: 'object',
210
- description: 'Propriétés du composant',
211
- additionalProperties: true
212
- },
213
- content: {
214
- type: 'string',
215
- description: 'Contenu du composant (optionnel)'
216
- }
217
- },
218
- required: ['component_name']
219
- }
220
- },
221
- {
222
- name: 'get_form_example',
223
- description: 'Génère un exemple de formulaire avec des composants Concorde',
224
- inputSchema: {
225
- type: 'object',
226
- properties: {
227
- fields: {
228
- type: 'array',
229
- description: 'Liste des champs du formulaire',
230
- items: {
231
- type: 'object',
232
- properties: {
233
- name: { type: 'string' },
234
- type: { type: 'string' },
235
- label: { type: 'string' },
236
- required: { type: 'boolean' }
237
- }
238
- }
239
- }
240
- }
241
- }
242
- },
243
- {
244
- name: 'get_theme_info',
245
- description: 'Obtient des informations sur le système de thèmes Concorde',
246
- inputSchema: {
247
- type: 'object',
248
- properties: {
249
- theme: {
250
- type: 'string',
251
- description: 'Nom du thème (light, dark, auto)',
252
- enum: ['light', 'dark', 'auto']
253
- }
254
- }
255
- }
256
- },
257
- {
258
- name: 'get_icons_list',
259
- description: 'Liste toutes les icônes disponibles dans Concorde',
260
- inputSchema: {
261
- type: 'object',
262
- properties: {
263
- library: {
264
- type: 'string',
265
- description: 'Bibliothèque d\'icônes (core, iconoir, fontAwesome)',
266
- enum: ['core', 'iconoir', 'fontAwesome']
267
- }
268
- }
269
- }
270
- }
271
- ];
272
-
273
- return { tools };
274
- });
275
-
276
- // Handler pour exécuter les outils
277
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
278
- const { name, arguments: args } = request.params;
279
-
280
- switch (name) {
281
- case 'search_component':
282
- return await this.searchComponent(args.query);
283
- case 'get_component_info':
284
- return await this.getComponentInfo(args.component_name);
285
- case 'generate_component_code':
286
- return await this.generateComponentCode(
287
- args.component_name,
288
- args.properties || {},
289
- args.content || ''
290
- );
291
- case 'get_form_example':
292
- return await this.getFormExample(args.fields || []);
293
- case 'get_theme_info':
294
- return await this.getThemeInfo(args.theme || 'light');
295
- case 'get_icons_list':
296
- return await this.getIconsList(args.library || 'core');
297
- default:
298
- return {
299
- content: [{
300
- type: 'text',
301
- text: `Outil inconnu: ${name}`
302
- }]
303
- };
304
- }
305
- });
306
- }
307
-
308
- async loadComponents() {
309
- // Charger les composants UI
310
- const uiPath = path.join(COMPONENTS_PATH, 'ui');
311
- await this.loadComponentsFromDirectory(uiPath, 'ui');
312
-
313
- // Charger les composants fonctionnels
314
- const functionalPath = path.join(COMPONENTS_PATH, 'functional');
315
- await this.loadComponentsFromDirectory(functionalPath, 'functional');
316
- }
317
-
318
- async loadComponentsFromDirectory(dirPath, category) {
319
- try {
320
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
321
-
322
- for (const entry of entries) {
323
- if (entry.isDirectory() && !entry.name.startsWith('_')) {
324
- await this.loadComponent(path.join(dirPath, entry.name), category);
325
- }
326
- }
327
- } catch (error) {
328
- console.warn(`Impossible de lire le répertoire ${dirPath}:`, error.message);
329
- }
330
- }
331
-
332
- async loadComponent(compDir, category) {
333
- const compName = path.basename(compDir);
334
- const tagName = `sonic-${compName}`;
335
-
336
- // Trouve le fichier principal
337
- const mainFile = path.join(compDir, `${compName}.ts`);
338
-
339
- try {
340
- const content = await fs.readFile(mainFile, 'utf-8');
341
-
342
- // Trouve le fichier de documentation
343
- const docFile = path.join(compDir, `${compName}.md`);
344
- let docContent = '';
345
- try {
346
- docContent = await fs.readFile(docFile, 'utf-8');
347
- } catch {
348
- // Pas de documentation
349
- }
350
-
351
- // Extrait les propriétés du composant
352
- const props = this.extractProperties(content);
353
-
354
- // Extrait la description
355
- const description = this.extractDescription(content);
356
-
357
- // Extrait les exemples de la documentation
358
- const examples = this.extractExamples(docContent);
359
-
360
- const compInfo = new ComponentInfo(
361
- compName,
362
- tagName,
363
- category,
364
- mainFile,
365
- docFile,
366
- description,
367
- props,
368
- examples
369
- );
370
-
371
- this.components.set(compName, compInfo);
372
- } catch (error) {
373
- console.warn(`Impossible de charger le composant ${compName}:`, error.message);
374
- }
375
- }
376
-
377
- extractProperties(content) {
378
- const props = [];
379
-
380
- // Recherche les décorateurs @property
381
- const propertyPattern = /@property\([^)]*\)\s+(\w+)(?::\s*([^=]+))?/g;
382
- let match;
383
-
384
- while ((match = propertyPattern.exec(content)) !== null) {
385
- const propName = match[1];
386
- const propType = match[2] ? match[2].trim() : 'string';
387
-
388
- // Recherche les commentaires JSDoc pour cette propriété
389
- const commentPattern = new RegExp(`/\\*\\*\\s*\\n\\s*\\*\\s*([^\\n]+)`, 'g');
390
- const commentMatch = commentPattern.exec(content);
391
- const description = commentMatch ? commentMatch[1].trim() : '';
392
-
393
- props.push({
394
- name: propName,
395
- type: propType,
396
- description: description
397
- });
398
- }
399
-
400
- return props;
401
- }
402
-
403
- extractDescription(content) {
404
- // Recherche les commentaires de classe
405
- const classPattern = /\/\*\*\s*\n\s*\*\s*([^\n]+)/;
406
- const match = classPattern.exec(content);
407
- if (match) {
408
- return match[1].trim();
409
- }
410
-
411
- // Recherche le nom de la classe
412
- const classNamePattern = /export class (\w+)/;
413
- const classNameMatch = classNamePattern.exec(content);
414
- if (classNameMatch) {
415
- return `Composant ${classNameMatch[1]}`;
416
- }
417
-
418
- return 'Composant Concorde';
419
- }
420
-
421
- extractExamples(docContent) {
422
- const examples = [];
423
-
424
- // Recherche les blocs sonic-code
425
- const codePattern = /<sonic-code>(.*?)<\/sonic-code>/gs;
426
- let match;
427
-
428
- while ((match = codePattern.exec(docContent)) !== null) {
429
- const example = match[1].trim();
430
- if (example) {
431
- examples.push(example);
432
- }
433
- }
434
-
435
- return examples;
436
- }
437
-
438
- async loadDocumentation() {
439
- // Documentation des concepts de base
440
- this.documentation.set('architecture', `
441
- # Architecture Concorde
442
-
443
- Concorde est un framework de composants Web basé sur Lit Element avec les concepts suivants :
444
-
445
- ## Mixins principaux
446
-
447
- ### Subscriber
448
- - Permet de lier un composant à un publisher
449
- - Gestion automatique des données réactives
450
- - Support du data binding
451
-
452
- ### FormElement
453
- - Gestion des formulaires
454
- - Validation automatique
455
- - Liaison avec les publishers de formulaire
456
-
457
- ### Fetcher
458
- - Gestion des appels API
459
- - Chargement automatique des données
460
- - Support des filtres et pagination
461
-
462
- ## Système de thèmes
463
- - Thèmes light/dark/auto
464
- - Variables CSS personnalisables
465
- - Support des couleurs sémantiques
466
-
467
- ## Composants disponibles
468
- - Composants UI : boutons, inputs, modales, etc.
469
- - Composants fonctionnels : fetch, list, router, etc.
470
- - Système d'icônes intégré
471
- `);
472
-
473
- this.documentation.set('data-binding', `
474
- # Data Binding Concorde
475
-
476
- ## Syntaxe
477
- - \`data-bind ::attribute="expression"\` : Liaison d'attribut
478
- - \`data-bind ::inner-html="expression"\` : Liaison de contenu HTML
479
- - \`data-bind ::text-content="expression"\` : Liaison de contenu texte
480
-
481
- ## Expressions
482
- - \`$property\` : Accès à une propriété du publisher
483
- - \`$property.subproperty\` : Accès à une sous-propriété
484
- - \`function|$property\` : Application d'une fonction
485
-
486
- ## Exemples
487
- \`\`\`html
488
- <sonic-input data-bind ::value="$email"></sonic-input>
489
- <span data-bind ::inner-html="$name"></span>
490
- <div data-bind ::class="active|$isActive"></div>
491
- \`\`\`
492
- `);
493
- }
494
-
495
- async searchComponent(query) {
496
- const results = [];
497
- const queryLower = query.toLowerCase();
498
-
499
- for (const [compName, compInfo] of this.components) {
500
- if (compName.toLowerCase().includes(queryLower) ||
501
- compInfo.description.toLowerCase().includes(queryLower) ||
502
- compInfo.tagName.toLowerCase().includes(queryLower)) {
503
- results.push(`- **${compInfo.tagName}** (${compInfo.category}): ${compInfo.description}`);
504
- }
505
- }
506
-
507
- const content = results.length > 0
508
- ? `Composants trouvés pour '${query}':\n\n${results.join('\n')}`
509
- : `Aucun composant trouvé pour '${query}'`;
510
-
511
- return {
512
- content: [{
513
- type: 'text',
514
- text: content
515
- }]
516
- };
517
- }
518
-
519
- async getComponentInfo(componentName) {
520
- if (!this.components.has(componentName)) {
521
- return {
522
- content: [{
523
- type: 'text',
524
- text: `Composant '${componentName}' non trouvé`
525
- }]
526
- };
527
- }
528
-
529
- const compInfo = this.components.get(componentName);
530
- const content = this.generateComponentDoc(compInfo);
531
-
532
- return {
533
- content: [{
534
- type: 'text',
535
- text: content
536
- }]
537
- };
538
- }
539
-
540
- async generateComponentCode(componentName, properties, content = '') {
541
- if (!this.components.has(componentName)) {
542
- return {
543
- content: [{
544
- type: 'text',
545
- text: `Composant '${componentName}' non trouvé`
546
- }]
547
- };
548
- }
549
-
550
- const compInfo = this.components.get(componentName);
551
- const tagName = compInfo.tagName;
552
-
553
- // Génère les attributs
554
- const attributes = [];
555
- for (const [key, value] of Object.entries(properties)) {
556
- if (typeof value === 'boolean') {
557
- if (value) {
558
- attributes.push(key);
559
- }
560
- } else {
561
- attributes.push(`${key}="${value}"`);
562
- }
563
- }
564
-
565
- // Génère le code HTML
566
- const htmlCode = content
567
- ? `<${tagName} ${attributes.join(' ')}>${content}</${tagName}>`
568
- : `<${tagName} ${attributes.join(' ')}></${tagName}>`;
569
-
570
- return {
571
- content: [{
572
- type: 'text',
573
- text: htmlCode
574
- }]
575
- };
576
- }
577
-
578
- async getFormExample(fields) {
579
- if (fields.length === 0) {
580
- // Exemple par défaut
581
- fields = [
582
- { name: 'email', type: 'email', label: 'Email', required: true },
583
- { name: 'password', type: 'password', label: 'Mot de passe', required: true },
584
- { name: 'remember', type: 'checkbox', label: 'Se souvenir de moi', required: false }
585
- ];
586
- }
587
-
588
- let formHtml = '<div formDataProvider="exampleForm">\n';
589
-
590
- for (const field of fields) {
591
- const { name, type, label, required } = field;
592
-
593
- if (type === 'checkbox') {
594
- formHtml += ` <sonic-checkbox name="${name}"`;
595
- if (required) {
596
- formHtml += ' required';
597
- }
598
- formHtml += `>${label}</sonic-checkbox>\n`;
599
- } else {
600
- formHtml += ` <sonic-input name="${name}" type="${type}" label="${label}"`;
601
- if (required) {
602
- formHtml += ' required';
603
- }
604
- formHtml += '></sonic-input>\n';
605
- }
606
- }
607
-
608
- formHtml += ' <sonic-form-actions>\n';
609
- formHtml += ' <sonic-button type="primary">Valider</sonic-button>\n';
610
- formHtml += ' <sonic-button variant="outline">Annuler</sonic-button>\n';
611
- formHtml += ' </sonic-form-actions>\n';
612
- formHtml += '</div>';
613
-
614
- return {
615
- content: [{
616
- type: 'text',
617
- text: formHtml
618
- }]
619
- };
620
- }
621
-
622
- async getThemeInfo(theme) {
623
- const themeInfo = {
624
- light: {
625
- description: 'Thème clair par défaut',
626
- colors: {
627
- primary: '#1e293b',
628
- info: '#2563eb',
629
- danger: '#f43f5e',
630
- warning: '#f97316',
631
- success: '#14b8a6'
632
- }
633
- },
634
- dark: {
635
- description: 'Thème sombre',
636
- colors: {
637
- primary: '#334155',
638
- info: '#3abff8',
639
- danger: '#f87272',
640
- warning: '#fbbd23',
641
- success: '#36d399'
642
- }
643
- },
644
- auto: {
645
- description: 'Thème automatique basé sur les préférences système',
646
- colors: 'Utilise les couleurs du thème sombre si l\'utilisateur préfère le mode sombre'
647
- }
648
- };
649
-
650
- const info = themeInfo[theme] || themeInfo.light;
651
-
652
- let content = `# Thème ${theme}\n\n${info.description}\n\n## Utilisation\n\n\`\`\`html\n<sonic-theme theme="${theme}">\n <!-- Vos composants ici -->\n</sonic-theme>\n\`\`\`\n\n`;
653
-
654
- if (info.colors && typeof info.colors === 'object') {
655
- content += '## Couleurs\n\n';
656
- for (const [colorName, colorValue] of Object.entries(info.colors)) {
657
- content += `- **${colorName}**: \`${colorValue}\`\n`;
658
- }
659
- }
660
-
661
- return {
662
- content: [{
663
- type: 'text',
664
- text: content
665
- }]
666
- };
667
- }
668
-
669
- async getIconsList(library) {
670
- const iconsInfo = {
671
- core: [
672
- 'cancel', 'check-circled-outline', 'check', 'emoji-puzzled',
673
- 'info-empty', 'loader', 'minus-small', 'more-horiz', 'more-vert',
674
- 'nav-arrow-down', 'warning-circled-outline'
675
- ],
676
- iconoir: 'Bibliothèque d\'icônes externe avec de nombreuses icônes',
677
- fontAwesome: 'Bibliothèque FontAwesome avec icônes solid et regular'
678
- };
679
-
680
- let content;
681
-
682
- if (library === 'core') {
683
- const icons = iconsInfo.core;
684
- content = `# Icônes Core Concorde\n\n## Utilisation\n\n\`\`\`html\n<sonic-icon library="core" name="nom-de-l-icone"></sonic-icon>\n\`\`\`\n\n## Icônes disponibles\n\n`;
685
- for (const icon of icons) {
686
- content += `- **${icon}**: \`<sonic-icon library="core" name="${icon}"></sonic-icon>\`\n`;
687
- }
688
- } else {
689
- content = `# Bibliothèque d'icônes ${library}\n\n${iconsInfo[library]}\n\n## Utilisation\n\n\`\`\`html\n<sonic-icon library="${library}" name="nom-de-l-icone"></sonic-icon>\n\`\`\`\n\nPour les icônes FontAwesome, vous pouvez spécifier le préfixe :\n\`\`\`html\n<sonic-icon library="fontAwesome" prefix="solid" name="home"></sonic-icon>\n<sonic-icon library="fontAwesome" prefix="regular" name="user"></sonic-icon>\n\`\`\`\n`;
690
- }
691
-
692
- return {
693
- content: [{
694
- type: 'text',
695
- text: content
696
- }]
697
- };
698
- }
699
-
700
- generateComponentDoc(compInfo) {
701
- let content = `# ${compInfo.tagName}\n\n**Catégorie:** ${compInfo.category}\n**Description:** ${compInfo.description}\n\n## Propriétés\n\n`;
702
-
703
- for (const prop of compInfo.props) {
704
- content += `- **${prop.name}** (${prop.type}): ${prop.description}\n`;
705
- }
706
-
707
- if (compInfo.examples.length > 0) {
708
- content += '\n## Exemples\n\n';
709
- for (let i = 0; i < Math.min(compInfo.examples.length, 3); i++) {
710
- content += `### Exemple ${i + 1}\n\n\`\`\`html\n${compInfo.examples[i]}\n\`\`\`\n\n`;
711
- }
712
- }
713
-
714
- return content;
715
- }
716
-
717
- generateUIExamples() {
718
- return `# Exemples de composants UI Concorde
719
-
720
- ## Bouton avec icône
721
-
722
- \`\`\`html
723
- <sonic-button type="primary">
724
- <sonic-icon library="core" name="check" slot="prefix"></sonic-icon>
725
- Valider
726
- </sonic-button>
727
- \`\`\`
728
-
729
- ## Formulaire complet
730
-
731
- \`\`\`html
732
- <div formDataProvider="userForm">
733
- <sonic-fieldset label="Informations utilisateur">
734
- <sonic-form-layout>
735
- <sonic-input name="firstName" label="Prénom" required></sonic-input>
736
- <sonic-input name="lastName" label="Nom" required></sonic-input>
737
- <sonic-input name="email" type="email" label="Email" required></sonic-input>
738
- </sonic-form-layout>
739
- </sonic-fieldset>
740
- <sonic-form-actions>
741
- <sonic-button type="primary">Enregistrer</sonic-button>
742
- <sonic-button variant="outline">Annuler</sonic-button>
743
- </sonic-form-actions>
744
- </div>
745
- \`\`\`
746
-
747
- ## Modal avec contenu
748
-
749
- \`\`\`html
750
- <sonic-modal id="exampleModal">
751
- <sonic-modal-title>Confirmation</sonic-modal-title>
752
- <sonic-modal-content>
753
- Êtes-vous sûr de vouloir continuer ?
754
- </sonic-modal-content>
755
- <sonic-modal-actions>
756
- <sonic-button hideModal>Annuler</sonic-button>
757
- <sonic-button type="primary" hideModal>Confirmer</sonic-button>
758
- </sonic-modal-actions>
759
- </sonic-modal>
760
- \`\`\`
761
- `;
762
- }
763
-
764
- generateFunctionalExamples() {
765
- return `# Exemples de composants fonctionnels Concorde
766
-
767
- ## Chargement de données avec Fetch
768
-
769
- \`\`\`html
770
- <sonic-fetch
771
- serviceURL="https://api.example.com"
772
- endPoint="users"
773
- dataProvider="usersData">
774
- </sonic-fetch>
775
-
776
- <sonic-list dataProvider="usersData" props='$usersData'>
777
- <template>
778
- <div class="user-card">
779
- <h3 data-bind ::inner-html="$name"></h3>
780
- <p data-bind ::inner-html="$email"></p>
781
- </div>
782
- </template>
783
- </sonic-list>
784
- \`\`\`
785
-
786
- ## Navigation avec Router
787
-
788
- \`\`\`html
789
- <sonic-router>
790
- <template data-route="#home">
791
- <h1>Page d'accueil</h1>
792
- </template>
793
- <template data-route="#about">
794
- <h1>À propos</h1>
795
- </template>
796
- <template data-route="#contact">
797
- <h1>Contact</h1>
798
- </template>
799
- </sonic-router>
800
-
801
- <nav>
802
- <sonic-button href="#home">Accueil</sonic-button>
803
- <sonic-button href="#about">À propos</sonic-button>
804
- <sonic-button href="#contact">Contact</sonic-button>
805
- </nav>
806
- \`\`\`
807
-
808
- ## États conditionnels
809
-
810
- \`\`\`html
811
- <sonic-states dataProvider="userData" data-path="status">
812
- <template data-value="loading">
813
- <sonic-loader></sonic-loader>
814
- </template>
815
- <template data-value="success">
816
- <div class="success-message">Données chargées avec succès</div>
817
- </template>
818
- <template data-value="error">
819
- <sonic-alert type="danger">Erreur lors du chargement</sonic-alert>
820
- </template>
821
- </sonic-states>
822
- \`\`\`
823
- `;
824
- }
825
-
826
- async run() {
827
- await this.initialize();
828
-
829
- const transport = new StdioServerTransport();
830
- await this.server.connect(transport);
831
-
832
- console.error('Serveur MCP Concorde démarré');
833
- }
834
- }
835
-
836
- // Point d'entrée principal
837
- async function main() {
838
- const server = new ConcordeMCPServer();
839
- await server.run();
840
- }
841
-
842
- // Gestion des erreurs non capturées
843
- process.on('uncaughtException', (error) => {
844
- console.error('Erreur non capturée:', error);
845
- process.exit(1);
846
- });
847
-
848
- process.on('unhandledRejection', (reason, promise) => {
849
- console.error('Promesse rejetée non gérée:', reason);
850
- process.exit(1);
851
- });
852
-
853
- // Point d'entrée principal
854
- main().catch((error) => {
855
- console.error('Erreur lors du démarrage du serveur:', error);
856
- process.exit(1);
857
- });
858
-
859
- export { ConcordeMCPServer };