@stellisoft/stellify-mcp 0.1.19 → 0.1.22

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
@@ -17,187 +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
20
  // Define MCP tools
202
21
  // Stellify Framework API - full method reference for AI code generation
203
22
  const STELLIFY_FRAMEWORK_API = {
@@ -253,6 +72,14 @@ Use this tool when you need to:
253
72
  - Verify method names before generating code
254
73
  - Understand the full API surface
255
74
 
75
+ IMPORTANT - List class and Vue reactivity:
76
+ The List class methods return List instances, NOT plain arrays.
77
+ Vue's v-for directive cannot iterate over List instances directly.
78
+
79
+ When assigning to a Vue ref that will be used with v-for, call .toArray():
80
+ - CORRECT: notes.value = List.from(response.data).toArray();
81
+ - INCORRECT (v-for won't work): notes.value = List.from(response.data);
82
+
256
83
  Example response:
257
84
  {
258
85
  "Form": ["create", "set", "get", "validate", "store", "update", "delete", ...],
@@ -434,7 +261,14 @@ Example response includes:
434
261
  },
435
262
  {
436
263
  name: 'add_method_body',
437
- description: 'Parse and add PHP code to a method body. Provide the method implementation code (without the function declaration). Stellify will parse it into structured statements.',
264
+ description: `Parse and add PHP code to a method body. Provide the method implementation code (without the function declaration). Stellify will parse it into structured statements.
265
+
266
+ IMPORTANT: This APPENDS to existing method statements. To REPLACE a method's code:
267
+ 1. Create a NEW method with create_method
268
+ 2. Add body with add_method_body
269
+ 3. Update the file's 'data' array to include new method UUID (remove old one)
270
+ 4. Update any element click handlers to reference the new method UUID
271
+ 5. Optionally delete the old method with delete_method`,
438
272
  inputSchema: {
439
273
  type: 'object',
440
274
  properties: {
@@ -456,15 +290,24 @@ Example response includes:
456
290
  },
457
291
  {
458
292
  name: 'save_method',
459
- description: `Update an existing method's properties (name, visibility, returnType, nullable, parameters).
293
+ description: `Update an existing method's properties (name, visibility, returnType, nullable, parameters, data).
460
294
 
461
295
  Use this to modify a method after creation. For updating the method body, use add_method_body instead.
462
296
 
463
- Example:
297
+ Parameters:
298
+ - data: Array of statement UUIDs that form the method body. Use this to reorder statements or remove unwanted statements from the method.
299
+
300
+ Example - Update return type:
464
301
  {
465
302
  "uuid": "method-uuid",
466
303
  "returnType": "object",
467
304
  "nullable": true
305
+ }
306
+
307
+ Example - Remove duplicate/unwanted statements:
308
+ {
309
+ "uuid": "method-uuid",
310
+ "data": ["statement-uuid-1", "statement-uuid-2"] // Only keep these statements
468
311
  }`,
469
312
  inputSchema: {
470
313
  type: 'object',
@@ -499,6 +342,11 @@ Example:
499
342
  description: 'Array of parameter clause UUIDs',
500
343
  items: { type: 'string' },
501
344
  },
345
+ data: {
346
+ type: 'array',
347
+ description: 'Array of statement UUIDs that form the method body. Use to reorder or remove statements.',
348
+ items: { type: 'string' },
349
+ },
502
350
  },
503
351
  required: ['uuid'],
504
352
  },
@@ -520,6 +368,34 @@ Example:
520
368
  },
521
369
  },
522
370
  },
371
+ {
372
+ name: 'delete_method',
373
+ description: 'Delete a method from a file by UUID. This permanently removes the method and all its code.',
374
+ inputSchema: {
375
+ type: 'object',
376
+ properties: {
377
+ uuid: {
378
+ type: 'string',
379
+ description: 'UUID of the method to delete',
380
+ },
381
+ },
382
+ required: ['uuid'],
383
+ },
384
+ },
385
+ {
386
+ name: 'get_method',
387
+ description: 'Get a method by UUID. Returns the method data including its parameters and body.',
388
+ inputSchema: {
389
+ type: 'object',
390
+ properties: {
391
+ uuid: {
392
+ type: 'string',
393
+ description: 'UUID of the method to retrieve',
394
+ },
395
+ },
396
+ required: ['uuid'],
397
+ },
398
+ },
523
399
  {
524
400
  name: 'search_files',
525
401
  description: 'Search for files in the project by name or type',
@@ -539,30 +415,9 @@ Example:
539
415
  },
540
416
  {
541
417
  name: 'create_route',
542
- description: `Create a new route/page in a Stellify project.
543
-
544
- IMPORTANT - WIRING ROUTES TO CONTROLLERS:
545
- For API routes to execute code, you MUST connect them to a controller and method:
546
- - controller: UUID of the controller file (e.g., NoteController)
547
- - controller_method: UUID of the method to execute (e.g., index, store, update, destroy)
548
-
549
- Without these fields, the route exists but won't execute any code!
550
-
551
- EXAMPLE - Create an API route wired to a controller:
552
- {
553
- "project_id": "project-uuid",
554
- "name": "notes.index",
555
- "path": "/api/notes",
556
- "method": "GET",
557
- "type": "api",
558
- "controller": "controller-file-uuid",
559
- "controller_method": "index-method-uuid"
560
- }
418
+ description: `Create a route/page. For API routes, pass controller and controller_method UUIDs to wire execution.
561
419
 
562
- WORKFLOW for API endpoints:
563
- 1. Create controller with create_file (type: "controller") or create_resources
564
- 2. Create methods with create_method + add_method_body
565
- 3. Create route with create_route, passing controller and controller_method UUIDs`,
420
+ Route params like {id} auto-inject into controller method parameters when names match.`,
566
421
  inputSchema: {
567
422
  type: 'object',
568
423
  properties: {
@@ -694,6 +549,22 @@ Available fields:
694
549
  required: ['uuid'],
695
550
  },
696
551
  },
552
+ {
553
+ name: 'delete_route',
554
+ description: `Delete a route/page from the project by UUID. This permanently removes the route.
555
+
556
+ WARNING: This is destructive and cannot be undone. Any elements attached to this route will become orphaned.`,
557
+ inputSchema: {
558
+ type: 'object',
559
+ properties: {
560
+ uuid: {
561
+ type: 'string',
562
+ description: 'UUID of the route to delete',
563
+ },
564
+ },
565
+ required: ['uuid'],
566
+ },
567
+ },
697
568
  {
698
569
  name: 'search_routes',
699
570
  description: `Search for routes/pages in the project by name. Use this to find existing routes before creating new ones.
@@ -727,7 +598,17 @@ Valid element types:
727
598
  - HTML5: s-wrapper, s-input, s-form, s-svg, s-shape, s-media, s-iframe
728
599
  - Components: s-loop, s-transition, s-freestyle, s-motion
729
600
  - Blade: s-directive
730
- - Shadcn/ui: s-chart, s-table, s-combobox, s-accordion, s-calendar, s-contiguous`,
601
+ - Shadcn/ui: s-chart, s-table, s-combobox, s-accordion, s-calendar, s-contiguous
602
+
603
+ s-loop ELEMENT TYPE:
604
+ Use s-loop for elements that should render with v-for directive.
605
+ Required attributes (set via update_element after creation):
606
+ - loop: The v-for expression (e.g., "note in notes", "item in items")
607
+ - key: The :key binding (e.g., "note.id", "item.id")
608
+
609
+ Example: After creating s-loop, update it with:
610
+ { "tag": "div", "loop": "note in notes", "key": "note.id", "classes": ["card", "p-4"] }
611
+ Generates: <div class="card p-4" v-for="note in notes" :key="note.id">`,
731
612
  inputSchema: {
732
613
  type: 'object',
733
614
  properties: {
@@ -755,37 +636,13 @@ Valid element types:
755
636
  },
756
637
  {
757
638
  name: 'update_element',
758
- description: `Update an existing UI element (for Elements v2).
759
-
760
- Use standard HTML attributes directly (placeholder, href, src, type, etc.).
761
-
762
- Special Stellify fields:
763
- - name: Element name in editor
764
- - type: Element type (s-wrapper, s-input, etc.)
765
- - locked: Prevent editing (boolean)
766
- - tag: HTML tag (div, input, button, etc.)
767
- - classes: CSS classes array ["class1", "class2"]
768
- - text: Element text content
769
-
770
- EVENT HANDLERS (set value to method UUID):
771
- - click: @click - buttons, links, any clickable element
772
- - submit: @submit - form submission
773
- - change: @change - input/select value changed (on blur)
774
- - input: @input - input value changing (real-time, as user types)
775
- - focus: @focus - element receives focus
776
- - blur: @blur - element loses focus
777
- - keydown: @keydown - key pressed down
778
- - keyup: @keyup - key released
779
- - mouseenter: @mouseenter - mouse enters element
780
- - mouseleave: @mouseleave - mouse leaves element
781
-
782
- Example wiring a button click to a method:
783
- {
784
- "uuid": "button-element-uuid",
785
- "data": {
786
- "click": "increment-method-uuid"
787
- }
788
- }`,
639
+ description: `Update a UI element's attributes.
640
+
641
+ Pass data object with: tag, classes (array), text, variable (for v-model), and event handlers (click, submit, etc. = method UUID).
642
+
643
+ Key fields: inputType (not 'type') for button/input HTML type. clickArgs for handler arguments in v-for loops.
644
+
645
+ Event handlers: click, submit, change, input, focus, blur, keydown, keyup, mouseenter, mouseleave.`,
789
646
  inputSchema: {
790
647
  type: 'object',
791
648
  properties: {
@@ -874,31 +731,11 @@ Note: To reorder elements, use update_element to modify the parent element's 'da
874
731
  },
875
732
  {
876
733
  name: 'html_to_elements',
877
- description: `Convert HTML to Stellify elements in ONE operation. This is the FASTEST way to build interfaces!
878
-
879
- This will:
880
- 1. Parse the HTML structure
881
- 2. Create all elements with proper nesting and types
882
- 3. Preserve all attributes, classes, text content
883
- 4. Auto-detect Vue bindings ({{ variable }}) and create linked statements
884
- 5. Return element UUIDs to use in save_file template array
885
-
886
- Element type mapping:
887
- - button, input, textarea, select → s-input
888
- - div, span, p, section, etc. → s-wrapper
889
- - form → s-form
890
- - img, video, audio → s-media
891
-
892
- VUE BINDING AUTO-DETECTION:
893
- Text like {{ count }} is automatically detected and:
894
- - A statement is created with the binding code
895
- - The statement UUID is added to the element's 'statements' array
896
- - You still need to create the reactive data source separately (const count = ref(0))
897
-
898
- For Vue components: Omit 'page' - elements are created standalone for the component template.
899
- For page content: Provide 'page' (route UUID) to attach elements directly.
900
-
901
- IMPORTANT: Use the returned root element UUID in save_file's template array.`,
734
+ description: `Convert HTML to Stellify elements. Returns element UUIDs to use in save_file template array.
735
+
736
+ Auto-detects Vue bindings ({{ var }}). For Vue components, omit 'page'. For pages, provide route UUID.
737
+
738
+ Prefer SVG icons over emoji (encoding issues).`,
902
739
  inputSchema: {
903
740
  type: 'object',
904
741
  properties: {
@@ -951,7 +788,7 @@ Use cases:
951
788
  - PHP: Class properties, use statements, constants
952
789
  - JS/Vue: Variable declarations, imports, reactive refs
953
790
 
954
- For Vue components, include the returned statement UUID in save_file's 'data' array.`,
791
+ For Vue components, include the returned statement UUID in save_file's 'statements' array (NOT 'data' - that's for methods).`,
955
792
  inputSchema: {
956
793
  type: 'object',
957
794
  properties: {
@@ -994,6 +831,38 @@ Examples:
994
831
  required: ['file', 'statement', 'code'],
995
832
  },
996
833
  },
834
+ {
835
+ name: 'delete_statement',
836
+ description: 'Delete a statement from a file by UUID. This permanently removes the statement (import, variable, ref, etc.).',
837
+ inputSchema: {
838
+ type: 'object',
839
+ properties: {
840
+ uuid: {
841
+ type: 'string',
842
+ description: 'UUID of the statement to delete',
843
+ },
844
+ },
845
+ required: ['uuid'],
846
+ },
847
+ },
848
+ {
849
+ name: 'save_statement',
850
+ description: 'Update an existing statement. Use this to modify statement properties after creation.',
851
+ inputSchema: {
852
+ type: 'object',
853
+ properties: {
854
+ uuid: {
855
+ type: 'string',
856
+ description: 'UUID of the statement to update',
857
+ },
858
+ data: {
859
+ type: 'object',
860
+ description: 'Statement data to update',
861
+ },
862
+ },
863
+ required: ['uuid'],
864
+ },
865
+ },
997
866
  {
998
867
  name: 'save_file',
999
868
  description: `Save/update a file with its full configuration. This FINALIZES the file after create_file.
@@ -1063,6 +932,11 @@ For <script setup> content, the order in statements array determines output orde
1063
932
  items: { type: 'string' },
1064
933
  description: 'Array of file UUIDs to import',
1065
934
  },
935
+ models: {
936
+ type: 'array',
937
+ items: { type: 'string' },
938
+ description: 'Array of model file UUIDs that this controller uses (required for model class loading)',
939
+ },
1066
940
  },
1067
941
  required: ['uuid', 'name', 'type'],
1068
942
  },
@@ -1081,6 +955,22 @@ For <script setup> content, the order in statements array determines output orde
1081
955
  required: ['uuid'],
1082
956
  },
1083
957
  },
958
+ {
959
+ name: 'delete_file',
960
+ description: `Delete a file from the project by UUID. This permanently removes the file and all its methods/statements.
961
+
962
+ WARNING: This is destructive and cannot be undone. Make sure the file is not referenced elsewhere before deleting.`,
963
+ inputSchema: {
964
+ type: 'object',
965
+ properties: {
966
+ uuid: {
967
+ type: 'string',
968
+ description: 'UUID of the file to delete',
969
+ },
970
+ },
971
+ required: ['uuid'],
972
+ },
973
+ },
1084
974
  {
1085
975
  name: 'get_directory',
1086
976
  description: `Get a directory by UUID to see its contents.
@@ -1119,37 +1009,31 @@ IMPORTANT: Check existing directories first using get_project and get_directory
1119
1009
  required: ['name'],
1120
1010
  },
1121
1011
  },
1012
+ {
1013
+ name: 'save_directory',
1014
+ description: 'Update an existing directory. Use this to rename or modify directory properties.',
1015
+ inputSchema: {
1016
+ type: 'object',
1017
+ properties: {
1018
+ uuid: {
1019
+ type: 'string',
1020
+ description: 'UUID of the directory to update',
1021
+ },
1022
+ name: {
1023
+ type: 'string',
1024
+ description: 'New directory name',
1025
+ },
1026
+ },
1027
+ required: ['uuid'],
1028
+ },
1029
+ },
1122
1030
  {
1123
1031
  name: 'broadcast_element_command',
1124
- description: `Broadcast a real-time command to update UI elements via WebSocket.
1125
-
1126
- IMPORTANT: USE THIS TOOL FIRST when the user asks you to:
1127
- - Show, display, or demonstrate something visually
1128
- - Update, change, or modify what's on screen
1129
- - Build or create UI elements for demonstration
1130
- - Send messages or content to the browser
1131
- - Do anything "live" or "in real-time"
1132
-
1133
- 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.
1134
-
1135
- ACTIONS:
1136
- - update: Modify an existing element's attributes (text, classes, styles, etc.)
1137
- - create: Create a new ephemeral element (provide any UUID string you want)
1138
- - batch: Modify multiple elements at once
1139
- - delete: Remove an element from the UI state
1032
+ description: `Push real-time UI updates via WebSocket. Use for SHOW/DISPLAY/DEMONSTRATE requests.
1140
1033
 
1141
- TO CREATE EPHEMERAL ELEMENTS (not stored in database):
1142
- 1. First, use action="create" with any UUID (e.g., "msg-001") and full element structure in changes
1143
- 2. Then, use action="update" on the PARENT element to add your new UUID to its "data" array
1034
+ Actions: update (modify element), create (ephemeral element), batch (multiple updates), delete.
1144
1035
 
1145
- Example - Update existing element text:
1146
- { action: "update", element: "existing-uuid", changes: { text: "Hello world!", classes: ["p-4", "bg-blue-500"] } }
1147
-
1148
- Example - Create ephemeral child element:
1149
- Step 1: { action: "create", element: "my-new-element", changes: { type: "s-wrapper", tag: "div", text: "I exist!", classes: ["p-2", "bg-green-500"] } }
1150
- Step 2: { action: "update", element: "parent-uuid", changes: { data: ["my-new-element"] } }
1151
-
1152
- For PERSISTENT changes (saved to database), use update_element or html_to_elements instead.`,
1036
+ Changes are EPHEMERAL (not saved). For persistent changes, use update_element or html_to_elements.`,
1153
1037
  inputSchema: {
1154
1038
  type: 'object',
1155
1039
  properties: {
@@ -1184,80 +1068,13 @@ For PERSISTENT changes (saved to database), use update_element or html_to_elemen
1184
1068
  },
1185
1069
  {
1186
1070
  name: 'create_resources',
1187
- description: `Scaffold a complete resource stack in ONE operation. Creates Model, Controller, Service, and Migration together.
1188
-
1189
- This is the FASTEST way to bootstrap new features! Instead of 20+ individual API calls, create everything at once.
1071
+ description: `Scaffold Model, Controller, Service, and Migration in ONE operation.
1190
1072
 
1191
- WHAT IT CREATES:
1192
- - Model: With $fillable, $casts, and relationship methods
1193
- - Controller: With index, store, show, update, destroy actions
1194
- - Service (optional): Business logic layer with list, find, create, update, delete methods
1195
- - Migration: With proper column types based on field definitions
1073
+ Creates: Model ($fillable, $casts, relationships), Controller (CRUD actions), Service (optional), Migration.
1196
1074
 
1197
- EXAMPLE - Create a User resource:
1198
- {
1199
- "name": "User",
1200
- "fields": [
1201
- { "name": "name", "type": "string" },
1202
- { "name": "email", "type": "string", "unique": true },
1203
- { "name": "password", "type": "string" },
1204
- { "name": "is_active", "type": "boolean", "default": true }
1205
- ],
1206
- "relationships": [
1207
- { "type": "hasMany", "model": "Post" }
1208
- ],
1209
- "controller": true,
1210
- "service": true,
1211
- "migration": true
1212
- }
1075
+ IMPORTANT: Routes are NOT auto-wired. After creation, use create_route with the returned controller UUID and method UUIDs.
1213
1076
 
1214
- FIELD TYPES:
1215
- - string, text, longtext (text fields)
1216
- - integer, int, bigint (numbers)
1217
- - boolean, bool (true/false)
1218
- - float, double, decimal (decimals)
1219
- - date, datetime, timestamp (dates)
1220
- - json (JSON/array data)
1221
- - email (string with email validation)
1222
-
1223
- FIELD OPTIONS:
1224
- - nullable: Allow NULL values
1225
- - unique: Add unique constraint
1226
- - required: Require in validation (default: true for store)
1227
- - default: Default value
1228
- - max: Maximum length/value
1229
-
1230
- RELATIONSHIP TYPES:
1231
- - hasOne: One-to-one (User hasOne Profile)
1232
- - hasMany: One-to-many (User hasMany Posts)
1233
- - belongsTo: Inverse of hasOne/hasMany (Post belongsTo User)
1234
- - belongsToMany: Many-to-many (User belongsToMany Roles)
1235
-
1236
- IMPORTANT - WIRING ROUTES TO CONTROLLERS:
1237
- This tool creates controller methods but does NOT automatically wire routes to them.
1238
- After calling create_resources, you must MANUALLY wire routes using create_route:
1239
-
1240
- 1. Note the returned controller UUID and method UUIDs from the response
1241
- 2. For each API route, call create_route with:
1242
- - controller: the controller file UUID
1243
- - controller_method: the specific method UUID (index, store, update, destroy)
1244
-
1245
- Example response structure:
1246
- {
1247
- "controller": {
1248
- "uuid": "controller-uuid",
1249
- "methods": [
1250
- { "uuid": "index-method-uuid", "name": "index" },
1251
- { "uuid": "store-method-uuid", "name": "store" },
1252
- ...
1253
- ]
1254
- }
1255
- }
1256
-
1257
- Then create routes:
1258
- create_route({ path: "/api/notes", method: "GET", controller: "controller-uuid", controller_method: "index-method-uuid" })
1259
-
1260
- Returns UUIDs for all created files so you can customize them further if needed.`,
1077
+ Response includes controller.methods array with {uuid, name} for each action (index, store, update, destroy).`,
1261
1078
  inputSchema: {
1262
1079
  type: 'object',
1263
1080
  properties: {
@@ -1563,6 +1380,38 @@ Key concepts:
1563
1380
  - Vue components link to UI elements via the 'template' field
1564
1381
  - Event handlers (click, submit) wire UI elements to methods by UUID
1565
1382
 
1383
+ ## General Workflow (all file types)
1384
+
1385
+ 1. create_file → empty shell, returns file UUID
1386
+ 2. create_method → signature only, returns method UUID
1387
+ 3. add_method_body → implementation code
1388
+ 4. create_statement + add_statement_code → for imports, variables, refs
1389
+ 5. save_file → finalize with template/data/statements arrays
1390
+
1391
+ ## Vue Component Workflow
1392
+
1393
+ 1. get_project → find 'js' directory UUID
1394
+ 2. create_file → type='js', extension='vue'
1395
+ 3. Create statements for imports: "import { ref } from 'vue';" (REQUIRED for ref())
1396
+ 4. Create statements for data: "const count = ref(0);"
1397
+ 5. create_method + add_method_body → functions
1398
+ 6. html_to_elements → template (no 'page' param for components)
1399
+ 7. update_element → wire click handlers to method UUIDs
1400
+ 8. save_file with: extension='vue', template=[elementUuid], data=[methodUuids], statements=[importUuids, refUuids]
1401
+
1402
+ ## Real-Time UI (broadcast_element_command)
1403
+
1404
+ Use for SHOW/DISPLAY/DEMONSTRATE requests - sends instant WebSocket updates to browser.
1405
+ Use html_to_elements/update_element for permanent/saved changes.
1406
+
1407
+ ## Common Pitfalls
1408
+
1409
+ - v-model requires ref(), NOT Form class: const formData = ref({title: ''})
1410
+ - List.from() returns List, not array - use .toArray() for v-for
1411
+ - add_method_body APPENDS, doesn't replace - create new method to replace
1412
+ - 'data' array = method UUIDs, 'statements' array = import/variable UUIDs
1413
+ - For buttons in forms, set inputType: "button" to prevent auto-submit
1414
+
1566
1415
  ## Framework Capabilities (Libraries/Packages)
1567
1416
 
1568
1417
  **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.**
@@ -1594,18 +1443,14 @@ Examples of capabilities (packages you cannot write):
1594
1443
 
1595
1444
  When building features, group related files by passing a "module" parameter.
1596
1445
 
1597
- **WORKFLOW:** Simply include the 'module' parameter when creating files or routes:
1598
-
1599
1446
  - create_file(..., module: "blog-posts") - auto-groups file
1600
1447
  - create_route(..., module: "blog-posts") - auto-groups route
1601
1448
 
1602
- Modules are auto-created if they don't exist. This helps users see all code related to a feature grouped together.
1603
-
1604
- Example module names: "user-auth", "blog-posts", "product-catalog", "order-management", "admin-dashboard"`;
1449
+ Modules are auto-created if they don't exist. This helps users see all code related to a feature grouped together.`;
1605
1450
  // Create MCP server
1606
1451
  const server = new Server({
1607
1452
  name: 'stellify-mcp',
1608
- version: '0.1.0',
1453
+ version: '0.1.22',
1609
1454
  }, {
1610
1455
  capabilities: {
1611
1456
  tools: {},
@@ -1742,6 +1587,37 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1742
1587
  ],
1743
1588
  };
1744
1589
  }
1590
+ case 'delete_method': {
1591
+ const { uuid } = args;
1592
+ const result = await stellify.deleteMethod(uuid);
1593
+ return {
1594
+ content: [
1595
+ {
1596
+ type: 'text',
1597
+ text: JSON.stringify({
1598
+ success: true,
1599
+ message: `Deleted method ${uuid}`,
1600
+ data: result,
1601
+ }, null, 2),
1602
+ },
1603
+ ],
1604
+ };
1605
+ }
1606
+ case 'get_method': {
1607
+ const { uuid } = args;
1608
+ const result = await stellify.getMethod(uuid);
1609
+ return {
1610
+ content: [
1611
+ {
1612
+ type: 'text',
1613
+ text: JSON.stringify({
1614
+ success: true,
1615
+ method: result,
1616
+ }, null, 2),
1617
+ },
1618
+ ],
1619
+ };
1620
+ }
1745
1621
  case 'search_files': {
1746
1622
  const result = await stellify.searchFiles(args);
1747
1623
  return {
@@ -1805,6 +1681,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1805
1681
  ],
1806
1682
  };
1807
1683
  }
1684
+ case 'delete_route': {
1685
+ const { uuid } = args;
1686
+ const result = await stellify.deleteRoute(uuid);
1687
+ return {
1688
+ content: [
1689
+ {
1690
+ type: 'text',
1691
+ text: JSON.stringify({
1692
+ success: true,
1693
+ message: `Deleted route ${uuid}`,
1694
+ data: result,
1695
+ }, null, 2),
1696
+ },
1697
+ ],
1698
+ };
1699
+ }
1808
1700
  case 'search_routes': {
1809
1701
  const result = await stellify.searchRoutes(args);
1810
1702
  const routes = result.data || result;
@@ -1982,6 +1874,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1982
1874
  ],
1983
1875
  };
1984
1876
  }
1877
+ case 'delete_statement': {
1878
+ const { uuid } = args;
1879
+ const result = await stellify.deleteStatement(uuid);
1880
+ return {
1881
+ content: [
1882
+ {
1883
+ type: 'text',
1884
+ text: JSON.stringify({
1885
+ success: true,
1886
+ message: `Deleted statement ${uuid}`,
1887
+ data: result,
1888
+ }, null, 2),
1889
+ },
1890
+ ],
1891
+ };
1892
+ }
1893
+ case 'save_statement': {
1894
+ const { uuid, ...data } = args;
1895
+ const result = await stellify.saveStatement(uuid, data);
1896
+ return {
1897
+ content: [
1898
+ {
1899
+ type: 'text',
1900
+ text: JSON.stringify({
1901
+ success: true,
1902
+ message: `Saved statement ${uuid}`,
1903
+ statement: result,
1904
+ }, null, 2),
1905
+ },
1906
+ ],
1907
+ };
1908
+ }
1985
1909
  case 'save_file': {
1986
1910
  const { uuid, ...data } = args;
1987
1911
  const result = await stellify.saveFile(uuid, { uuid, ...data });
@@ -2013,6 +1937,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2013
1937
  ],
2014
1938
  };
2015
1939
  }
1940
+ case 'delete_file': {
1941
+ const { uuid } = args;
1942
+ const result = await stellify.deleteFile(uuid);
1943
+ return {
1944
+ content: [
1945
+ {
1946
+ type: 'text',
1947
+ text: JSON.stringify({
1948
+ success: true,
1949
+ message: `Deleted file ${uuid}`,
1950
+ data: result,
1951
+ }, null, 2),
1952
+ },
1953
+ ],
1954
+ };
1955
+ }
2016
1956
  case 'get_directory': {
2017
1957
  const result = await stellify.getDirectory(args.uuid);
2018
1958
  const dirData = result.data || result;
@@ -2047,6 +1987,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2047
1987
  ],
2048
1988
  };
2049
1989
  }
1990
+ case 'save_directory': {
1991
+ const { uuid, ...data } = args;
1992
+ const result = await stellify.saveDirectory(uuid, data);
1993
+ return {
1994
+ content: [
1995
+ {
1996
+ type: 'text',
1997
+ text: JSON.stringify({
1998
+ success: true,
1999
+ message: `Saved directory ${uuid}`,
2000
+ directory: result,
2001
+ }, null, 2),
2002
+ },
2003
+ ],
2004
+ };
2005
+ }
2050
2006
  case 'broadcast_element_command': {
2051
2007
  const result = await stellify.broadcastElementCommand(args);
2052
2008
  return {
@@ -76,17 +76,21 @@ 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
80
  getMethod(method: string): Promise<any>;
80
81
  saveMethod(method: string, data: any): Promise<any>;
82
+ deleteMethod(method: string): Promise<any>;
81
83
  createStatement(params: {
82
84
  file?: string;
83
85
  method?: string;
84
86
  }): Promise<any>;
85
87
  getStatement(statement: string): Promise<any>;
88
+ deleteStatement(statement: string): Promise<any>;
86
89
  saveStatement(statement: string, data: any): Promise<any>;
87
90
  createRoute(params: CreateRouteParams): Promise<any>;
88
91
  getRoute(route: string): Promise<any>;
89
92
  saveRoute(route: string, data: any): Promise<any>;
93
+ deleteRoute(route: string): Promise<any>;
90
94
  searchRoutes(params: {
91
95
  search?: string;
92
96
  type?: string;
@@ -43,6 +43,10 @@ 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}`);
48
+ return response.data;
49
+ }
46
50
  async getMethod(method) {
47
51
  const response = await this.client.get(`/method/${method}`);
48
52
  return response.data;
@@ -51,6 +55,10 @@ export class StellifyClient {
51
55
  const response = await this.client.put(`/method/${method}`, data);
52
56
  return response.data;
53
57
  }
58
+ async deleteMethod(method) {
59
+ const response = await this.client.delete(`/method/${method}`);
60
+ return response.data;
61
+ }
54
62
  async createStatement(params) {
55
63
  const response = await this.client.post('/statement', params);
56
64
  return response.data;
@@ -59,6 +67,10 @@ export class StellifyClient {
59
67
  const response = await this.client.get(`/statement/${statement}`);
60
68
  return response.data;
61
69
  }
70
+ async deleteStatement(statement) {
71
+ const response = await this.client.delete(`/statement/${statement}`);
72
+ return response.data;
73
+ }
62
74
  async saveStatement(statement, data) {
63
75
  const response = await this.client.put(`/statement/${statement}`, data);
64
76
  return response.data;
@@ -75,6 +87,10 @@ export class StellifyClient {
75
87
  const response = await this.client.put(`/route/${route}`, { uuid: route, ...data });
76
88
  return response.data;
77
89
  }
90
+ async deleteRoute(route) {
91
+ const response = await this.client.delete(`/route/${route}`);
92
+ return response.data;
93
+ }
78
94
  async searchRoutes(params) {
79
95
  const response = await this.client.get('/route/search', { params });
80
96
  return response.data;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellisoft/stellify-mcp",
3
- "version": "0.1.19",
3
+ "version": "0.1.22",
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.18",
9
+ "version": "0.1.22",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@stellisoft/stellify-mcp",
14
- "version": "0.1.18",
14
+ "version": "0.1.22",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },