# Stellify MCP Server
[](https://www.npmjs.com/package/@stellisoft/stellify-mcp)
[](https://opensource.org/licenses/MIT)
Model Context Protocol (MCP) server for [Stellify](https://stellisoft.com) - the AI-native code generation platform.
## What is This?
This MCP server lets AI assistants (like Claude Desktop) interact with your Stellify projects to build Laravel and Vue.js applications incrementally. Instead of generating full code files at once, AI can:
- Create file structures (classes, controllers, models, middleware, Vue components)
- Add method signatures with type hints
- Parse PHP/JavaScript code into structured JSON (statement-by-statement)
- Convert HTML to Stellify elements in a single operation
- Search existing code in your projects
- Install reusable code from the global library
- Build applications through natural conversation
## Quick Start
### Prerequisites
- **Node.js 18 or higher**
- **A Stellify account** - Sign up at [stellisoft.com](https://stellisoft.com)
- **Claude Desktop** (or another MCP-compatible AI client)
### Installation
Install globally via npm:
```bash
npm install -g @stellisoft/stellify-mcp
```
### Configuration
1. **Get your Stellify API token:**
- Log into [Stellify](https://stellisoft.com)
- Navigate to Settings → API Tokens
- Click "Create New Token"
- Copy your token
2. **Configure Claude Desktop:**
Edit your Claude Desktop configuration file:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux:** `~/.config/claude/claude_desktop_config.json`
Add the Stellify MCP server:
```json
{
"mcpServers": {
"stellify": {
"command": "stellify-mcp",
"env": {
"STELLIFY_API_URL": "https://api.stellisoft.com/v1",
"STELLIFY_API_TOKEN": "your-token-here"
}
}
}
}
```
3. **Restart Claude Desktop**
That's it! The Stellify tools should now be available in Claude Desktop.
## Usage
Once configured, you can talk to Claude naturally to build applications:
### Example Conversations
**Create a new controller:**
```
"Create a UserController in my Stellify project"
```
**Add methods:**
```
"Add a method called 'store' that takes a Request parameter and returns a JsonResponse"
```
**Implement method logic:**
```
"Add this implementation to the store method:
$user = User::create($request->validated());
return response()->json($user, 201);"
```
**Build a Vue component:**
```
"Create a Counter component with an increment button"
```
**Convert HTML to elements:**
```
"Convert this HTML to Stellify elements:
Hello
"
```
**Search your codebase:**
```
"Search for all controller files in my project"
"Find methods related to authentication"
```
## Available Tools
### Project & Directory Tools
#### `get_project`
Get the active Stellify project for the authenticated user. **Call this first before any other operations.**
**Parameters:** None
**Returns:**
- `uuid`: Project UUID (needed for most operations)
- `name`: Project name
- `directories`: Array of `{uuid, name}` for existing directories
---
#### `get_directory`
Get a directory by UUID to see its contents.
**Parameters:**
- `uuid` (required): The UUID of the directory
---
#### `create_directory`
Create a new directory for organizing files.
**Parameters:**
- `name` (required): Directory name (e.g., "js", "css", "components")
---
### File Tools
#### `create_file`
Create a new file in a Stellify project. This creates an empty file shell - no methods, statements, or template yet.
**Parameters:**
- `directory` (required): UUID of the directory (get from `get_project` directories array)
- `name` (required): File name without extension (e.g., "Counter", "UserController")
- `type` (required): File type - "class", "model", "controller", "middleware", or "js"
- `extension` (optional): File extension. Use "vue" for Vue components.
- `namespace` (optional): PHP namespace (e.g., "App\\Services\\"). Only for PHP files.
- `includes` (optional): Array of fully-qualified class names to import (e.g., `["App\\Models\\User", "Illuminate\\Http\\Request"]`). Stellify will resolve these to file UUIDs, fetching from Laravel API or vendor directory if needed.
**Directory selection:** Match the directory to your file's purpose. If the directory doesn't exist, create it first with `create_directory`.
| File Type | Directory | Namespace |
|-----------|-----------|-----------|
| Controllers | `controllers` | `App\Http\Controllers\` |
| Models | `models` | `App\Models\` |
| Services | `services` | `App\Services\` |
| Middleware | `middleware` | `App\Http\Middleware\` |
| Vue/JS | `js` | N/A |
**Example workflow:**
1. `create_file` → creates empty shell, returns file UUID
2. `create_statement` + `add_statement_code` → add variables/imports
3. `create_method` + `add_method_body` → add functions
4. `html_to_elements` → create template elements (for Vue)
5. `save_file` → finalize with all UUIDs wired together
**Auto-dependency creation** (when `auto_create_dependencies: true`):
When you create a file with code like:
```php
validated());
return response()->json($user);
}
}
```
Stellify will:
1. Parse `use` statements to find dependencies (`User`, `Request`, `Socialite`)
2. Check Application DB for framework classes → find cached classes
3. For core Laravel classes → fetch from [api.laravel.com](https://api.laravel.com/docs/12.x/)
4. For vendor packages (Socialite, Spatie, etc.) → read from `vendor/` directory
5. Create missing App classes → create `User` model file
6. Wire up the file's `includes` array with all dependency UUIDs
**Supported sources:**
- **Laravel API** - Core `Illuminate\*` classes fetched from api.laravel.com
- **Vendor packages** - `Laravel\Socialite\*`, `Laravel\Cashier\*`, `Spatie\*`, `Livewire\*`, etc. read directly from your `vendor/` directory using PHP-Parser
The response includes a `dependencies` report showing what was created/resolved and from which source.
---
#### `get_file`
Get a file by UUID with all its metadata, methods, and statements.
**Parameters:**
- `uuid` (required): UUID of the file
---
#### `save_file`
Save/update a file with its full configuration. This finalizes the file after `create_file`.
**Parameters:**
- `uuid` (required): UUID of the file
- `name` (required): File name (without extension)
- `type` (required): File type ("js", "class", "controller", "model", "middleware")
- `extension` (optional): File extension ("vue" for Vue SFCs)
- `template` (optional): Array of root element UUIDs for Vue `` section
- `data` (optional): Array of METHOD UUIDs only (functions)
- `statements` (optional): Array of STATEMENT UUIDs (imports, variables, refs)
- `includes` (optional): Array of file UUIDs to import
**Important:** `data` = method UUIDs only, `statements` = statement UUIDs (code outside methods)
---
#### `search_files`
Search for files in the project by name or type.
**Parameters:**
- `name` (optional): File name pattern to search for
- `type` (optional): File type filter
---
### Method Tools
#### `create_method`
Create a method signature in a file (without implementation).
**Parameters:**
- `file` (required): UUID of the file to add the method to
- `name` (required): Method name (e.g., "increment", "store", "handleClick")
- `visibility` (optional): "public", "protected", or "private" (PHP only, default: "public")
- `is_static` (optional): Whether the method is static (PHP only, default: false)
- `returnType` (optional): Return type (e.g., "int", "string", "void")
- `parameters` (optional): Array of `{name, type}` objects
---
#### `add_method_body`
Parse and add code to a method body. Stellify parses the code into structured JSON statements.
**Parameters:**
- `file_uuid` (required): UUID of the file containing the method
- `method_uuid` (required): UUID of the method to add code to
- `code` (required): Code for the method body (just the statements, no function declaration)
**Example:**
```
code: "return $a + $b;"
```
---
#### `search_methods`
Search for methods in the project by name or within a specific file.
**Parameters:**
- `name` (optional): Method name to search for (supports wildcards)
- `file_uuid` (optional): Filter results to a specific file
---
### Statement Tools
#### `create_statement`
Create an empty statement in a file. This is step 1 of 2 - you must call `add_statement_code` next.
**Parameters:**
- `file` (optional): UUID of the file to add the statement to
- `method` (optional): UUID of the method to add the statement to (for method body statements)
**Use cases:**
- PHP: Class properties, use statements, constants
- JS/Vue: Variable declarations, imports, reactive refs
---
#### `add_statement_code`
Add code to an existing statement. This is step 2 of 2 - call after `create_statement`.
**Parameters:**
- `file_uuid` (required): UUID of the file containing the statement
- `statement_uuid` (required): UUID of the statement to add code to
- `code` (required): The code to add
**Examples:**
```
code: "use Illuminate\\Http\\Request;"
code: "const count = ref(0);"
code: "import { ref } from 'vue';"
```
---
#### `get_statement`
Get a statement by UUID with its clauses (code tokens).
**Parameters:**
- `uuid` (required): The UUID of the statement
---
### Route Tools
#### `create_route`
Create a new route/page in a Stellify project.
**Parameters:**
- `project_id` (required): The UUID of the Stellify project
- `name` (required): Route/page name (e.g., "Home", "Counter", "About")
- `path` (required): URL path (e.g., "/", "/counter", "/about")
- `method` (required): HTTP method ("GET", "POST", "PUT", "DELETE", "PATCH")
- `type` (optional): Route type - "web" for pages, "api" for API endpoints (default: "web")
- `data` (optional): Additional route data
---
#### `get_route`
Get a route/page by UUID.
**Parameters:**
- `uuid` (required): The UUID of the route
---
#### `search_routes`
Search for routes/pages in the project by name.
**Parameters:**
- `search` (optional): Search term to match route names
- `type` (optional): Filter by route type ("web" or "api")
- `per_page` (optional): Results per page (default: 10)
---
### Views & Blade Templates
Stellify stores Blade views as elements instead of files. The root element's `name` field maps to the view name:
- Element with `name="notes.index"` → `view('notes.index', $data)`
- Element with `name="layouts.app"` → `@extends('layouts.app')`
- Element with `name="components.card"` → ``
Use `update_element` to set the `name` on a root element after creating it with `html_to_elements`.
**Convention for reusable templates:** Attach layouts, components, and partials to a template route (e.g., `/template/app-layout`, `/template/card`) to keep them organized and editable.
---
### Element Tools (UI Components)
#### `create_element`
Create a new UI element. Provide either `page` (route UUID) for root elements, or `parent` (element UUID) for child elements.
**Parameters:**
- `type` (required): Element type - one of:
- HTML5: `s-wrapper`, `s-input`, `s-form`, `s-svg`, `s-shape`, `s-media`, `s-iframe`
- Components: `s-transition`, `s-freestyle`, `s-motion`
- Blade: `s-directive`
- Shadcn/ui: `s-chart`, `s-table`, `s-combobox`, `s-accordion`, `s-calendar`, `s-contiguous`
- `page` (optional): UUID of the page/route (for root elements)
- `parent` (optional): UUID of the parent element (for child elements)
**Using `s-directive` for Blade Conditionals:**
`s-directive` elements output Blade directives (like `@if`, `@foreach`, `@endif`). They are **sibling elements** — they don't wrap children. To conditionally render content:
1. Create an `s-directive` element with a statement for the opening directive (e.g., `@if(...)`)
2. Create the content element(s) as the **next sibling(s)**
3. Create another `s-directive` element with a statement for the closing directive (e.g., `@endif`)
Example — conditionally showing an image:
```
// 1. Create statement for @if
create_statement_with_code({
file: "",
code: "@if($item->featured_image)"
})
// 2. Create opening directive element and set its statement
create_element({ type: "s-directive", page: "" })
update_element({ uuid: "", data: { "statement": "" } })
// 3. Create the image as the next sibling
html_to_elements({ page: "", elements: "" })
// Then update with dynamic src:
update_element({ uuid: "", data: { "srcField": "featured_image" } })
// 4. Create statement for @endif
create_statement_with_code({ file: "", code: "@endif" })
// 5. Create closing directive element
create_element({ type: "s-directive", page: "" })
update_element({ uuid: "", data: { "statement": "" } })
```
The three elements render in order as siblings:
```blade
@if($item->featured_image)
@endif
```
**Using `s-directive` for Loops:**
```
// 1. Create @foreach directive
create_statement_with_code({ file: "", code: "@foreach($posts as $item)" })
create_element({ type: "s-directive", page: "" })
update_element({ uuid: "", data: { "statement": "" } })
// 2. Create loop content (article with dynamic fields)
html_to_elements({ page: "", elements: "" })
// Update elements to use loop item fields:
update_element({ uuid: "", data: { "textField": "title" } }) // → {{ $item->title }}
update_element({ uuid: "", data: { "textField": "excerpt" } }) // → {{ $item->excerpt }}
// 3. Create @endforeach directive
create_statement_with_code({ file: "", code: "@endforeach" })
create_element({ type: "s-directive", page: "" })
update_element({ uuid: "", data: { "statement": "" } })
```
**Loop Item Attributes:**
Inside `@foreach` loops, use these attributes on elements to reference `$item`:
- `textField: "fieldName"` → outputs `{{ $item->fieldName }}`
- `hrefField: "fieldName"` → outputs `href="{{ $item->fieldName }}"`
- `srcField: "fieldName"` → outputs `src="{{ $item->fieldName }}"`
- `hrefExpression: "{{ route('posts.show', $item->slug) }}"` → for complex expressions
- `srcExpression`, `altExpression` → same pattern for other attributes
---
#### `update_element`
Update an existing UI element.
**Parameters:**
- `uuid` (required): UUID of the element to update
- `data` (required): Object with HTML attributes and Stellify fields
**Standard HTML attributes:** `placeholder`, `href`, `src`, `type`, etc.
**Stellify fields:**
- `name`: Element name in editor
- `type`: Element type
- `locked`: Prevent editing (boolean)
- `tag`: HTML tag (div, input, button, etc.)
- `classes`: CSS classes array `["class1", "class2"]`
- `text`: Static text content
- `statements`: Array of statement UUIDs for dynamic Blade content
**Loop item fields** (for elements inside `@foreach` loops, references `$item`):
- `textField`: Field name → outputs `{{ $item->fieldName }}`
- `hrefField`: Field name → outputs `href="{{ $item->fieldName }}"`
- `srcField`: Field name → outputs `src="{{ $item->fieldName }}"`
**Expression attributes** (for complex Blade expressions):
- `hrefExpression`: Full Blade expression for href (e.g., `"{{ route('posts.show', $item->slug) }}"`)
- `srcExpression`: Full Blade expression for src
- `altExpression`: Full Blade expression for alt
**Event handlers** (set value to method UUID):
- `click`: @click
- `submit`: @submit
- `change`: @change
- `input`: @input
- `focus`: @focus
- `blur`: @blur
- `keydown`: @keydown
- `keyup`: @keyup
- `mouseenter`: @mouseenter
- `mouseleave`: @mouseleave
---
#### `get_element`
Get a single element by UUID.
**Parameters:**
- `uuid` (required): UUID of the element
---
#### `get_element_tree`
Get an element with all its descendants as a hierarchical tree structure.
**Parameters:**
- `uuid` (required): UUID of the root element
---
#### `delete_element`
Delete an element and all its children (CASCADE).
**Parameters:**
- `uuid` (required): UUID of the element to delete
---
#### `search_elements`
Search for elements in the project.
**Parameters:**
- `search` (optional): Search query to match element name, type, or content
- `type` (optional): Filter by element type
- `include_metadata` (optional): Include additional metadata (default: false)
- `per_page` (optional): Results per page, 1-100 (default: 20)
---
#### `html_to_elements`
Convert HTML to Stellify elements in ONE operation. This is the fastest way to build interfaces!
**Parameters:**
- `elements` (required): HTML string to convert
- `page` (optional): Route UUID to attach elements to. Omit for Vue components.
- `selection` (optional): Parent element UUID to attach to (alternative to page)
- `file` (optional): Vue component file UUID. Pass this to auto-wire @click handlers to method UUIDs.
- `test` (optional): If true, returns structure without creating elements
**⚠️ CRITICAL: Multiple Root Elements**
When passing HTML with **multiple root-level elements** (e.g., ``, ``, `