@stellisoft/stellify-mcp 0.1.24 → 0.1.25

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/index.js CHANGED
@@ -294,12 +294,13 @@ IMPORTANT: This APPENDS to existing method statements. To REPLACE a method's cod
294
294
  },
295
295
  {
296
296
  name: 'save_method',
297
- description: `Update an existing method's properties (name, visibility, returnType, nullable, parameters, data).
297
+ description: `Update an existing method's properties (name, visibility, returnType, nullable, parameters, data, is_async).
298
298
 
299
299
  Use this to modify a method after creation. For updating the method body, use add_method_body instead.
300
300
 
301
301
  Parameters:
302
302
  - data: Array of statement UUIDs that form the method body. Use this to reorder statements or remove unwanted statements from the method.
303
+ - is_async: Set to true for JavaScript/Vue methods that use await.
303
304
 
304
305
  Example - Update return type:
305
306
  {
@@ -308,6 +309,12 @@ Example - Update return type:
308
309
  "nullable": true
309
310
  }
310
311
 
312
+ Example - Mark method as async (for methods using await):
313
+ {
314
+ "uuid": "method-uuid",
315
+ "is_async": true
316
+ }
317
+
311
318
  Example - Remove duplicate/unwanted statements:
312
319
  {
313
320
  "uuid": "method-uuid",
@@ -351,6 +358,10 @@ Example - Remove duplicate/unwanted statements:
351
358
  description: 'Array of statement UUIDs that form the method body. Use to reorder or remove statements.',
352
359
  items: { type: 'string' },
353
360
  },
361
+ is_async: {
362
+ type: 'boolean',
363
+ description: 'Whether the method is async (JavaScript/Vue only). Set to true for methods that use await.',
364
+ },
354
365
  },
355
366
  required: ['uuid'],
356
367
  },
@@ -374,16 +385,20 @@ Example - Remove duplicate/unwanted statements:
374
385
  },
375
386
  {
376
387
  name: 'delete_method',
377
- description: 'Delete a method from a file by UUID. This permanently removes the method and all its code.',
388
+ description: 'Delete a method from a file by UUID. This permanently removes the method and all its code. Requires both the file UUID and method UUID.',
378
389
  inputSchema: {
379
390
  type: 'object',
380
391
  properties: {
392
+ file: {
393
+ type: 'string',
394
+ description: 'UUID of the file containing the method (required)',
395
+ },
381
396
  uuid: {
382
397
  type: 'string',
383
398
  description: 'UUID of the method to delete',
384
399
  },
385
400
  },
386
- required: ['uuid'],
401
+ required: ['file', 'uuid'],
387
402
  },
388
403
  },
389
404
  {
@@ -903,7 +918,12 @@ Vue SFC example:
903
918
  statements: [importStmtUuid, refStmtUuid] // Statement UUIDs (imports, refs)
904
919
  })
905
920
 
906
- For <script setup> content, the order in statements array determines output order.`,
921
+ For <script setup> content, the order in statements array determines output order.
922
+
923
+ DEPENDENCY RESOLUTION (includes array):
924
+ The 'includes' array accepts BOTH UUIDs and namespace strings.
925
+ Namespace strings (e.g., "Illuminate\\Http\\JsonResponse") are automatically resolved to UUIDs.
926
+ This works the same as create_file's dependency resolution.`,
907
927
  inputSchema: {
908
928
  type: 'object',
909
929
  properties: {
@@ -942,7 +962,7 @@ For <script setup> content, the order in statements array determines output orde
942
962
  includes: {
943
963
  type: 'array',
944
964
  items: { type: 'string' },
945
- description: 'Array of file UUIDs to import',
965
+ description: 'Array of file UUIDs OR namespace strings to import. Namespace strings (e.g., "Illuminate\\\\Http\\\\JsonResponse") are auto-resolved to UUIDs.',
946
966
  },
947
967
  models: {
948
968
  type: 'array',
@@ -975,12 +995,16 @@ WARNING: This is destructive and cannot be undone. Make sure the file is not ref
975
995
  inputSchema: {
976
996
  type: 'object',
977
997
  properties: {
998
+ directory: {
999
+ type: 'string',
1000
+ description: 'UUID of the directory containing the file (get from get_project directories array or get_file response)',
1001
+ },
978
1002
  uuid: {
979
1003
  type: 'string',
980
1004
  description: 'UUID of the file to delete',
981
1005
  },
982
1006
  },
983
- required: ['uuid'],
1007
+ required: ['directory', 'uuid'],
984
1008
  },
985
1009
  },
986
1010
  {
@@ -1086,6 +1110,8 @@ Creates: Model ($fillable, $casts, relationships), Controller (CRUD actions), Se
1086
1110
 
1087
1111
  IMPORTANT: Routes are NOT auto-wired. After creation, use create_route with the returned controller UUID and method UUIDs.
1088
1112
 
1113
+ IMPORTANT: After creation, check the controller methods for return types and parameter types. If methods use classes not already in includes (e.g., JsonResponse), add those class UUIDs to the controller's includes via save_file.
1114
+
1089
1115
  Response includes controller.methods array with {uuid, name} for each action (index, store, update, destroy).`,
1090
1116
  inputSchema: {
1091
1117
  type: 'object',
@@ -1404,18 +1430,30 @@ Key concepts:
1404
1430
 
1405
1431
  1. get_project → find 'js' directory UUID (or create it)
1406
1432
  2. create_file → type='js', extension='vue' for the component
1407
- 3. Create statements for imports:
1408
- - "import { ref } from 'vue';" (REQUIRED for ref())
1409
- - "import { Http, List } from 'stellify-framework';" (for Stellify classes)
1433
+ 3. **Create a template route** for editor access:
1434
+ - create_route with name like "notes-template" or "component-name-template"
1435
+ - This route is NOT where the component displays - it's only for accessing the template in the Stellify visual editor
1436
+ - The actual display route (e.g., "/notes") will have just \`<div id="app"></div>\` where Vue mounts
1437
+ 4. Create statements for imports:
1438
+ - "import { ref, onMounted } from 'vue';" (REQUIRED for ref() and lifecycle hooks)
1439
+ - "import { Http } from 'stellify-framework';" (for API calls)
1410
1440
  NOTE: The npm package is "stellify-framework" (NOT @stellify/core)
1411
- 4. Create statements for data: "const count = ref(0);"
1412
- 5. create_method + add_method_body functions
1413
- 6. html_to_elements → template (no 'page' param for components)
1414
- 7. update_element wire click handlers to method UUIDs
1415
- 8. save_file with: extension='vue', template=[elementUuid], data=[methodUuids], statements=[importUuids, refUuids]
1416
- 9. **MANDATORY: Create app.js entry file** (see "CRITICAL: JavaScript Entry File" section below)
1417
- 10. Create web route for the page
1418
- 11. **MANDATORY: Add a div with id="app"** to the page using html_to_elements:
1441
+ 5. Create statements for reactive data: "const notes = ref([]);"
1442
+ 6. create_method + add_method_body for functions. Example fetchNotes body:
1443
+ \`\`\`
1444
+ const response = await Http.get('/api/notes');
1445
+ notes.value = response.data || [];
1446
+ \`\`\`
1447
+ **THEN call save_method with is_async: true** (required for methods using await)
1448
+ 7. Create statement for onMounted: "onMounted(fetchNotes);" (direct method reference, no arrow wrapper)
1449
+ 8. html_to_elements → template **with page=templateRouteUuid** (attach to the template route for editor access)
1450
+ 9. update_element → wire click handlers to method UUIDs
1451
+ 10. save_file with: extension='vue', template=[elementUuid], data=[methodUuids], statements=[importUuids, refUuids, onMountedUuid]
1452
+ - **data = method UUIDs only** (functions)
1453
+ - **statements = statement UUIDs** (imports, refs, onMounted)
1454
+ 11. **MANDATORY: Create app.js entry file** (see "CRITICAL: JavaScript Entry File" section below)
1455
+ 12. Create web route for the display page (e.g., "/notes")
1456
+ 13. **MANDATORY: Add a div with id="app"** to the display page using html_to_elements:
1419
1457
  - html_to_elements with page=routeUuid and elements='<div id="app"></div>'
1420
1458
  - This is where Vue mounts the component. Without it, nothing renders!
1421
1459
 
@@ -1424,8 +1462,33 @@ Key concepts:
1424
1462
  Use for SHOW/DISPLAY/DEMONSTRATE requests - sends instant WebSocket updates to browser.
1425
1463
  Use html_to_elements/update_element for permanent/saved changes.
1426
1464
 
1465
+ ## CRITICAL: Http Response Handling (Most Common Error)
1466
+
1467
+ **This is the #1 cause of "notes not displaying" bugs.**
1468
+
1469
+ When fetching data from API endpoints, stellify-framework's Http class returns the JSON body DIRECTLY - it does NOT wrap responses like axios does.
1470
+
1471
+ Laravel pagination returns: \`{ data: [...items], current_page: 1, per_page: 15, ... }\`
1472
+
1473
+ Since Http.get() returns this JSON directly (no axios wrapper), you access the array with ONE \`.data\`:
1474
+
1475
+ \`\`\`javascript
1476
+ // CORRECT - Http returns JSON directly, .data gets the paginated array
1477
+ const response = await Http.get('/api/notes');
1478
+ notes.value = response.data || [];
1479
+
1480
+ // WRONG - Double .data (axios habit) - returns undefined, notes stay empty!
1481
+ const response = await Http.get('/api/notes');
1482
+ notes.value = response.data.data || []; // BUG: response.data.data is undefined
1483
+ \`\`\`
1484
+
1485
+ **Why this mistake happens:** With axios, you write \`response.data.data\` because axios wraps the HTTP response (\`response.data\` unwraps axios, then \`.data\` gets the pagination array). Stellify's Http skips the wrapper, so you only need ONE \`.data\`.
1486
+
1487
+ **Symptom:** Notes exist in database, API returns them, but UI shows empty list or "No notes yet" message.
1488
+
1427
1489
  ## Common Pitfalls
1428
1490
 
1491
+ - **Vue template editor access:** Templates MUST be attached to a route for users to edit them in the visual editor. Create a separate "template route" (e.g., "notes-template") and pass its UUID to html_to_elements. This is different from the display route where the component renders.
1429
1492
  - **Stellify imports:** Use "stellify-framework" package (NOT @stellify/core)
1430
1493
  CORRECT: import { Http, List, Form } from 'stellify-framework';
1431
1494
  WRONG: import { Http } from '@stellify/core';
@@ -1434,6 +1497,44 @@ Use html_to_elements/update_element for permanent/saved changes.
1434
1497
  - add_method_body APPENDS, doesn't replace - create new method to replace
1435
1498
  - 'data' array = method UUIDs, 'statements' array = import/variable UUIDs
1436
1499
  - For buttons in forms, set inputType: "button" to prevent auto-submit
1500
+ - **Async methods:** Methods using await MUST be marked async via save_method with is_async: true
1501
+ - **onMounted:** Use direct method reference: "onMounted(fetchNotes);"
1502
+ The assembler automatically outputs lifecycle hooks after method definitions.
1503
+
1504
+ ## CRITICAL: Nullable Refs and v-if Guards
1505
+
1506
+ **This causes "Cannot read properties of null" errors.**
1507
+
1508
+ When using a nullable ref (e.g., \`const editingNote = ref(null)\`) with v-model or property access in templates, you MUST guard with an explicit v-if that checks the ref is not null.
1509
+
1510
+ **WRONG - v-else does NOT protect against null evaluation:**
1511
+ \`\`\`html
1512
+ <template v-if="!editingItem">
1513
+ <!-- view mode -->
1514
+ </template>
1515
+ <template v-else>
1516
+ <input v-model="editingItem.title" /> <!-- ERROR: editingItem could be null -->
1517
+ </template>
1518
+ \`\`\`
1519
+
1520
+ **CORRECT - explicit v-if with null check:**
1521
+ \`\`\`html
1522
+ <template v-if="!editingItem || editingItem.id !== item.id">
1523
+ <!-- view mode -->
1524
+ </template>
1525
+ <template v-if="editingItem && editingItem.id === item.id">
1526
+ <input v-model="editingItem.title" /> <!-- Safe: editingItem is guaranteed non-null -->
1527
+ </template>
1528
+ \`\`\`
1529
+
1530
+ **Why v-else fails:** Vue evaluates v-model bindings during compilation/render setup, before the v-else condition is fully applied. The explicit v-if with \`editingItem &&\` ensures the binding is only evaluated when the ref exists.
1531
+
1532
+ **Inline editing pattern (CRUD apps):**
1533
+ 1. Create ref: \`const editingItem = ref(null);\`
1534
+ 2. View template: \`v-if="!editingItem || editingItem.id !== item.id"\`
1535
+ 3. Edit template: \`v-if="editingItem && editingItem.id === item.id"\` (NOT v-else!)
1536
+ 4. Start editing: \`editingItem.value = { ...item };\`
1537
+ 5. Cancel/save: \`editingItem.value = null;\`
1437
1538
 
1438
1539
  ## Framework Capabilities (Libraries/Packages)
1439
1540
 
@@ -1520,7 +1621,7 @@ Example app.js structure:
1520
1621
  // Create MCP server
1521
1622
  const server = new Server({
1522
1623
  name: 'stellify-mcp',
1523
- version: '0.1.24',
1624
+ version: '0.1.25',
1524
1625
  }, {
1525
1626
  capabilities: {
1526
1627
  tools: {},
@@ -1658,15 +1759,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1658
1759
  };
1659
1760
  }
1660
1761
  case 'delete_method': {
1661
- const { uuid } = args;
1662
- const result = await stellify.deleteMethod(uuid);
1762
+ const { file, uuid } = args;
1763
+ const result = await stellify.deleteMethod(file, uuid);
1663
1764
  return {
1664
1765
  content: [
1665
1766
  {
1666
1767
  type: 'text',
1667
1768
  text: JSON.stringify({
1668
1769
  success: true,
1669
- message: `Deleted method ${uuid}`,
1770
+ message: `Deleted method ${uuid} from file ${file}`,
1670
1771
  data: result,
1671
1772
  }, null, 2),
1672
1773
  },
@@ -2008,15 +2109,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2008
2109
  };
2009
2110
  }
2010
2111
  case 'delete_file': {
2011
- const { uuid } = args;
2012
- const result = await stellify.deleteFile(uuid);
2112
+ const { directory, uuid } = args;
2113
+ const result = await stellify.deleteFile(directory, uuid);
2013
2114
  return {
2014
2115
  content: [
2015
2116
  {
2016
2117
  type: 'text',
2017
2118
  text: JSON.stringify({
2018
2119
  success: true,
2019
- message: `Deleted file ${uuid}`,
2120
+ message: `Deleted file ${uuid} from directory ${directory}`,
2020
2121
  data: result,
2021
2122
  }, null, 2),
2022
2123
  },
@@ -76,10 +76,10 @@ export declare class StellifyClient {
76
76
  searchFiles(params: SearchFilesParams): Promise<any>;
77
77
  getFile(file: string): Promise<any>;
78
78
  saveFile(file: string, data: any): Promise<any>;
79
- deleteFile(file: string): Promise<any>;
79
+ deleteFile(directory: string, file: string): Promise<any>;
80
80
  getMethod(method: string): Promise<any>;
81
81
  saveMethod(method: string, data: any): Promise<any>;
82
- deleteMethod(method: string): Promise<any>;
82
+ deleteMethod(file: string, method: string): Promise<any>;
83
83
  createStatement(params: {
84
84
  file?: string;
85
85
  method?: string;
@@ -43,8 +43,8 @@ export class StellifyClient {
43
43
  const response = await this.client.put(`/file/${file}`, data);
44
44
  return response.data;
45
45
  }
46
- async deleteFile(file) {
47
- const response = await this.client.delete(`/file/${file}`);
46
+ async deleteFile(directory, file) {
47
+ const response = await this.client.delete(`/file/${directory}/${file}`);
48
48
  return response.data;
49
49
  }
50
50
  async getMethod(method) {
@@ -55,8 +55,8 @@ export class StellifyClient {
55
55
  const response = await this.client.put(`/method/${method}`, data);
56
56
  return response.data;
57
57
  }
58
- async deleteMethod(method) {
59
- const response = await this.client.delete(`/method/${method}`);
58
+ async deleteMethod(file, method) {
59
+ const response = await this.client.delete(`/method/${file}/${method}`);
60
60
  return response.data;
61
61
  }
62
62
  async createStatement(params) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellisoft/stellify-mcp",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "mcpName": "io.github.MattStellisoft/stellify-mcp",
5
5
  "description": "MCP server for Stellify - AI-native code generation platform",
6
6
  "main": "dist/index.js",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/Stellify-Software-Ltd/stellify-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.1.24",
9
+ "version": "0.1.25",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@stellisoft/stellify-mcp",
14
- "version": "0.1.24",
14
+ "version": "0.1.25",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },