@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 +125 -24
- package/dist/stellify-client.d.ts +2 -2
- package/dist/stellify-client.js +4 -4
- package/package.json +1 -1
- package/server.json +2 -2
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
|
|
1408
|
-
-
|
|
1409
|
-
-
|
|
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
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
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.
|
|
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;
|
package/dist/stellify-client.js
CHANGED
|
@@ -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
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.
|
|
9
|
+
"version": "0.1.25",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@stellisoft/stellify-mcp",
|
|
14
|
-
"version": "0.1.
|
|
14
|
+
"version": "0.1.25",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|