@stellisoft/stellify-mcp 0.1.21 → 0.1.23

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 (3) hide show
  1. package/dist/index.js +121 -432
  2. package/package.json +1 -1
  3. package/server.json +2 -2
package/dist/index.js CHANGED
@@ -17,223 +17,6 @@ const stellify = new StellifyClient({
17
17
  apiUrl: API_URL,
18
18
  apiToken: API_TOKEN,
19
19
  });
20
- // =============================================================================
21
- // STELLIFY AI WORKFLOW GUIDE
22
- // =============================================================================
23
- // Stellify stores code as structured JSON, not text files.
24
- // This enables surgical AI edits at the statement level.
25
- //
26
- // -----------------------------------------------------------------------------
27
- // REAL-TIME UI BROADCASTING (use this for demonstrations!)
28
- // -----------------------------------------------------------------------------
29
- // When users ask you to SHOW, DISPLAY, BUILD, or DEMONSTRATE anything visually,
30
- // use broadcast_element_command FIRST. This sends real-time updates via WebSocket
31
- // directly to the user's browser - no database storage, instant feedback.
32
- //
33
- // Use broadcast_element_command for:
34
- // - Showing the user something visually
35
- // - Building UI elements as you discuss them
36
- // - Sending messages/content to the browser
37
- // - Any "live" or "real-time" interaction
38
- //
39
- // Use html_to_elements/update_element for:
40
- // - Permanent changes that should persist
41
- // - Building components that will be saved
42
- //
43
- // SUPPORTED FILE TYPES:
44
- // - PHP: Controllers, Models, Middleware, Classes
45
- // - JavaScript/TypeScript: JS files, Vue SFCs
46
- // - UI: Elements (HTML structure stored as JSON)
47
- //
48
- // -----------------------------------------------------------------------------
49
- // GENERAL WORKFLOW (applies to all file types)
50
- // -----------------------------------------------------------------------------
51
- // 1. Create file skeleton (create_file) - empty structure, no methods yet
52
- // 2. Add methods (create_method) - creates signature only
53
- // 3. Add method bodies (add_method_body) - implementation code
54
- // 4. Add statements (create_statement + add_statement_code) - for non-method code
55
- // 5. Save file (save_file) - finalize with all references
56
- //
57
- // -----------------------------------------------------------------------------
58
- // PHP EXAMPLE: Creating a Controller
59
- // -----------------------------------------------------------------------------
60
- // 1. create_file: type='controller', name='UserController'
61
- // 2. create_method: name='store', parameters=[{name:'request', type:'Request'}]
62
- // 3. add_method_body: code='return response()->json($request->all());'
63
- //
64
- // -----------------------------------------------------------------------------
65
- // VUE COMPONENT WORKFLOW (step-by-step)
66
- // -----------------------------------------------------------------------------
67
- // Vue components combine UI elements with reactive data. Follow this order:
68
- //
69
- // 1. get_project - Find the 'js' directory UUID
70
- // 2. create_file - type='js', extension='vue' in js directory
71
- // 3. Create statements for IMPORTS and DATA (each needs create_statement + add_statement_code):
72
- // - "import { ref } from 'vue';" ← REQUIRED for using ref()
73
- // - "const count = ref(0);"
74
- // NOTE: Vue imports are NOT auto-generated. You must add them manually.
75
- // 4. create_method - Creates method signature (returns UUID)
76
- // add_method_body - Add implementation: "count.value++;"
77
- // 5. html_to_elements - Convert template HTML to elements (no 'page' needed)
78
- // NOTE: Vue bindings like {{ count }} auto-create statements linked to elements
79
- // 6. update_element - Wire event handlers (e.g., click → method UUID)
80
- // 7. save_file - Finalize with:
81
- // - extension: 'vue'
82
- // - template: [rootElementUuid] (from html_to_elements)
83
- // - data: [methodUuid] (METHOD UUIDs only!)
84
- // - statements: [importStmtUuid, countStmtUuid] (STATEMENT UUIDs - imports, refs)
85
- //
86
- // Vue SFC file structure:
87
- // - extension: 'vue'
88
- // - template: Array of root element UUIDs (<template> section)
89
- // - data: Array of METHOD UUIDs only (<script setup> functions)
90
- // - statements: Array of STATEMENT UUIDs (<script setup> imports, variables, refs)
91
- // - includes: Array of file UUIDs to import
92
- //
93
- // -----------------------------------------------------------------------------
94
- // VUE COMPONENT + ROUTE PATTERN (for visual editing)
95
- // -----------------------------------------------------------------------------
96
- // When building Vue components, use TWO routes to enable visual editing:
97
- //
98
- // 1. TEMPLATE ROUTE - Holds the component's UI elements for editing
99
- // - create_route: name='NotesTemplate', path='/notes-template', type='web'
100
- // - html_to_elements: page=templateRouteUuid, elements='<div>...</div>'
101
- // - Users can visually edit these elements in the route editor
102
- //
103
- // 2. DISPLAY ROUTE - The actual page that renders the component
104
- // - create_route: name='Notes', path='/notes', type='web'
105
- // - html_to_elements: page=displayRouteUuid, elements='<NotesApp />'
106
- // - This embeds the Vue component on the page
107
- //
108
- // 3. VUE COMPONENT FILE - Links to template route elements
109
- // - create_file: type='js', extension='vue', name='NotesApp'
110
- // - save_file: template=[elementUuidsFromTemplateRoute]
111
- //
112
- // WHY THIS PATTERN?
113
- // - Template elements need a route to be viewable/editable in the UI
114
- // - The display route keeps the clean component embedding pattern
115
- // - Component logic (methods, state) stays in the .vue file
116
- //
117
- // EXAMPLE WORKFLOW:
118
- // 1. Create template route: '/notes-template' (for editing)
119
- // 2. Create display route: '/notes' (for viewing)
120
- // 3. html_to_elements on template route (creates editable elements)
121
- // 4. html_to_elements on display route with '<NotesApp />'
122
- // 5. create_file for NotesApp.vue
123
- // 6. Add methods, statements, wire events
124
- // 7. save_file with template pointing to template route's root element
125
- //
126
- // -----------------------------------------------------------------------------
127
- // ELEMENT EVENT HANDLERS (for frontend files)
128
- // -----------------------------------------------------------------------------
129
- // Elements can have these event properties (value is method UUID):
130
- // - click: Fires on click (@click)
131
- // - submit: Fires on form submit (@submit)
132
- // - change: Fires on input change (@change)
133
- // - input: Fires on input in real-time (@input)
134
- // - focus: Fires when element receives focus (@focus)
135
- // - blur: Fires when element loses focus (@blur)
136
- // - keydown: Fires on key press (@keydown)
137
- // - keyup: Fires on key release (@keyup)
138
- // - mouseenter: Fires on mouse enter (@mouseenter)
139
- // - mouseleave: Fires on mouse leave (@mouseleave)
140
- //
141
- // -----------------------------------------------------------------------------
142
- // STELLIFY FRAMEWORK (frontend library for Vue/JS files)
143
- // -----------------------------------------------------------------------------
144
- // Stellify Framework is an AI-friendly frontend library with constrained APIs.
145
- // Use these modules in Vue components for common frontend tasks.
146
- //
147
- // IMPORT PATTERN:
148
- // import { Form, Http, Table } from 'stellify-framework'
149
- //
150
- // DATA & FORMS:
151
- // Form.create({name:'',email:''}).validate({...}).store('/api/users')
152
- // Table.create(data).addColumn('name').sort('name').paginate(10)
153
- // List.create(items).add(item).remove(id).filter(fn).map(fn)
154
- // Tree.create().setRoot(data).addChild(parentId,child).traverse(fn)
155
- //
156
- // NETWORK:
157
- // Http.create('/api').withToken(t).get('/users').post('/users',data)
158
- // Socket.create('wss://...').on('message',fn).connect().send(data)
159
- // Auth.create('/api').login(creds).logout().getUser().isAuthenticated()
160
- // Stream.create('/api/chat').onChunk(fn).onComplete(fn).post(data)
161
- //
162
- // GRAPHICS:
163
- // Svg.create(800,600).rect(0,0,100,50).circle(50,50,20).text('Hi',10,10)
164
- // Canvas.create(800,600).rect(0,0,100,50).circle(50,50,20).toDataURL()
165
- // Graph.create().addNode('a').addNode('b').addEdge('a','b').layout('force')
166
- // Scale.linear().domain([0,100]).range([0,500]).value(50) // returns 250
167
- // Motion.tween(0,100,{duration:500}).onUpdate(fn).start()
168
- //
169
- // PLATFORM:
170
- // Router.create().register('/users',component).navigate('/users')
171
- // Storage.local().set('key',val).get('key').remove('key')
172
- // Events.create().on('event',fn).emit('event',data)
173
- // Clipboard.copy('text').paste()
174
- // Notify.request().send('Title',{body:'Message'})
175
- // Geo.getPosition().then(pos=>...).watchPosition(fn)
176
- // Media.selectFile({accept:'image/*'}).resize(800,600).toBase64()
177
- // DB.create('mydb').store({name:'items'}).open().put('items',obj)
178
- // Worker.fromFunction(fn).run(data).terminate()
179
- //
180
- // AI & LANGUAGE:
181
- // Speech.create().onResult(fn).listen({continuous:true})
182
- // Speech.create().speak('Hello',{voice:'...'})
183
- // Chat.create().addUser('Hi').addAssistant('Hello').getMessages()
184
- // Embed.create().store('id',vector,meta).nearest(queryVec,5)
185
- // Diff.lines(old,new) // [{type:'equal'|'insert'|'delete',value:'...'}]
186
- //
187
- // UTILITIES:
188
- // Time.now().format('YYYY-MM-DD').add(7,'days').relative()
189
- //
190
- // KEY METHODS PER MODULE (max 7 each - AI-friendly constraint):
191
- // Form: create,set,get,validate,store,update,delete
192
- // Table: create,setData,addColumn,sort,filter,paginate
193
- // Http: create,get,post,put,delete,withToken
194
- // Stream: create,post,onChunk,onComplete,abort,getBuffer
195
- // Speech: create,listen,speak,stopListening,getVoices,onResult
196
- // Chat: create,addMessage,getHistory,clear,fork,truncate
197
- // Embed: create,store,compare,nearest,search,toJSON
198
- // Diff: chars,words,lines,apply,createPatch,similarity
199
- //
200
- // -----------------------------------------------------------------------------
201
- // COMMON PITFALLS - AVOID THESE MISTAKES
202
- // -----------------------------------------------------------------------------
203
- // 1. v-model requires ref(), NOT Form class
204
- // WRONG: const form = Form.create({title: ''}) with v-model="form.title"
205
- // RIGHT: const formData = ref({title: ''}) with v-model="formData.title"
206
- //
207
- // 2. List.from() returns List instance, not array - use .toArray() for v-for
208
- // WRONG: notes.value = List.from(response.data)
209
- // RIGHT: notes.value = List.from(response.data).toArray()
210
- //
211
- // 3. add_method_body APPENDS, doesn't replace - create new method to replace
212
- //
213
- // 4. Use 'inputType' not 'type' for HTML type attribute on elements
214
- //
215
- // 5. Statements go in 'statements' array, methods go in 'data' array in save_file
216
- //
217
- // 6. Always wire click handlers to METHOD UUIDs, not file UUIDs
218
- //
219
- // 7. For buttons in forms, set inputType: "button" to prevent auto-submit
220
- //
221
- // -----------------------------------------------------------------------------
222
- // ERROR HANDLING
223
- // -----------------------------------------------------------------------------
224
- // If a tool call fails, check:
225
- // - UUID validity: Is the file/method/element UUID correct and exists?
226
- // - Required fields: Did you provide all required parameters?
227
- // - Order of operations: Did you create the parent before the child?
228
- // - Array contents: Are you passing statement UUIDs to 'statements' (not 'data')?
229
- //
230
- // Common error scenarios:
231
- // - "File not found" → The file UUID is invalid or was deleted
232
- // - "Method not found" → The method UUID doesn't exist in that file
233
- // - "Invalid element type" → Use valid types like s-wrapper, s-input, s-form
234
- // - Empty response → Operation succeeded but returned no data (normal for deletes)
235
- //
236
- // =============================================================================
237
20
  // Define MCP tools
238
21
  // Stellify Framework API - full method reference for AI code generation
239
22
  const STELLIFY_FRAMEWORK_API = {
@@ -289,6 +72,10 @@ Use this tool when you need to:
289
72
  - Verify method names before generating code
290
73
  - Understand the full API surface
291
74
 
75
+ IMPORTANT - Stellify Framework Import:
76
+ The npm package is "stellify-framework" (NOT @stellify/core).
77
+ Import like: import { Http, List, Form } from 'stellify-framework';
78
+
292
79
  IMPORTANT - List class and Vue reactivity:
293
80
  The List class methods return List instances, NOT plain arrays.
294
81
  Vue's v-for directive cannot iterate over List instances directly.
@@ -632,39 +419,9 @@ Example - Remove duplicate/unwanted statements:
632
419
  },
633
420
  {
634
421
  name: 'create_route',
635
- description: `Create a new route/page in a Stellify project.
636
-
637
- IMPORTANT - WIRING ROUTES TO CONTROLLERS:
638
- For API routes to execute code, you MUST connect them to a controller and method:
639
- - controller: UUID of the controller file (e.g., NoteController)
640
- - controller_method: UUID of the method to execute (e.g., index, store, update, destroy)
641
-
642
- Without these fields, the route exists but won't execute any code!
643
-
644
- EXAMPLE - Create an API route wired to a controller:
645
- {
646
- "project_id": "project-uuid",
647
- "name": "notes.index",
648
- "path": "/api/notes",
649
- "method": "GET",
650
- "type": "api",
651
- "controller": "controller-file-uuid",
652
- "controller_method": "index-method-uuid"
653
- }
654
-
655
- WORKFLOW for API endpoints:
656
- 1. Create controller with create_file (type: "controller") or create_resources
657
- 2. Create methods with create_method + add_method_body
658
- 3. Create route with create_route, passing controller and controller_method UUIDs
422
+ description: `Create a route/page. For API routes, pass controller and controller_method UUIDs to wire execution.
659
423
 
660
- ROUTE PARAMETERS:
661
- Route parameters like {id} in "/api/notes/{id}" are automatically injected into controller method parameters when the parameter name matches.
662
-
663
- Example: Route "/api/notes/{id}" (DELETE) with controller method destroy($id)
664
- The $id parameter receives the value from the URL automatically.
665
-
666
- When creating methods with create_method, include the parameter:
667
- { "name": "destroy", "parameters": [{ "name": "id", "datatype": "int" }] }`,
424
+ Route params like {id} auto-inject into controller method parameters when names match.`,
668
425
  inputSchema: {
669
426
  type: 'object',
670
427
  properties: {
@@ -883,55 +640,13 @@ Generates: <div class="card p-4" v-for="note in notes" :key="note.id">`,
883
640
  },
884
641
  {
885
642
  name: 'update_element',
886
- description: `Update an existing UI element (for Elements v2).
887
-
888
- Use standard HTML attributes directly (placeholder, href, src, type, etc.).
889
-
890
- Special Stellify fields:
891
- - name: Element name in editor
892
- - type: Element type (s-wrapper, s-input, etc.)
893
- - locked: Prevent editing (boolean)
894
- - tag: HTML tag (div, input, button, etc.)
895
- - classes: CSS classes array ["class1", "class2"]
896
- - text: Element text content
897
-
898
- V-MODEL BINDING (for s-input elements):
899
- - variable: Set this to bind v-model to a reactive variable
900
- - Example: { "variable": "formData.title" } renders as <input v-model="formData.title" />
901
- - IMPORTANT: The variable must reference a Vue ref() object, NOT a Form class instance
902
- - CORRECT: const formData = ref({ title: '', content: '' }) → v-model="formData.title"
903
- - WRONG: const form = Form.create({ title: '' }) → Form class is not reactive for v-model
904
-
905
- INPUT TYPE ATTRIBUTE:
906
- - Use 'inputType' (not 'type') to set the HTML type attribute on buttons/inputs
907
- - Example: { "inputType": "button" } renders as type="button"
908
- - Example: { "inputType": "textarea" } renders as <textarea> instead of <input>
909
- - For buttons inside <form> elements, always set inputType: "button" to prevent form submission on click
910
-
911
- EVENT HANDLERS (set value to method UUID):
912
- - click: @click - buttons, links, any clickable element
913
- - submit: @submit - form submission
914
- - change: @change - input/select value changed (on blur)
915
- - input: @input - input value changing (real-time, as user types)
916
- - focus: @focus - element receives focus
917
- - blur: @blur - element loses focus
918
- - keydown: @keydown - key pressed down
919
- - keyup: @keyup - key released
920
- - mouseenter: @mouseenter - mouse enters element
921
- - mouseleave: @mouseleave - mouse leaves element
922
-
923
- EVENT HANDLER ARGUMENTS:
924
- When wiring click handlers that need arguments (e.g., from v-for loops), use clickArgs:
925
- - { "click": "delete-method-uuid", "clickArgs": "item.id" } → @click="deleteItem(item.id)"
926
- - { "click": "edit-method-uuid", "clickArgs": "item" } → @click="editItem(item)"
927
-
928
- Example wiring a button click to a method:
929
- {
930
- "uuid": "button-element-uuid",
931
- "data": {
932
- "click": "increment-method-uuid"
933
- }
934
- }`,
643
+ description: `Update a UI element's attributes.
644
+
645
+ Pass data object with: tag, classes (array), text, variable (for v-model), and event handlers (click, submit, etc. = method UUID).
646
+
647
+ Key fields: inputType (not 'type') for button/input HTML type. clickArgs for handler arguments in v-for loops.
648
+
649
+ Event handlers: click, submit, change, input, focus, blur, keydown, keyup, mouseenter, mouseleave.`,
935
650
  inputSchema: {
936
651
  type: 'object',
937
652
  properties: {
@@ -1020,37 +735,11 @@ Note: To reorder elements, use update_element to modify the parent element's 'da
1020
735
  },
1021
736
  {
1022
737
  name: 'html_to_elements',
1023
- description: `Convert HTML to Stellify elements in ONE operation. This is the FASTEST way to build interfaces!
1024
-
1025
- This will:
1026
- 1. Parse the HTML structure
1027
- 2. Create all elements with proper nesting and types
1028
- 3. Preserve all attributes, classes, text content
1029
- 4. Auto-detect Vue bindings ({{ variable }}) and create linked statements
1030
- 5. Return element UUIDs to use in save_file template array
1031
-
1032
- Element type mapping:
1033
- - button, input, textarea, select → s-input
1034
- - div, span, p, section, etc. → s-wrapper
1035
- - form → s-form
1036
- - img, video, audio → s-media
1037
-
1038
- VUE BINDING AUTO-DETECTION:
1039
- Text like {{ count }} is automatically detected and:
1040
- - A statement is created with the binding code
1041
- - The statement UUID is added to the element's 'statements' array
1042
- - You still need to create the reactive data source separately (const count = ref(0))
1043
-
1044
- For Vue components: Omit 'page' - elements are created standalone for the component template.
1045
- For page content: Provide 'page' (route UUID) to attach elements directly.
1046
-
1047
- ICONS - Best practices:
1048
- - Prefer SVG icons or icon fonts (Heroicons, Font Awesome) over emoji
1049
- - Use HTML entities where available (e.g., &times; for ×)
1050
- - Avoid raw emoji characters as they may have encoding issues
1051
- - Example: <button><svg>...</svg></button> instead of <button>🗑️</button>
1052
-
1053
- IMPORTANT: Use the returned root element UUID in save_file's template array.`,
738
+ description: `Convert HTML to Stellify elements. Returns element UUIDs to use in save_file template array.
739
+
740
+ Auto-detects Vue bindings ({{ var }}). For Vue components, omit 'page'. For pages, provide route UUID.
741
+
742
+ Prefer SVG icons over emoji (encoding issues).`,
1054
743
  inputSchema: {
1055
744
  type: 'object',
1056
745
  properties: {
@@ -1344,35 +1033,11 @@ IMPORTANT: Check existing directories first using get_project and get_directory
1344
1033
  },
1345
1034
  {
1346
1035
  name: 'broadcast_element_command',
1347
- description: `Broadcast a real-time command to update UI elements via WebSocket.
1348
-
1349
- IMPORTANT: USE THIS TOOL FIRST when the user asks you to:
1350
- - Show, display, or demonstrate something visually
1351
- - Update, change, or modify what's on screen
1352
- - Build or create UI elements for demonstration
1353
- - Send messages or content to the browser
1354
- - Do anything "live" or "in real-time"
1355
-
1356
- This is the PRIMARY tool for real-time AI-to-browser communication. It pushes changes instantly to all connected browsers. Changes are EPHEMERAL (not saved to database) - perfect for demonstrations, live content, and interactive sessions.
1357
-
1358
- ACTIONS:
1359
- - update: Modify an existing element's attributes (text, classes, styles, etc.)
1360
- - create: Create a new ephemeral element (provide any UUID string you want)
1361
- - batch: Modify multiple elements at once
1362
- - delete: Remove an element from the UI state
1036
+ description: `Push real-time UI updates via WebSocket. Use for SHOW/DISPLAY/DEMONSTRATE requests.
1363
1037
 
1364
- TO CREATE EPHEMERAL ELEMENTS (not stored in database):
1365
- 1. First, use action="create" with any UUID (e.g., "msg-001") and full element structure in changes
1366
- 2. Then, use action="update" on the PARENT element to add your new UUID to its "data" array
1038
+ Actions: update (modify element), create (ephemeral element), batch (multiple updates), delete.
1367
1039
 
1368
- Example - Update existing element text:
1369
- { action: "update", element: "existing-uuid", changes: { text: "Hello world!", classes: ["p-4", "bg-blue-500"] } }
1370
-
1371
- Example - Create ephemeral child element:
1372
- Step 1: { action: "create", element: "my-new-element", changes: { type: "s-wrapper", tag: "div", text: "I exist!", classes: ["p-2", "bg-green-500"] } }
1373
- Step 2: { action: "update", element: "parent-uuid", changes: { data: ["my-new-element"] } }
1374
-
1375
- For PERSISTENT changes (saved to database), use update_element or html_to_elements instead.`,
1040
+ Changes are EPHEMERAL (not saved). For persistent changes, use update_element or html_to_elements.`,
1376
1041
  inputSchema: {
1377
1042
  type: 'object',
1378
1043
  properties: {
@@ -1407,80 +1072,13 @@ For PERSISTENT changes (saved to database), use update_element or html_to_elemen
1407
1072
  },
1408
1073
  {
1409
1074
  name: 'create_resources',
1410
- description: `Scaffold a complete resource stack in ONE operation. Creates Model, Controller, Service, and Migration together.
1075
+ description: `Scaffold Model, Controller, Service, and Migration in ONE operation.
1411
1076
 
1412
- This is the FASTEST way to bootstrap new features! Instead of 20+ individual API calls, create everything at once.
1077
+ Creates: Model ($fillable, $casts, relationships), Controller (CRUD actions), Service (optional), Migration.
1413
1078
 
1414
- WHAT IT CREATES:
1415
- - Model: With $fillable, $casts, and relationship methods
1416
- - Controller: With index, store, show, update, destroy actions
1417
- - Service (optional): Business logic layer with list, find, create, update, delete methods
1418
- - Migration: With proper column types based on field definitions
1079
+ IMPORTANT: Routes are NOT auto-wired. After creation, use create_route with the returned controller UUID and method UUIDs.
1419
1080
 
1420
- EXAMPLE - Create a User resource:
1421
- {
1422
- "name": "User",
1423
- "fields": [
1424
- { "name": "name", "type": "string" },
1425
- { "name": "email", "type": "string", "unique": true },
1426
- { "name": "password", "type": "string" },
1427
- { "name": "is_active", "type": "boolean", "default": true }
1428
- ],
1429
- "relationships": [
1430
- { "type": "hasMany", "model": "Post" }
1431
- ],
1432
- "controller": true,
1433
- "service": true,
1434
- "migration": true
1435
- }
1436
-
1437
- FIELD TYPES:
1438
- - string, text, longtext (text fields)
1439
- - integer, int, bigint (numbers)
1440
- - boolean, bool (true/false)
1441
- - float, double, decimal (decimals)
1442
- - date, datetime, timestamp (dates)
1443
- - json (JSON/array data)
1444
- - email (string with email validation)
1445
-
1446
- FIELD OPTIONS:
1447
- - nullable: Allow NULL values
1448
- - unique: Add unique constraint
1449
- - required: Require in validation (default: true for store)
1450
- - default: Default value
1451
- - max: Maximum length/value
1452
-
1453
- RELATIONSHIP TYPES:
1454
- - hasOne: One-to-one (User hasOne Profile)
1455
- - hasMany: One-to-many (User hasMany Posts)
1456
- - belongsTo: Inverse of hasOne/hasMany (Post belongsTo User)
1457
- - belongsToMany: Many-to-many (User belongsToMany Roles)
1458
-
1459
- IMPORTANT - WIRING ROUTES TO CONTROLLERS:
1460
- This tool creates controller methods but does NOT automatically wire routes to them.
1461
- After calling create_resources, you must MANUALLY wire routes using create_route:
1462
-
1463
- 1. Note the returned controller UUID and method UUIDs from the response
1464
- 2. For each API route, call create_route with:
1465
- - controller: the controller file UUID
1466
- - controller_method: the specific method UUID (index, store, update, destroy)
1467
-
1468
- Example response structure:
1469
- {
1470
- "controller": {
1471
- "uuid": "controller-uuid",
1472
- "methods": [
1473
- { "uuid": "index-method-uuid", "name": "index" },
1474
- { "uuid": "store-method-uuid", "name": "store" },
1475
- ...
1476
- ]
1477
- }
1478
- }
1479
-
1480
- Then create routes:
1481
- create_route({ path: "/api/notes", method: "GET", controller: "controller-uuid", controller_method: "index-method-uuid" })
1482
-
1483
- Returns UUIDs for all created files so you can customize them further if needed.`,
1081
+ Response includes controller.methods array with {uuid, name} for each action (index, store, update, destroy).`,
1484
1082
  inputSchema: {
1485
1083
  type: 'object',
1486
1084
  properties: {
@@ -1786,6 +1384,49 @@ Key concepts:
1786
1384
  - Vue components link to UI elements via the 'template' field
1787
1385
  - Event handlers (click, submit) wire UI elements to methods by UUID
1788
1386
 
1387
+ ## General Workflow (all file types)
1388
+
1389
+ 1. create_file → empty shell, returns file UUID
1390
+ 2. create_method → signature only, returns method UUID
1391
+ 3. add_method_body → implementation code
1392
+ 4. create_statement + add_statement_code → for imports, variables, refs
1393
+ 5. save_file → finalize with template/data/statements arrays
1394
+
1395
+ ## Vue Component Workflow
1396
+
1397
+ 1. get_project → find 'js' directory UUID (or create it)
1398
+ 2. create_file → type='js', extension='vue' for the component
1399
+ 3. Create statements for imports:
1400
+ - "import { ref } from 'vue';" (REQUIRED for ref())
1401
+ - "import { Http, List } from 'stellify-framework';" (for Stellify classes)
1402
+ NOTE: The npm package is "stellify-framework" (NOT @stellify/core)
1403
+ 4. Create statements for data: "const count = ref(0);"
1404
+ 5. create_method + add_method_body → functions
1405
+ 6. html_to_elements → template (no 'page' param for components)
1406
+ 7. update_element → wire click handlers to method UUIDs
1407
+ 8. save_file with: extension='vue', template=[elementUuid], data=[methodUuids], statements=[importUuids, refUuids]
1408
+ 9. **MANDATORY: Create app.js entry file** (see "CRITICAL: JavaScript Entry File" section below)
1409
+ 10. Create web route for the page
1410
+ 11. **MANDATORY: Add a div with id="app"** to the page using html_to_elements:
1411
+ - html_to_elements with page=routeUuid and elements='<div id="app"></div>'
1412
+ - This is where Vue mounts the component. Without it, nothing renders!
1413
+
1414
+ ## Real-Time UI (broadcast_element_command)
1415
+
1416
+ Use for SHOW/DISPLAY/DEMONSTRATE requests - sends instant WebSocket updates to browser.
1417
+ Use html_to_elements/update_element for permanent/saved changes.
1418
+
1419
+ ## Common Pitfalls
1420
+
1421
+ - **Stellify imports:** Use "stellify-framework" package (NOT @stellify/core)
1422
+ CORRECT: import { Http, List, Form } from 'stellify-framework';
1423
+ WRONG: import { Http } from '@stellify/core';
1424
+ - v-model requires ref(), NOT Form class: const formData = ref({title: ''})
1425
+ - List.from() returns List, not array - use .toArray() for v-for
1426
+ - add_method_body APPENDS, doesn't replace - create new method to replace
1427
+ - 'data' array = method UUIDs, 'statements' array = import/variable UUIDs
1428
+ - For buttons in forms, set inputType: "button" to prevent auto-submit
1429
+
1789
1430
  ## Framework Capabilities (Libraries/Packages)
1790
1431
 
1791
1432
  **CRITICAL: You write BUSINESS LOGIC only. Capabilities are installed packages/libraries (Sanctum, Stripe, AWS SDK, etc.) that Stellify provides. You CANNOT create these by writing code.**
@@ -1817,18 +1458,66 @@ Examples of capabilities (packages you cannot write):
1817
1458
 
1818
1459
  When building features, group related files by passing a "module" parameter.
1819
1460
 
1820
- **WORKFLOW:** Simply include the 'module' parameter when creating files or routes:
1821
-
1822
1461
  - create_file(..., module: "blog-posts") - auto-groups file
1823
1462
  - create_route(..., module: "blog-posts") - auto-groups route
1824
1463
 
1825
1464
  Modules are auto-created if they don't exist. This helps users see all code related to a feature grouped together.
1826
1465
 
1827
- Example module names: "user-auth", "blog-posts", "product-catalog", "order-management", "admin-dashboard"`;
1466
+ ## CRITICAL: JavaScript Entry File (app.js)
1467
+
1468
+ **You MUST have a JS entry file to register Vue components for use on pages.**
1469
+
1470
+ ### First component in a project:
1471
+ 1. Create app.js in the 'js' directory:
1472
+ - create_file with type='js', extension='js', name='app'
1473
+ 2. Add statements:
1474
+ - "import { createApp } from 'vue';"
1475
+ - "import NotesApp from './NotesApp.vue';"
1476
+ - "createApp(NotesApp).mount('#app');"
1477
+ 3. save_file with all statement UUIDs
1478
+
1479
+ ### Adding more components (app.js already exists):
1480
+ 1. **search_files** for "app" to find existing app.js
1481
+ 2. **get_file** to retrieve current statements
1482
+ 3. Add ONLY the new import statement:
1483
+ - "import Counter from './Counter.vue';"
1484
+ 4. Update the mount code to register the new component:
1485
+ - Create new statement: "app.component('Counter', Counter);"
1486
+ - Or recreate the initialization to include all components
1487
+ 5. save_file with updated statements array
1488
+
1489
+ **DO NOT create duplicate app.js files or duplicate createApp imports!**
1490
+
1491
+ ### Page mount point (div#app):
1492
+ Each page that uses Vue components needs a \`<div id="app"></div>\`.
1493
+
1494
+ - **First time on a page:** html_to_elements(page=routeUuid, elements='<div id="app"></div>')
1495
+ - **Page already has it:** Do NOT add another one. Check with get_route first if unsure.
1496
+
1497
+ **Without app.js AND div#app, Vue components will NOT render!**
1498
+
1499
+ Example app.js with multiple components:
1500
+ \`\`\`javascript
1501
+ import { createApp } from 'vue';
1502
+ import NotesApp from './NotesApp.vue';
1503
+ import Counter from './Counter.vue';
1504
+
1505
+ const app = createApp({});
1506
+ app.component('NotesApp', NotesApp);
1507
+ app.component('Counter', Counter);
1508
+ app.mount('#app');
1509
+ \`\`\`
1510
+
1511
+ ## Efficiency Tips
1512
+
1513
+ - **Move elements between routes:** Use \`update_element\` to change \`routeParent\` - don't delete/recreate
1514
+ - **Reparent elements:** Update \`parent\` attribute instead of recreating
1515
+ - **Reorder children:** Update parent's \`data\` array with new UUID order
1516
+ - Always prefer updating over deleting and recreating`;
1828
1517
  // Create MCP server
1829
1518
  const server = new Server({
1830
1519
  name: 'stellify-mcp',
1831
- version: '0.1.21',
1520
+ version: '0.1.23',
1832
1521
  }, {
1833
1522
  capabilities: {
1834
1523
  tools: {},
@@ -2270,7 +1959,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2270
1959
  }
2271
1960
  case 'save_statement': {
2272
1961
  const { uuid, ...data } = args;
2273
- const result = await stellify.saveStatement(uuid, data);
1962
+ const result = await stellify.saveStatement(uuid, { uuid, ...data });
2274
1963
  return {
2275
1964
  content: [
2276
1965
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellisoft/stellify-mcp",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
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.21",
9
+ "version": "0.1.23",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@stellisoft/stellify-mcp",
14
- "version": "0.1.21",
14
+ "version": "0.1.23",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },