fleetbo-svro 1.0.46 → 1.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/fleetbo-mcp.js +489 -0
  2. package/package.json +4 -2
@@ -0,0 +1,489 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema,
7
+ ListPromptsRequestSchema,
8
+ GetPromptRequestSchema,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import { z } from "zod";
11
+ import fs from "node:fs";
12
+ import path from "node:path";
13
+ import os from "node:os";
14
+
15
+ function getDevToken() {
16
+ if (process.env.FLEETBO_DEV_TOKEN) return process.env.FLEETBO_DEV_TOKEN;
17
+ try {
18
+ const credPath = path.join(os.homedir(), ".fleetbo", "credentials.json");
19
+ if (fs.existsSync(credPath)) {
20
+ return JSON.parse(fs.readFileSync(credPath, "utf8")).devToken || null;
21
+ }
22
+ } catch (_) {}
23
+ return null;
24
+ }
25
+
26
+ const DEV_AUTH_TOKEN = getDevToken();
27
+ const CLOUD_RUN_REGION = "jqycakhlxa-uc.a.run.app";
28
+
29
+ // ============================================================================
30
+ // CONTRAT DE DONNÉES & DIRECTIVES STRICTES D'ARCHITECTURE FLEETBO SVRO
31
+ // ============================================================================
32
+ const FLEETBO_SYSTEM_GUIDELINES = `
33
+ # LE CONTRAT DE DONNÉES FLEETBO (FLEETBO DATA CONTRACT)
34
+ Ce document constitue le Cahier des charges officiel et le Contrat bilatéral d'intégrité liant le code client et le moteur Data OS Fleetbo SVRO.
35
+
36
+ 🚨 DIRECTIVE D'EXÉCUTION OBLIGATOIRE POUR L'AGENT IA :
37
+ 1. Interdiction d'extrapolation : Ne crée aucun champ, type ou endpoint non déclaré explicitement dans svro.schema.json.
38
+ 2. Zéro backend intermédiaire : N'écris AUCUN serveur Express, NestJS ou route d'API REST fictive.
39
+ 3. Objet global unique : Utilise exclusivement l'objet global Fleetbo.* (add, getDocsG, getDoc, update, delete, call, join).
40
+ 4. Zero Import : L'objet Fleetbo et les balises <fleetbo-*> sont des composants globaux au runtime. Ne fais aucun import manuel de SDK.
41
+ 5. Typage strict avant écriture : Caste systématiquement les types reçus des formulaires (Number, String, Boolean).
42
+
43
+ CYCLE DE MODÉLISATION DU DATA OS :
44
+ - Étape 1 (Création) : Alloue le projet via 'fleetbo_create_project'.
45
+ - Étape 2 (Amorçage) : Lance 'npx fleetbo-svro init ...' puis 'npx fleetbo-svro sync'.
46
+ - Étape 3 (Modélisation Jour 1) : Écris tes premières vues UI (JSX, TSX, Vue) et modélise la base via 'fleetbo_update_project'.
47
+ - Étape 4 (Scellage) : Exécute 'npx fleetbo-svro sync' pour générer svro.schema.json, svro.workflow.json, Fleetbo_contract.md et le typage TypeScript.
48
+ - Étape 5 (Évolutions Jour 2) : Chaque nouvelle vue ou règle passe par 'fleetbo_update_project' suivi d'un 'npx fleetbo-svro sync'.
49
+
50
+ SYNTAXE CRUD CANONIQUE DU SDK FLEETBO :
51
+ - CREATE : await Fleetbo.add('collection', { name: String(n).trim(), price: Number(p) });
52
+ - READ ALL : const docs = await Fleetbo.getDocsG('collection');
53
+ - READ ONE : const doc = await Fleetbo.getDoc('collection', docId);
54
+ - READ USER : const docs = await Fleetbo.getDocsU('collection');
55
+ - UPDATE : await Fleetbo.update('collection', docId, { status: 'PAID' });
56
+ - DELETE : await Fleetbo.delete('collection', docId);
57
+ - JOIN : await Fleetbo.join('orders', { innerJoin: { collection: 'users', on: ['userId', '==', 'id'], as: 'user' } });
58
+ - CLOUD FUNCTION : const res = await Fleetbo.call('$functionName', payload);
59
+
60
+ GESTION DE L'ENVIRONNEMENT (.env) :
61
+ - VITE_FLEETBO_PROTOTYPE=true : Mode bac à sable UI. L'Edge acquitte immédiatement sans toucher à la base physique.
62
+ - VITE_FLEETBO_PROTOTYPE=false : Mode strict live. L'Edge valide le contrat DDL et persiste sur MongoDB Atlas.
63
+ `;
64
+
65
+ const server = new Server(
66
+ {
67
+ name: "fleetbo-svro-mcp",
68
+ version: "1.0.0",
69
+ },
70
+ {
71
+ capabilities: {
72
+ tools: {},
73
+ prompts: {},
74
+ },
75
+ }
76
+ );
77
+
78
+ // ============================================================================
79
+ // 1. PROMPTS MCP
80
+ // ============================================================================
81
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
82
+ return {
83
+ prompts: [
84
+ {
85
+ name: "fleetbo_contract_rules",
86
+ description:
87
+ "Loads strict architectural rules, invariants, and integrity directives for Fleetbo SVRO.",
88
+ },
89
+ ],
90
+ };
91
+ });
92
+
93
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
94
+ if (request.params.name === "fleetbo_contract_rules") {
95
+ return {
96
+ description: "Official Fleetbo SVRO architecture directives",
97
+ messages: [
98
+ {
99
+ role: "user",
100
+ content: {
101
+ type: "text",
102
+ text: FLEETBO_SYSTEM_GUIDELINES,
103
+ },
104
+ },
105
+ ],
106
+ };
107
+ }
108
+ throw new Error(`Unknown prompt: ${request.params.name}`);
109
+ });
110
+
111
+ // ============================================================================
112
+ // 2. OUTILS MCP (Tools)
113
+ // ============================================================================
114
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
115
+ return {
116
+ tools: [
117
+ {
118
+ name: "fleetbo_create_project",
119
+ description:
120
+ "Étape 1 : Crée une nouvelle application Fleetbo Data OS dans le Cloud avec son nom et sa clé unique (contrats initiaux vierges prêts pour la modélisation).",
121
+ inputSchema: {
122
+ type: "object",
123
+ properties: {
124
+ name: {
125
+ type: "string",
126
+ description: "Nom d'affichage de l'application (ex: CoWorking Manager)",
127
+ },
128
+ keyApp: {
129
+ type: "string",
130
+ description: "Clé unique d'application sans espace ni caractères spéciaux (ex: coworking_prod)",
131
+ },
132
+ },
133
+ required: ["name", "keyApp"],
134
+ },
135
+ },
136
+ {
137
+ name: "fleetbo_update_project",
138
+ description:
139
+ "Step 3 & 5: Analyzes UI component files (JSX, TSX, Vue) and business rules to forge or enrich DDL schema and workflow additively.",
140
+ inputSchema: {
141
+ type: "object",
142
+ properties: {
143
+ keyApp: {
144
+ type: "string",
145
+ description: "Unique application key (e.g. coworking_prod)",
146
+ },
147
+ name: {
148
+ type: "string",
149
+ description: "Application name",
150
+ },
151
+ rules: {
152
+ type: "string",
153
+ description: "New business rules, calculations, or state transitions.",
154
+ },
155
+ filePaths: {
156
+ type: "array",
157
+ items: { type: "string" },
158
+ description: "Relative paths of view files to analyze (e.g. ['src/views/Bookings.jsx']).",
159
+ },
160
+ viewFiles: {
161
+ type: "array",
162
+ items: {
163
+ type: "object",
164
+ properties: {
165
+ name: { type: "string" },
166
+ content: { type: "string" },
167
+ },
168
+ required: ["name", "content"],
169
+ },
170
+ description: "View files already loaded in memory [{ name, content }].",
171
+ },
172
+ },
173
+ required: ["keyApp", "name"],
174
+ },
175
+ },
176
+ {
177
+ name: "fleetbo_publish_function",
178
+ description:
179
+ "Deploys a private or public cloud utility function executed in a secure Fleetbo serverless environment.",
180
+ inputSchema: {
181
+ type: "object",
182
+ properties: {
183
+ enterpriseID: {
184
+ type: "string",
185
+ description: "Project enterpriseID infrastructure identifier",
186
+ },
187
+ functionName: {
188
+ type: "string",
189
+ description: "Function name (alphanumeric 3-40 chars, e.g. calculateTotal)",
190
+ },
191
+ code: {
192
+ type: "string",
193
+ description: "JS source code (e.g. async function calculateTotal(payload, Fleetbo) { ... })",
194
+ },
195
+ description: {
196
+ type: "string",
197
+ description: "Action documentation for the catalog and Alex AI",
198
+ },
199
+ isPublic: {
200
+ type: "boolean",
201
+ description: "true to publish to the global Marketplace, false for private function",
202
+ },
203
+ },
204
+ required: ["enterpriseID", "functionName", "code"],
205
+ },
206
+ },
207
+ {
208
+ name: "fleetbo_get_contract",
209
+ description:
210
+ "Provides the official data contract, SDK directives, production lifecycle and canonical blueprint.",
211
+ inputSchema: {
212
+ type: "object",
213
+ properties: {},
214
+ },
215
+ },
216
+ ],
217
+ };
218
+ });
219
+
220
+ // ============================================================================
221
+ // 3. EXÉCUTION DES OUTILS
222
+ // ============================================================================
223
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
224
+ const { name, arguments: args } = request.params;
225
+
226
+ if (name === "fleetbo_get_contract") {
227
+ return {
228
+ content: [
229
+ {
230
+ type: "text",
231
+ text: FLEETBO_SYSTEM_GUIDELINES,
232
+ },
233
+ ],
234
+ };
235
+ }
236
+
237
+ if (!DEV_AUTH_TOKEN) {
238
+ return {
239
+ isError: true,
240
+ content: [
241
+ {
242
+ type: "text",
243
+ text: "Error: FLEETBO_DEV_TOKEN is missing from your environment. Run 'npx fleetbo-svro login' or configure it in your MCP client.",
244
+ },
245
+ ],
246
+ };
247
+ }
248
+
249
+ try {
250
+ // --- ACTION 1 : CREATE PROJECT ---
251
+ if (name === "fleetbo_create_project") {
252
+ const schema = z.object({
253
+ name: z.string().min(2),
254
+ keyApp: z.string().min(2),
255
+ });
256
+ const params = schema.parse(args);
257
+
258
+ const res = await fetch(`https://createprojectlight-${CLOUD_RUN_REGION}`, {
259
+ method: "POST",
260
+ headers: {
261
+ "Content-Type": "application/json",
262
+ Authorization: `Bearer ${DEV_AUTH_TOKEN}`,
263
+ },
264
+ body: JSON.stringify({
265
+ data: {
266
+ name: params.name,
267
+ keyApp: params.keyApp,
268
+ },
269
+ }),
270
+ });
271
+
272
+ const json = await res.json();
273
+ if (!res.ok || json.error) {
274
+ throw new Error(json.error?.message || "Failed to create project on Fleetbo OS.");
275
+ }
276
+
277
+ const proj = json.result?.data || json.data || {};
278
+ const resolvedId = proj.enterpriseId || proj.referenceId || proj.id;
279
+
280
+ return {
281
+ content: [
282
+ {
283
+ type: "text",
284
+ text: JSON.stringify(
285
+ {
286
+ status: "SUCCESS",
287
+ message: `Project "${params.name}" successfully created. Ready for modeling.`,
288
+ enterpriseID: resolvedId,
289
+ keyApp: params.keyApp,
290
+ bootstrapToken: proj.bootstrapToken,
291
+ commandInit: `npx fleetbo-svro init --keyApp=${params.keyApp} --token=${proj.bootstrapToken}`,
292
+ nextSteps: [
293
+ "1. Run commandInit in your terminal to configure local .env.",
294
+ "2. Write your initial UI component (e.g. src/views/App.jsx).",
295
+ "3. Call 'fleetbo_update_project' with this file to forge data contract.",
296
+ "4. Run 'npx fleetbo-svro sync' to seal Edge and generate Fleetbo_contract.md.",
297
+ ],
298
+ },
299
+ null,
300
+ 2
301
+ ),
302
+ },
303
+ ],
304
+ };
305
+ }
306
+
307
+ // --- ACTION 2 : UPDATE PROJECT (MODÉLISATION ADDITIVE) ---
308
+ if (name === "fleetbo_update_project") {
309
+ const schema = z.object({
310
+ keyApp: z.string().min(2),
311
+ name: z.string().min(2),
312
+ rules: z.string().optional(),
313
+ filePaths: z.array(z.string()).optional(),
314
+ viewFiles: z
315
+ .array(
316
+ z.object({
317
+ name: z.string(),
318
+ content: z.string(),
319
+ })
320
+ )
321
+ .optional(),
322
+ });
323
+ const params = schema.parse(args);
324
+
325
+ const filesPayload = [...(params.viewFiles || [])];
326
+
327
+ const ALLOWED_EXTENSIONS = new Set([".jsx", ".tsx", ".vue", ".svelte", ".js", ".ts", ".html"]);
328
+ const FORBIDDEN_PATTERNS = [/\.env/i, /id_rsa/i, /node_modules/i, /\.git/i, /package-lock/i, /\.pem$/i];
329
+ const MAX_FILE_SIZE_BYTES = 500 * 1024;
330
+
331
+ if (params.filePaths && params.filePaths.length > 0) {
332
+ const resolvedProjectRoot = path.resolve(process.cwd());
333
+
334
+ for (const relPath of params.filePaths) {
335
+ const fullPath = path.resolve(resolvedProjectRoot, relPath);
336
+ const relative = path.relative(resolvedProjectRoot, fullPath);
337
+
338
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
339
+ console.warn(`[MCP Security] Access denied outside project directory: ${relPath}`);
340
+ continue;
341
+ }
342
+
343
+ const baseName = path.basename(fullPath);
344
+ if (FORBIDDEN_PATTERNS.some((pat) => pat.test(baseName))) {
345
+ console.warn(`[MCP Security] Sensitive file skipped: ${baseName}`);
346
+ continue;
347
+ }
348
+
349
+ const ext = path.extname(fullPath).toLowerCase();
350
+ if (!ALLOWED_EXTENSIONS.has(ext)) {
351
+ console.warn(`[MCP Security] Unsupported file extension: ${ext}`);
352
+ continue;
353
+ }
354
+
355
+ if (fs.existsSync(fullPath)) {
356
+ const stat = fs.statSync(fullPath);
357
+ if (!stat.isFile()) {
358
+ console.warn(`[MCP Security] Path skipped (not a regular file): ${relPath}`);
359
+ continue;
360
+ }
361
+ if (stat.size > MAX_FILE_SIZE_BYTES) {
362
+ console.warn(`[MCP Security] File too large (> 500 KB) skipped: ${relPath}`);
363
+ continue;
364
+ }
365
+
366
+ filesPayload.push({
367
+ name: baseName,
368
+ content: fs.readFileSync(fullPath, "utf8"),
369
+ });
370
+ } else {
371
+ console.warn(`[MCP Security] File not found on disk: ${relPath}`);
372
+ }
373
+ }
374
+ }
375
+
376
+ if (filesPayload.length === 0 && (!params.rules || !params.rules.trim())) {
377
+ throw new Error(
378
+ "Modeling failed: You must provide at least one valid UI view file (filePaths/viewFiles) or a business rule (rules)."
379
+ );
380
+ }
381
+
382
+ const res = await fetch(`https://updateprojectlight-${CLOUD_RUN_REGION}`, {
383
+ method: "POST",
384
+ headers: {
385
+ "Content-Type": "application/json",
386
+ Authorization: `Bearer ${DEV_AUTH_TOKEN}`,
387
+ },
388
+ body: JSON.stringify({
389
+ data: {
390
+ keyApp: params.keyApp,
391
+ name: params.name,
392
+ newViewFiles: filesPayload,
393
+ fleetbo_rules: params.rules || "",
394
+ },
395
+ }),
396
+ });
397
+
398
+ const json = await res.json();
399
+ if (!res.ok || json.error) {
400
+ throw new Error(json.error?.message || "Failed to model project on Fleetbo Cloud.");
401
+ }
402
+
403
+ return {
404
+ content: [
405
+ {
406
+ type: "text",
407
+ text: JSON.stringify(
408
+ {
409
+ status: "SUCCESS",
410
+ message: `Alex AI modeled ${filesPayload.length} component(s) and registered business rules successfully.`,
411
+ actionRequired: "npx fleetbo-svro sync",
412
+ directive:
413
+ "RUN 'npx fleetbo-svro sync' in terminal now to fetch contracts, seal Edge KV, update TypeScript types and generate Fleetbo_contract.md.",
414
+ },
415
+ null,
416
+ 2
417
+ ),
418
+ },
419
+ ],
420
+ };
421
+ }
422
+
423
+ // --- ACTION 3 : PUBLISH FUNCTION ---
424
+ if (name === "fleetbo_publish_function") {
425
+ const schema = z.object({
426
+ enterpriseID: z.string(),
427
+ functionName: z.string().min(3).max(40),
428
+ code: z.string().min(10),
429
+ description: z.string().optional(),
430
+ isPublic: z.boolean().optional(),
431
+ });
432
+ const params = schema.parse(args);
433
+
434
+ const res = await fetch(`https://publishfunction-${CLOUD_RUN_REGION}`, {
435
+ method: "POST",
436
+ headers: {
437
+ "Content-Type": "application/json",
438
+ Authorization: `Bearer ${DEV_AUTH_TOKEN}`,
439
+ },
440
+ body: JSON.stringify({
441
+ data: {
442
+ enterpriseID: params.enterpriseID,
443
+ functionName: params.functionName,
444
+ targetType: "inline",
445
+ code: params.code,
446
+ description: params.description || "",
447
+ isPublic: params.isPublic ?? false,
448
+ },
449
+ }),
450
+ });
451
+
452
+ const json = await res.json();
453
+ if (!res.ok || json.error) {
454
+ throw new Error(json.error?.message || "Failed to deploy function.");
455
+ }
456
+
457
+ return {
458
+ content: [
459
+ {
460
+ type: "text",
461
+ text: JSON.stringify(
462
+ {
463
+ status: "SUCCESS",
464
+ functionName: `$${params.functionName}`,
465
+ isPublic: params.isPublic ?? false,
466
+ usageHint: `Direct client usage: const res = await Fleetbo.call.$${params.functionName}(payload);`,
467
+ },
468
+ null,
469
+ 2
470
+ ),
471
+ },
472
+ ],
473
+ };
474
+ }
475
+
476
+ throw new Error(`Unknown tool: ${name}`);
477
+ } catch (err) {
478
+ return {
479
+ isError: true,
480
+ content: [{ type: "text", text: `Fleetbo MCP Error: ${err.message}` }],
481
+ };
482
+ }
483
+ });
484
+
485
+ // ============================================================================
486
+ // 4. CONNEXION STDIO
487
+ // ============================================================================
488
+ const transport = new StdioServerTransport();
489
+ await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-svro",
3
- "version": "1.0.46",
3
+ "version": "1.0.47",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,8 +21,10 @@
21
21
  "index.d.ts"
22
22
  ],
23
23
  "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.30.0",
24
25
  "firebase": "^12.16.0",
25
- "unplugin-auto-import": "^0.18.0"
26
+ "unplugin-auto-import": "^0.18.0",
27
+ "zod": "^4.6.5"
26
28
  },
27
29
  "devDependencies": {
28
30
  "esbuild": "^0.28.1"