gufi-cli 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/CLAUDE.md +97 -182
  2. package/dist/mcp.js +296 -245
  3. package/package.json +1 -1
package/CLAUDE.md CHANGED
@@ -1,213 +1,128 @@
1
- # Gufi CLI - Documentación para Claude
1
+ # Gufi CLI & MCP Server
2
2
 
3
- > **Documentación centralizada en `docs/claude/`**
3
+ > **Para documentación de USO del CLI**, ve a `docs/mcp/`
4
4
  >
5
- > Este archivo es un puntero. Para documentación completa del CLI, lee:
6
- > - [docs/claude/06-cli.md](../../docs/claude/06-cli.md) - Comandos del CLI
7
- > - [docs/claude/00-index.md](../../docs/claude/00-index.md) - Overview de Gufi
8
- > - [docs/claude/05-automations.md](../../docs/claude/05-automations.md) - Automations
9
- > - [docs/claude/04-views.md](../../docs/claude/04-views.md) - Sistema de vistas
5
+ > Este archivo es para desarrollo INTERNO del CLI (código en `tools/cli/src/`)
10
6
 
11
- ## Quick Reference
7
+ ## Estructura del CLI
12
8
 
13
- ```bash
14
- # Contexto, diagnóstico y documentación
15
- gufi context # Genera contexto para Claude
16
- gufi doctor # Diagnóstico del sistema
17
- gufi docs # Ver topics disponibles
18
- gufi docs fields # Documentación de tipos de campo
19
- gufi docs errors # Errores comunes y soluciones
20
- gufi docs --search "currency" # Buscar en toda la documentación
21
-
22
- # Entornos
23
- gufi config # Ver entornos
24
- gufi config:local # Cambiar a localhost
25
- gufi config:prod # Cambiar a producción
26
-
27
- # Módulos
28
- gufi modules 146 # Ver módulos
29
- gufi module 360 --edit # Editar con $EDITOR
30
-
31
- # Automations
32
- gufi automations # Ver scripts
33
- gufi automation 15 --edit # Editar script
34
- gufi entity:automations 4136 # Ver triggers
35
-
36
- # Vistas
37
- gufi view:pull 13 # Descargar
38
- gufi view:push # Subir cambios
39
- gufi view:watch # Auto-sync
40
-
41
- # Datos
42
- gufi rows m360_t16192 # Listar registros
43
- gufi row:create table --data '{...}'
44
9
  ```
45
-
46
- ## Output JSON (para Claude/scripts)
47
-
48
- Todos los comandos de lectura soportan `--json` para output estructurado sin colores ni emojis:
49
-
50
- ```bash
51
- gufi companies --json # Lista companies en JSON
52
- gufi modules 146 --json # Lista módulos en JSON
53
- gufi module 360 --json # JSON del módulo
54
- gufi automations --json # Lista automations en JSON
55
- gufi automation 15 --json # Código y metadata del automation
56
- gufi schema --json # Estructura de tablas en JSON
57
- gufi rows m360_t16192 --json # Registros en JSON
58
- gufi row m360_t16192 5 --json # Registro específico en JSON
59
- gufi packages --json # Lista packages en JSON
60
- gufi package 14 --json # Detalles del package en JSON
10
+ tools/cli/
11
+ ├── src/
12
+ │ ├── index.ts # Entry point CLI
13
+ │ ├── mcp.ts # MCP Server (44 tools)
14
+ │ ├── commands/ # Comandos CLI
15
+ │ │ ├── context.ts # gufi context
16
+ │ │ ├── pull.ts # gufi view:pull
17
+ │ │ ├── push.ts # gufi view:push
18
+ │ │ ├── watch.ts # gufi view:watch
19
+ │ │ └── ...
20
+ │ └── lib/
21
+ │ ├── api.ts # Cliente API
22
+ │ ├── config.ts # Gestión de config (~/.gufi/)
23
+ │ └── sync.ts # Sincronización de vistas
24
+ ├── package.json
25
+ └── tsconfig.json
61
26
  ```
62
27
 
63
- Usar `--json` cuando necesites parsear el output programáticamente.
28
+ ## MCP Server
64
29
 
65
- ## MCP Server (Model Context Protocol)
30
+ El servidor MCP está en `src/mcp.ts` y expone 44 tools para que Claude interactúe con Gufi.
66
31
 
67
- El CLI incluye un servidor MCP que permite a Claude interactuar **directamente** con Gufi sin ejecutar comandos manualmente.
32
+ ### Tools principales (nuevos)
68
33
 
69
- ### Configuración (una sola vez)
34
+ - **`gufi_start`** - Entrypoint inteligente que auto-detecta contexto:
35
+ - Si está en gogufi/: Detecta codebase, apunta a docs/claude/
36
+ - Si está en carpeta de vista: Devuelve contexto de la vista
37
+ - Si no detecta nada: Lista packages del usuario
70
38
 
71
- ```bash
72
- claude mcp add --transport stdio gufi -- gufi mcp
73
- ```
39
+ - **`gufi_context`** - Ahora devuelve:
40
+ - `summary`: Resumen ejecutivo
41
+ - `next_actions`: Pasos sugeridos
42
+ - Auto-detección de codebase y vistas locales
74
43
 
75
- ### Tools disponibles (43 tools)
76
-
77
- **Contexto e Info (EMPEZAR AQUÍ):**
78
- - `gufi_context` - **USAR PRIMERO** - Genera contexto inteligente del proyecto
79
- - `gufi_whoami` - Usuario y entorno actual
80
- - `gufi_schema` - Estructura de tablas/campos
81
- - `gufi_docs` - **LEER DOCUMENTACIÓN** - Topics: fields, views, automations, errors, examples
82
-
83
- **Companies:**
84
- - `gufi_companies` - Listar companies
85
- - `gufi_company_create` - Crear company
86
-
87
- **Módulos (estructura de datos):**
88
- - `gufi_modules` - Listar módulos de una company
89
- - `gufi_module` - Ver JSON completo de un módulo
90
- - `gufi_module_update` - **Modificar módulo** (añadir campos, entidades)
91
- - `gufi_module_create` - Crear módulo nuevo
92
-
93
- **Automations (lógica de negocio):**
94
- - `gufi_automations` - Listar scripts
95
- - `gufi_automation` - Ver código JS de un script
96
- - `gufi_automation_create` - **Crear/actualizar script**
97
- - `gufi_entity_automations` - Ver triggers de una entidad
98
- - `gufi_entity_automations_update` - **Configurar triggers**
99
- - `gufi_automations_executions` - Ver historial de ejecuciones
100
-
101
- **Datos (CRUD):**
102
- - `gufi_rows` - Listar registros de una tabla
103
- - `gufi_row` - Ver un registro
104
- - `gufi_row_create` - Crear registro
105
- - `gufi_row_update` - Actualizar registro
106
- - `gufi_row_delete` - Eliminar registro
107
-
108
- **Environment Variables:**
109
- - `gufi_env` - Listar variables
110
- - `gufi_env_set` - Crear/actualizar variable
111
- - `gufi_env_delete` - Eliminar variable
112
-
113
- **Vistas (React/TSX):**
114
- - `gufi_view_files` - Ver archivos de una vista
115
- - `gufi_view_file_update` - **Modificar archivo de vista**
116
- - `gufi_view_files_update` - Modificar múltiples archivos
117
-
118
- **Packages (Marketplace):**
119
- - `gufi_packages` - Listar packages
120
- - `gufi_package` - Ver detalles
121
- - `gufi_package_create` - Crear package
122
- - `gufi_package_publish` - Publicar
123
- - `gufi_package_sync` - Sincronizar versión
124
- - `gufi_package_add_module` / `gufi_package_remove_module`
125
- - `gufi_package_add_view` / `gufi_package_remove_view`
126
-
127
- **Package Migrations:**
128
- - `gufi_package_migrations` - Listar migraciones
129
- - `gufi_package_migration_create` - Crear migración SQL
130
- - `gufi_package_entities` - Listar entidades para target_entity
131
-
132
- ### Ejemplos de uso con Claude
44
+ ### Añadir un nuevo tool MCP
133
45
 
46
+ 1. **Definir tool** en array `TOOLS` (~línea 200):
47
+ ```typescript
48
+ {
49
+ name: "gufi_nuevo_tool",
50
+ description: getDesc("gufi_nuevo_tool"),
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ param1: { type: "string", description: "..." },
55
+ },
56
+ required: ["param1"],
57
+ },
58
+ },
134
59
  ```
135
- Usuario: "Agrega un campo 'fecha_entrega' tipo date al módulo de pedidos"
136
- Claude: [usa gufi_module para leer] [modifica JSON] → [usa gufi_module_update]
137
- "Listo, agregué el campo fecha_entrega al módulo de pedidos"
138
-
139
- Usuario: "Crea un automation que envíe email cuando un pedido pase a 'enviado'"
140
- Claude: [usa gufi_automations para ver existentes]
141
- [escribe código JS]
142
- [usa gufi_automation_create]
143
- [usa gufi_entity_automations_update para configurar trigger]
144
- "Listo, creé el automation 'email_pedido_enviado' con trigger on_update"
145
-
146
- Usuario: "¿Cuántos clientes hay en la empresa 116?"
147
- Claude: [usa gufi_schema para encontrar tabla de clientes]
148
- [usa gufi_rows para consultar]
149
- "Hay 234 clientes en la tabla m360_t4136"
60
+
61
+ 2. **Añadir handler** en `toolHandlers` (~línea 870):
62
+ ```typescript
63
+ async gufi_nuevo_tool(params: { param1: string }) {
64
+ // Implementación
65
+ return { result: "..." };
66
+ },
150
67
  ```
151
68
 
152
- ### Tipos de Campo (@gufi/column-types)
69
+ 3. **Añadir descripción** en `docs/mcp/tool-descriptions.json`:
70
+ ```json
71
+ "gufi_nuevo_tool": {
72
+ "description": "Descripción clara del tool..."
73
+ }
74
+ ```
153
75
 
154
- Al crear o actualizar datos, usa los formatos correctos:
76
+ ### Funciones helper importantes
155
77
 
156
- **Simples:**
157
- - text, email, url, barcode: `"string"`
158
- - number_int: `42` | number_float: `3.14` | percentage: `0.75`
159
- - boolean: `true/false`
160
- - date: `"2024-01-15"` | datetime: `"2024-01-15T10:30:00Z"` | time: `"14:30:00"`
161
- - select: `"value"` | relation: `123`
78
+ - `detectIfInGufiCodebase()` - Detecta si está en el repo gogufi
79
+ - `loadViewMetaFromCwd()` - Carga `.gufi-view.json` del directorio actual
80
+ - `generateViewContextMcp()` - Genera contexto de una vista
81
+ - `generatePackageContextMcp()` - Genera contexto de un package
82
+ - `apiRequest()` - Peticiones a API con auth
83
+ - `developerRequest()` - Peticiones a /api/developer/
162
84
 
163
- **Arrays:**
164
- - multiselect: `["value1", "value2"]`
165
- - users: `[16, 23]`
85
+ ## CLI Commands
166
86
 
167
- **JSONB (objetos complejos):**
168
- - currency: `{ "currency": "EUR", "amount": 150.00 }`
169
- - phone: `{ "prefix": "+34", "number": "612345678" }`
170
- - location: `{ "street": "Mayor", "number": "15", "city": "Madrid", "lat": 40.41 }`
171
- - file: `[{ "url": "company_130/doc.pdf", "name": "doc.pdf" }]`
87
+ Cada comando está en `src/commands/`. Patrón común:
172
88
 
173
- En vistas usa `gufi.CB.*` para formatear correctamente:
174
89
  ```typescript
175
- gufi.CB.currency(150) // { currency: 'EUR', amount: 150 }
176
- gufi.CB.phone('612345678') // { prefix: '+34', number: '612345678' }
177
- gufi.CB.date() // '2024-01-15' (hoy)
178
- gufi.CB.multiselect('a', 'b') // → ['a', 'b']
90
+ export async function miComando(args: string[], flags: Flags) {
91
+ // 1. Parsear argumentos
92
+ // 2. Validar
93
+ // 3. Hacer petición API
94
+ // 4. Mostrar resultado
95
+ }
179
96
  ```
180
97
 
181
- ### Seguridad
98
+ ## Config (~/.gufi/)
182
99
 
183
- - Usa las credenciales del CLI (`gufi login`)
184
- - Solo accede a resources con permisos del usuario
185
- - Todo corre localmente (stdio), no hay servidor público
100
+ ```
101
+ ~/.gufi/
102
+ ├── config.json # Credenciales y entornos
103
+ └── gufi-dev/ # Vistas descargadas
104
+ └── view_13/
105
+ ├── .gufi-view.json # Metadata de sync
106
+ ├── index.tsx
107
+ └── ...
108
+ ```
186
109
 
187
- ## Comandos Esenciales
110
+ ## Testing
188
111
 
189
- | Quiero... | Comando |
190
- |-----------|---------|
191
- | **Contexto para Claude** | `gufi context` |
192
- | **Diagnóstico** | `gufi doctor` |
193
- | **Leer documentación** | `gufi docs fields` |
194
- | **Buscar en docs** | `gufi docs --search "currency"` |
195
- | Ver companies | `gufi companies` |
196
- | Ver módulos | `gufi modules 146` |
197
- | Editar módulo | `gufi module 360 --edit` |
198
- | Ver automations | `gufi automations` |
199
- | Desarrollar vista | `gufi view:pull 13` → `gufi view:push` |
112
+ ```bash
113
+ cd tools/cli
114
+ npm test
115
+ ```
200
116
 
201
- ## Tips
117
+ ## Build
202
118
 
203
- 1. **`gufi context`**: Úsalo al inicio de cualquier tarea
204
- 2. **Auto-detección**: `module`, `automation`, `rows` detectan company automáticamente
205
- 3. **--edit**: Abre en `$EDITOR`
206
- 4. **Entornos separados**: Cada uno con sus credenciales
207
- 5. **Auto-login**: CLI refresca tokens automáticamente
119
+ ```bash
120
+ npm run build # Compila TypeScript
121
+ npm link # Instala globalmente para testing
122
+ ```
208
123
 
209
- ## Documentación Completa
124
+ ## Documentación
210
125
 
211
- Para documentación detallada de cada comando, arquitectura, y patrones, ve a:
212
- - `docs/claude/` - Fuente de verdad para Claude
213
- - `docs/guide/27-gufi-cli.md` - Guía técnica del CLI
126
+ - **Para usuarios del CLI**: `docs/mcp/` (usado por `gufi_docs`)
127
+ - **Para desarrollo del CLI**: Este archivo
128
+ - **Tool descriptions**: `docs/mcp/tool-descriptions.json`
package/dist/mcp.js CHANGED
@@ -122,30 +122,34 @@ async function developerRequest(path, options = {}, retry = true) {
122
122
  return res.json();
123
123
  }
124
124
  // ════════════════════════════════════════════════════════════════════════════
125
- // Tool Definitions
125
+ // Tool Definitions - Descriptions loaded from docs/mcp/tool-descriptions.json
126
126
  // ════════════════════════════════════════════════════════════════════════════
127
+ // Load tool descriptions from centralized documentation
128
+ const TOOL_DESCRIPTIONS_PATH = path.join(DOCS_MCP_PATH, "tool-descriptions.json");
129
+ let toolDescriptions = {};
130
+ try {
131
+ const content = fs.readFileSync(TOOL_DESCRIPTIONS_PATH, "utf-8");
132
+ toolDescriptions = JSON.parse(content);
133
+ }
134
+ catch (err) {
135
+ console.error(`Warning: Could not load tool descriptions from ${TOOL_DESCRIPTIONS_PATH}`);
136
+ }
137
+ // Helper to get description from JSON or use fallback
138
+ function getDesc(toolName, fallback = "") {
139
+ return toolDescriptions[toolName]?.description || fallback;
140
+ }
127
141
  const TOOLS = [
128
142
  // ─────────────────────────────────────────────────────────────────────────
129
143
  // Context & Info
130
144
  // ─────────────────────────────────────────────────────────────────────────
145
+ {
146
+ name: "gufi_start",
147
+ description: getDesc("gufi_start"),
148
+ inputSchema: { type: "object", properties: {} },
149
+ },
131
150
  {
132
151
  name: "gufi_context",
133
- description: `Generate intelligent context about a Gufi project. This is the FIRST tool to use when starting work on a Gufi project - it provides a complete overview of modules, entities, fields, automations, and relationships.
134
-
135
- Use cases:
136
- - Starting work on a package: gufi_context({ package_id: "14" })
137
- - Understanding a view: gufi_context({ view_id: "13" })
138
- - Exploring a company: gufi_context({ company_id: "116" })
139
-
140
- The context includes:
141
- - All modules and their entities (tables) with physical table names
142
- - Field definitions with types, constraints, and options
143
- - Available automations and their trigger types
144
- - DataSources mappings for views (viewSpec.mainTable, etc.)
145
- - Environment variables available
146
- - Useful CLI commands for the project
147
-
148
- Returns markdown-formatted context optimized for Claude.`,
152
+ description: getDesc("gufi_context"),
149
153
  inputSchema: {
150
154
  type: "object",
151
155
  properties: {
@@ -158,20 +162,12 @@ Returns markdown-formatted context optimized for Claude.`,
158
162
  },
159
163
  {
160
164
  name: "gufi_whoami",
161
- description: "Get current user info and environment (local/prod). Use this to verify authentication status before making changes.",
165
+ description: getDesc("gufi_whoami"),
162
166
  inputSchema: { type: "object", properties: {} },
163
167
  },
164
168
  {
165
169
  name: "gufi_schema",
166
- description: `Get the database schema of a company - lists all modules, entities (tables), and their fields.
167
-
168
- Returns for each entity:
169
- - id: Entity ID
170
- - name: Entity name
171
- - table: Physical table name (m{moduleId}_t{entityId})
172
- - fields: Array of {name, type, label}
173
-
174
- Use this to understand the data structure before creating queries or modifications.`,
170
+ description: getDesc("gufi_schema"),
175
171
  inputSchema: {
176
172
  type: "object",
177
173
  properties: {
@@ -182,26 +178,7 @@ Use this to understand the data structure before creating queries or modificatio
182
178
  },
183
179
  {
184
180
  name: "gufi_docs",
185
- description: `Read documentation about Gufi. Use this when you need detailed information about specific topics.
186
-
187
- Available topics:
188
- - "overview" - Overview and workflow (start here)
189
- - "architecture" - Technical architecture
190
- - "modules" - Module system and entities
191
- - "fields" - Field types and CB builders (IMPORTANT for data operations)
192
- - "views" - View system, SDK, and React components
193
- - "automations" - Automations and worker
194
- - "api" - API endpoints reference
195
- - "packages" - Packages and marketplace
196
- - "errors" - Common errors and solutions
197
- - "examples" - Practical code examples
198
-
199
- You can also search across all docs with the search parameter.
200
-
201
- Examples:
202
- - gufi_docs({ topic: "fields" }) - Read about field types
203
- - gufi_docs({ topic: "errors" }) - Common errors and fixes
204
- - gufi_docs({ search: "currency" }) - Search for currency info`,
181
+ description: getDesc("gufi_docs"),
205
182
  inputSchema: {
206
183
  type: "object",
207
184
  properties: {
@@ -215,12 +192,12 @@ Examples:
215
192
  // ─────────────────────────────────────────────────────────────────────────
216
193
  {
217
194
  name: "gufi_companies",
218
- description: "List all companies the user has access to. Returns company IDs, names, and creation dates.",
195
+ description: getDesc("gufi_companies"),
219
196
  inputSchema: { type: "object", properties: {} },
220
197
  },
221
198
  {
222
199
  name: "gufi_company_create",
223
- description: "Create a new company. Returns the new company ID.",
200
+ description: getDesc("gufi_company_create"),
224
201
  inputSchema: {
225
202
  type: "object",
226
203
  properties: {
@@ -234,7 +211,7 @@ Examples:
234
211
  // ─────────────────────────────────────────────────────────────────────────
235
212
  {
236
213
  name: "gufi_modules",
237
- description: "List all modules of a company. Modules define the data structure (entities, fields, relations). Returns module IDs, names, and entity counts.",
214
+ description: getDesc("gufi_modules"),
238
215
  inputSchema: {
239
216
  type: "object",
240
217
  properties: {
@@ -245,26 +222,7 @@ Examples:
245
222
  },
246
223
  {
247
224
  name: "gufi_module",
248
- description: `Get the full JSON definition of a module. Auto-detects company from module ID.
249
-
250
- Returns the complete module structure:
251
- - name, displayName, icon
252
- - submodules[]: Array of submodules
253
- - entities[]: Array of entities (tables)
254
- - name, label, kind
255
- - fields[]: Array of fields with type, label, required, options, etc.
256
-
257
- Field types (from @gufi/column-types):
258
- - Text: text, email, url, barcode
259
- - Numbers: number_int, number_float, percentage
260
- - Date/Time: date, datetime, time
261
- - Boolean: boolean
262
- - Selection: select (single), multiselect (array)
263
- - Relations: relation (FK), reversed_relation (virtual), users (array of user IDs)
264
- - Complex (JSONB): currency, phone, location, file, signature, json
265
- - Computed: formula, mirror
266
-
267
- Each type has specific format. Use gufi.CB.* builders for correct format.`,
225
+ description: getDesc("gufi_module"),
268
226
  inputSchema: {
269
227
  type: "object",
270
228
  properties: {
@@ -275,33 +233,7 @@ Each type has specific format. Use gufi.CB.* builders for correct format.`,
275
233
  },
276
234
  {
277
235
  name: "gufi_module_update",
278
- description: `Update a module's JSON definition. Use this to add/modify entities, fields, relations.
279
-
280
- IMPORTANT: Always read the module first with gufi_module, modify the JSON, then update.
281
-
282
- Common modifications:
283
- - Add a field: Add to entity.fields array
284
- - Add an entity: Add to submodule.entities array
285
- - Modify field: Change properties like type, label, required, options
286
-
287
- Example field definition:
288
- {
289
- "name": "fecha_entrega",
290
- "type": "date",
291
- "label": "Fecha de Entrega",
292
- "required": false
293
- }
294
-
295
- For select fields, include options:
296
- {
297
- "name": "estado",
298
- "type": "select",
299
- "label": "Estado",
300
- "options": [
301
- { "value": "pendiente", "label": "Pendiente", "color": "yellow" },
302
- { "value": "completado", "label": "Completado", "color": "green" }
303
- ]
304
- }`,
236
+ description: getDesc("gufi_module_update"),
305
237
  inputSchema: {
306
238
  type: "object",
307
239
  properties: {
@@ -313,28 +245,7 @@ For select fields, include options:
313
245
  },
314
246
  {
315
247
  name: "gufi_module_create",
316
- description: `Create a new module in a company.
317
-
318
- Example module structure:
319
- {
320
- "name": "inventory",
321
- "displayName": "Inventario",
322
- "icon": "Package",
323
- "submodules": [{
324
- "name": "products",
325
- "label": "Productos",
326
- "entities": [{
327
- "name": "productos",
328
- "label": "Productos",
329
- "kind": "table",
330
- "fields": [
331
- { "name": "nombre", "type": "text", "label": "Nombre", "required": true },
332
- { "name": "precio", "type": "currency", "label": "Precio" },
333
- { "name": "stock", "type": "number_int", "label": "Stock" }
334
- ]
335
- }]
336
- }]
337
- }`,
248
+ description: getDesc("gufi_module_create"),
338
249
  inputSchema: {
339
250
  type: "object",
340
251
  properties: {
@@ -349,14 +260,7 @@ Example module structure:
349
260
  // ─────────────────────────────────────────────────────────────────────────
350
261
  {
351
262
  name: "gufi_automations",
352
- description: `List all automation scripts of a company. Automations are JavaScript functions that run on events.
353
-
354
- Trigger types:
355
- - on_create: Runs when a row is created
356
- - on_update: Runs when a row is updated
357
- - on_delete: Runs when a row is deleted
358
- - on_click: Manually triggered from UI buttons
359
- - schedule: Runs on a cron schedule`,
263
+ description: getDesc("gufi_automations"),
360
264
  inputSchema: {
361
265
  type: "object",
362
266
  properties: {
@@ -367,7 +271,7 @@ Trigger types:
367
271
  },
368
272
  {
369
273
  name: "gufi_automation",
370
- description: "Get the JavaScript code and metadata of an automation script. Returns id, name, description, company_id, and the full JS code.",
274
+ description: getDesc("gufi_automation"),
371
275
  inputSchema: {
372
276
  type: "object",
373
277
  properties: {
@@ -378,32 +282,7 @@ Trigger types:
378
282
  },
379
283
  {
380
284
  name: "gufi_automation_create",
381
- description: `Create or update an automation script. If a script with the same name exists, it will be updated.
382
-
383
- IMPORTANT: api.query() returns rows directly, NOT { rows }:
384
- const rows = await api.query("SELECT * FROM table"); // ✅ Correct
385
- const { rows } = await api.query(...); // ❌ Wrong!
386
-
387
- Available API methods:
388
- - api.query(sql, params) - Execute SQL, returns rows array
389
- - api.getOne(table, id) - Get single row
390
- - api.getList(table, { filters, sort, limit }) - Get multiple rows
391
- - api.create(table, data) - Create row, returns { id }
392
- - api.update(table, id, data) - Update row
393
- - api.delete(table, id) - Delete row
394
- - api.log(message) - Log for debugging
395
- - api.sendEmail({ to, subject, body }) - Send email
396
- - api.sendWhatsApp({ to, template, params }) - Send WhatsApp
397
-
398
- Example automation:
399
- async function send_welcome_email({ record, api }) {
400
- const { email, nombre } = record;
401
- await api.sendEmail({
402
- to: email,
403
- subject: "Bienvenido!",
404
- body: \`Hola \${nombre}, gracias por registrarte.\`
405
- });
406
- }`,
285
+ description: getDesc("gufi_automation_create"),
407
286
  inputSchema: {
408
287
  type: "object",
409
288
  properties: {
@@ -417,7 +296,7 @@ async function send_welcome_email({ record, api }) {
417
296
  },
418
297
  {
419
298
  name: "gufi_entity_automations",
420
- description: "Get the automation triggers configured for an entity. Shows which scripts run on create, update, delete, or click events.",
299
+ description: getDesc("gufi_entity_automations"),
421
300
  inputSchema: {
422
301
  type: "object",
423
302
  properties: {
@@ -428,19 +307,7 @@ async function send_welcome_email({ record, api }) {
428
307
  },
429
308
  {
430
309
  name: "gufi_entity_automations_update",
431
- description: `Update the automation triggers for an entity. Configure which scripts run on which events.
432
-
433
- Example configuration:
434
- {
435
- "on_create": ["send_welcome_email"],
436
- "on_update": ["sync_to_external", "notify_changes"],
437
- "on_delete": [],
438
- "on_click": [
439
- { "function_name": "generate_report", "label": "Generar Reporte", "icon": "FileText" }
440
- ]
441
- }
442
-
443
- For on_click, you can specify label and icon for the button that triggers it.`,
310
+ description: getDesc("gufi_entity_automations_update"),
444
311
  inputSchema: {
445
312
  type: "object",
446
313
  properties: {
@@ -455,7 +322,7 @@ For on_click, you can specify label and icon for the button that triggers it.`,
455
322
  },
456
323
  {
457
324
  name: "gufi_automations_executions",
458
- description: "Get the execution history of automations. Useful for debugging - shows success/failure, duration, and error messages.",
325
+ description: getDesc("gufi_automations_executions"),
459
326
  inputSchema: {
460
327
  type: "object",
461
328
  properties: {
@@ -471,13 +338,7 @@ For on_click, you can specify label and icon for the button that triggers it.`,
471
338
  // ─────────────────────────────────────────────────────────────────────────
472
339
  {
473
340
  name: "gufi_rows",
474
- description: `List rows from a table. Table names follow the pattern m{moduleId}_t{entityId}.
475
- Company is auto-detected from the module ID in the table name.
476
-
477
- Supports:
478
- - Pagination: limit (default 20), offset (default 0)
479
- - Sorting: sort (field name), order (ASC/DESC)
480
- - Filtering: filter="field=value"`,
341
+ description: getDesc("gufi_rows"),
481
342
  inputSchema: {
482
343
  type: "object",
483
344
  properties: {
@@ -493,7 +354,7 @@ Supports:
493
354
  },
494
355
  {
495
356
  name: "gufi_row",
496
- description: "Get a single row by ID. Returns all fields including relations and computed values.",
357
+ description: getDesc("gufi_row"),
497
358
  inputSchema: {
498
359
  type: "object",
499
360
  properties: {
@@ -505,35 +366,7 @@ Supports:
505
366
  },
506
367
  {
507
368
  name: "gufi_row_create",
508
- description: `Create a new row in a table. Data should match the entity's field schema.
509
-
510
- Field formats (from @gufi/column-types):
511
-
512
- SIMPLE TYPES:
513
- - text/email/url/barcode: "string value"
514
- - number_int: 42 (integer)
515
- - number_float: 3.14 (decimal)
516
- - percentage: 0.75 (decimal, displayed as 75%)
517
- - boolean: true/false
518
- - date: "2024-01-15" (ISO date)
519
- - datetime: "2024-01-15T10:30:00Z" (ISO)
520
- - time: "14:30:00"
521
- - select: "value" (option value, not label)
522
- - relation: 123 (FK integer)
523
-
524
- ARRAY TYPES:
525
- - multiselect: ["value1", "value2"]
526
- - users: [16, 23] (array of user IDs)
527
-
528
- JSONB TYPES (complex objects):
529
- - currency: { "currency": "EUR", "amount": 150.00 }
530
- - phone: { "prefix": "+34", "number": "612345678" }
531
- - location: { "street": "Mayor", "number": "15", "city": "Madrid", "lat": 40.41, "lng": -3.70 }
532
- - file: [{ "url": "company_130/uuid.pdf", "name": "doc.pdf" }] or ["company_130/photo.jpg"]
533
- - signature: "data:image/png;base64,..." (base64 data URL)
534
- - json: { any: "object" }
535
-
536
- In views, use gufi.CB.* builders for correct formatting.`,
369
+ description: getDesc("gufi_row_create"),
537
370
  inputSchema: {
538
371
  type: "object",
539
372
  properties: {
@@ -545,20 +378,7 @@ In views, use gufi.CB.* builders for correct formatting.`,
545
378
  },
546
379
  {
547
380
  name: "gufi_row_update",
548
- description: `Update an existing row. Only include fields you want to change.
549
-
550
- IMPORTANT for select/relation fields:
551
- When updating a select or relation field, you must update BOTH:
552
- - The field value: "estado": "completado"
553
- - The display value: "estado__display": "Completado"
554
-
555
- Example:
556
- {
557
- "estado": "completado",
558
- "estado__display": "Completado",
559
- "cliente": 123,
560
- "cliente__display": "Empresa ABC"
561
- }`,
381
+ description: getDesc("gufi_row_update"),
562
382
  inputSchema: {
563
383
  type: "object",
564
384
  properties: {
@@ -571,7 +391,7 @@ Example:
571
391
  },
572
392
  {
573
393
  name: "gufi_row_delete",
574
- description: "Delete a row from a table. This is permanent and cannot be undone.",
394
+ description: getDesc("gufi_row_delete"),
575
395
  inputSchema: {
576
396
  type: "object",
577
397
  properties: {
@@ -586,7 +406,7 @@ Example:
586
406
  // ─────────────────────────────────────────────────────────────────────────
587
407
  {
588
408
  name: "gufi_env",
589
- description: "List environment variables of a company. These are used in automations via process.env.KEY.",
409
+ description: getDesc("gufi_env"),
590
410
  inputSchema: {
591
411
  type: "object",
592
412
  properties: {
@@ -596,7 +416,7 @@ Example:
596
416
  },
597
417
  {
598
418
  name: "gufi_env_set",
599
- description: "Create or update an environment variable. Used for API keys, secrets, and configuration.",
419
+ description: getDesc("gufi_env_set"),
600
420
  inputSchema: {
601
421
  type: "object",
602
422
  properties: {
@@ -608,7 +428,7 @@ Example:
608
428
  },
609
429
  {
610
430
  name: "gufi_env_delete",
611
- description: "Delete an environment variable.",
431
+ description: getDesc("gufi_env_delete"),
612
432
  inputSchema: {
613
433
  type: "object",
614
434
  properties: {
@@ -622,7 +442,7 @@ Example:
622
442
  // ─────────────────────────────────────────────────────────────────────────
623
443
  {
624
444
  name: "gufi_view_files",
625
- description: "Get all files of a marketplace view. Returns the React/TypeScript code, CSS, and configuration files.",
445
+ description: getDesc("gufi_view_files"),
626
446
  inputSchema: {
627
447
  type: "object",
628
448
  properties: {
@@ -633,7 +453,7 @@ Example:
633
453
  },
634
454
  {
635
455
  name: "gufi_view_file_update",
636
- description: "Update a single file in a marketplace view. Use for modifying React components, styles, or configuration.",
456
+ description: getDesc("gufi_view_file_update"),
637
457
  inputSchema: {
638
458
  type: "object",
639
459
  properties: {
@@ -646,7 +466,7 @@ Example:
646
466
  },
647
467
  {
648
468
  name: "gufi_view_files_update",
649
- description: "Update multiple files in a marketplace view at once. More efficient than updating one by one.",
469
+ description: getDesc("gufi_view_files_update"),
650
470
  inputSchema: {
651
471
  type: "object",
652
472
  properties: {
@@ -672,12 +492,12 @@ Example:
672
492
  // ─────────────────────────────────────────────────────────────────────────
673
493
  {
674
494
  name: "gufi_packages",
675
- description: "List all packages owned by the user. Packages bundle modules and views for distribution in the Marketplace.",
495
+ description: getDesc("gufi_packages"),
676
496
  inputSchema: { type: "object", properties: {} },
677
497
  },
678
498
  {
679
499
  name: "gufi_package",
680
- description: "Get detailed information about a package including its modules, views, and publication status.",
500
+ description: getDesc("gufi_package"),
681
501
  inputSchema: {
682
502
  type: "object",
683
503
  properties: {
@@ -688,7 +508,7 @@ Example:
688
508
  },
689
509
  {
690
510
  name: "gufi_package_create",
691
- description: "Create a new package. After creation, add modules and views to it.",
511
+ description: getDesc("gufi_package_create"),
692
512
  inputSchema: {
693
513
  type: "object",
694
514
  properties: {
@@ -700,7 +520,7 @@ Example:
700
520
  },
701
521
  {
702
522
  name: "gufi_package_delete",
703
- description: "Delete a package. Only works if the package is not published.",
523
+ description: getDesc("gufi_package_delete"),
704
524
  inputSchema: {
705
525
  type: "object",
706
526
  properties: {
@@ -711,7 +531,7 @@ Example:
711
531
  },
712
532
  {
713
533
  name: "gufi_package_add_module",
714
- description: "Import a module into a package. The module will be snapshotted for distribution.",
534
+ description: getDesc("gufi_package_add_module"),
715
535
  inputSchema: {
716
536
  type: "object",
717
537
  properties: {
@@ -724,7 +544,7 @@ Example:
724
544
  },
725
545
  {
726
546
  name: "gufi_package_remove_module",
727
- description: "Remove a module from a package.",
547
+ description: getDesc("gufi_package_remove_module"),
728
548
  inputSchema: {
729
549
  type: "object",
730
550
  properties: {
@@ -736,7 +556,7 @@ Example:
736
556
  },
737
557
  {
738
558
  name: "gufi_package_add_view",
739
- description: "Add a marketplace view to a package.",
559
+ description: getDesc("gufi_package_add_view"),
740
560
  inputSchema: {
741
561
  type: "object",
742
562
  properties: {
@@ -748,7 +568,7 @@ Example:
748
568
  },
749
569
  {
750
570
  name: "gufi_package_remove_view",
751
- description: "Remove a view from a package.",
571
+ description: getDesc("gufi_package_remove_view"),
752
572
  inputSchema: {
753
573
  type: "object",
754
574
  properties: {
@@ -760,7 +580,7 @@ Example:
760
580
  },
761
581
  {
762
582
  name: "gufi_package_publish",
763
- description: "Publish a package to the Marketplace. Makes it available for installation by other companies.",
583
+ description: getDesc("gufi_package_publish"),
764
584
  inputSchema: {
765
585
  type: "object",
766
586
  properties: {
@@ -771,7 +591,7 @@ Example:
771
591
  },
772
592
  {
773
593
  name: "gufi_package_unpublish",
774
- description: "Unpublish a package from the Marketplace.",
594
+ description: getDesc("gufi_package_unpublish"),
775
595
  inputSchema: {
776
596
  type: "object",
777
597
  properties: {
@@ -782,7 +602,7 @@ Example:
782
602
  },
783
603
  {
784
604
  name: "gufi_package_sync",
785
- description: "Sync package version - updates module snapshots and increments version number.",
605
+ description: getDesc("gufi_package_sync"),
786
606
  inputSchema: {
787
607
  type: "object",
788
608
  properties: {
@@ -793,7 +613,7 @@ Example:
793
613
  },
794
614
  {
795
615
  name: "gufi_package_check",
796
- description: "Check if package modules have changes that need syncing.",
616
+ description: getDesc("gufi_package_check"),
797
617
  inputSchema: {
798
618
  type: "object",
799
619
  properties: {
@@ -807,7 +627,7 @@ Example:
807
627
  // ─────────────────────────────────────────────────────────────────────────
808
628
  {
809
629
  name: "gufi_package_migrations",
810
- description: "List SQL migrations for a package. Migrations run when clients update to new versions.",
630
+ description: getDesc("gufi_package_migrations"),
811
631
  inputSchema: {
812
632
  type: "object",
813
633
  properties: {
@@ -818,7 +638,7 @@ Example:
818
638
  },
819
639
  {
820
640
  name: "gufi_package_migration_create",
821
- description: "Create a SQL migration for a package. Use placeholders: {tableName}, {entityId}, {companyId}.",
641
+ description: getDesc("gufi_package_migration_create"),
822
642
  inputSchema: {
823
643
  type: "object",
824
644
  properties: {
@@ -834,7 +654,7 @@ Example:
834
654
  },
835
655
  {
836
656
  name: "gufi_package_migration_delete",
837
- description: "Delete a migration (only if not yet applied to any installation).",
657
+ description: getDesc("gufi_package_migration_delete"),
838
658
  inputSchema: {
839
659
  type: "object",
840
660
  properties: {
@@ -846,7 +666,7 @@ Example:
846
666
  },
847
667
  {
848
668
  name: "gufi_package_entities",
849
- description: "List entities available in a package. Use for target_entity in migrations.",
669
+ description: getDesc("gufi_package_entities"),
850
670
  inputSchema: {
851
671
  type: "object",
852
672
  properties: {
@@ -927,11 +747,117 @@ async function detectCompanyFromTable(table) {
927
747
  const result = await detectCompanyFromModule(moduleId);
928
748
  return result?.companyId;
929
749
  }
750
+ // ─────────────────────────────────────────────────────────────────────────────
751
+ // Context Auto-Detection Helpers
752
+ // ─────────────────────────────────────────────────────────────────────────────
753
+ /**
754
+ * Detect if we're inside the gogufi codebase (for internal development)
755
+ * Checks for presence of key directories: backend/, frontend/, tools/cli/, CLAUDE.md
756
+ */
757
+ function detectIfInGufiCodebase() {
758
+ try {
759
+ const cwd = process.cwd();
760
+ const indicators = [
761
+ path.join(cwd, "backend"),
762
+ path.join(cwd, "frontend"),
763
+ path.join(cwd, "tools", "cli"),
764
+ path.join(cwd, "CLAUDE.md"),
765
+ ];
766
+ const matches = indicators.filter((p) => fs.existsSync(p));
767
+ return matches.length >= 3; // If 3+ indicators exist, it's the codebase
768
+ }
769
+ catch {
770
+ return false;
771
+ }
772
+ }
773
+ function loadViewMetaFromCwd() {
774
+ try {
775
+ const metaPath = path.join(process.cwd(), ".gufi-view.json");
776
+ if (fs.existsSync(metaPath)) {
777
+ return JSON.parse(fs.readFileSync(metaPath, "utf-8"));
778
+ }
779
+ }
780
+ catch { }
781
+ return null;
782
+ }
930
783
  // Tool handler implementations
931
784
  const toolHandlers = {
932
785
  // ─────────────────────────────────────────────────────────────────────────
933
786
  // Context & Info
934
787
  // ─────────────────────────────────────────────────────────────────────────
788
+ /**
789
+ * Smart entrypoint that auto-detects context and provides guidance
790
+ */
791
+ async gufi_start() {
792
+ // 1. Check if we're in the gogufi codebase (internal development)
793
+ if (detectIfInGufiCodebase()) {
794
+ return {
795
+ detected: "gogufi_codebase",
796
+ summary: "You are inside the Gufi codebase. This is for INTERNAL platform development.",
797
+ what_to_read: {
798
+ first: "docs/claude/01-critical-rules.md - MUST READ (deployment, notificaciones, traducciones)",
799
+ architecture: "docs/claude/02-architecture.md",
800
+ patterns: "docs/claude/07-patterns.md - Common errors and patterns",
801
+ },
802
+ important_rules: {
803
+ hot_reload: "Frontend and backend auto-reload on save. DON'T restart manually.",
804
+ column_types: "After libs/column-types changes: cd libs/column-types && npm run build",
805
+ no_deploy: "NEVER deploy to production without explicit user request.",
806
+ notifications: "Use toastSuccess/toastError from @/shared/notifications/toast (NOT shadcn)",
807
+ translations: "Add to es.ts AND en.ts BEFORE using tUI()",
808
+ },
809
+ for_client_work: "If you need to work on packages/views, use: gufi_context({ package_id: 'X' })",
810
+ };
811
+ }
812
+ // 2. Check if we're in a view directory (.gufi-view.json)
813
+ const viewMeta = loadViewMetaFromCwd();
814
+ if (viewMeta) {
815
+ const context = await generateViewContextMcp(viewMeta.viewId, false);
816
+ return {
817
+ detected: "view_directory",
818
+ summary: `Working on view "${viewMeta.viewName}" (ID: ${viewMeta.viewId})`,
819
+ ...context,
820
+ workflow: {
821
+ edit: "Edit files with your editor, changes will sync",
822
+ watch: "Run: gufi view:watch (auto-syncs on save)",
823
+ push: "Manual push: gufi view:push",
824
+ logs: "View logs: gufi view:logs",
825
+ },
826
+ };
827
+ }
828
+ // 3. Fallback: List packages and guide
829
+ try {
830
+ const response = await developerRequest("/my-packages");
831
+ const packages = response.data || [];
832
+ return {
833
+ detected: "none",
834
+ summary: `No specific context detected. You have ${packages.length} package(s).`,
835
+ packages: packages.map((p) => ({
836
+ id: p.pk_id,
837
+ name: p.name,
838
+ version: p.version,
839
+ status: p.status,
840
+ })),
841
+ how_to_start: [
842
+ "Get package context: gufi_context({ package_id: 'X' })",
843
+ "Get view context: gufi_context({ view_id: 'Y' })",
844
+ "Pull a view locally: gufi view:pull <id>",
845
+ "Then gufi_start will auto-detect",
846
+ ],
847
+ if_building_new: [
848
+ "Create package: gufi_package_create({ name: 'My Package' })",
849
+ "Then add modules and views",
850
+ ],
851
+ };
852
+ }
853
+ catch {
854
+ return {
855
+ detected: "none",
856
+ summary: "Could not fetch packages. Make sure you're logged in.",
857
+ hint: "Run: gufi login",
858
+ };
859
+ }
860
+ },
935
861
  async gufi_whoami() {
936
862
  const config = loadConfig();
937
863
  return {
@@ -953,18 +879,57 @@ const toolHandlers = {
953
879
  return generateCompanyContextMcp(parseInt(params.company_id), params.full);
954
880
  }
955
881
  else {
956
- // Return packages overview as fallback
882
+ // Auto-detect context from current directory
883
+ // 1. Check if we're in the gogufi codebase
884
+ if (detectIfInGufiCodebase()) {
885
+ return {
886
+ type: "codebase",
887
+ summary: "You are inside the Gufi codebase (gogufi/). This is for INTERNAL development of the platform.",
888
+ what_to_do: {
889
+ for_codebase_work: [
890
+ "Read docs/claude/01-critical-rules.md FIRST (deployment rules, notificaciones, traducciones)",
891
+ "Architecture: docs/claude/02-architecture.md",
892
+ "Patterns & errors: docs/claude/07-patterns.md",
893
+ ],
894
+ for_client_work: [
895
+ "To work on a specific package: gufi_context({ package_id: 'X' })",
896
+ "To work on a specific view: gufi_context({ view_id: 'Y' })",
897
+ "List your packages: gufi_packages()",
898
+ ],
899
+ },
900
+ important_rules: {
901
+ hot_reload: "Frontend and backend auto-reload on file save. DON'T restart manually.",
902
+ column_types: "After changes to libs/column-types: cd libs/column-types && npm run build",
903
+ no_deploy: "NEVER deploy to production without explicit request from user.",
904
+ },
905
+ docs_structure: {
906
+ "docs/claude/": "For INTERNAL codebase development (you are here)",
907
+ "docs/mcp/": "For platform USERS (consultants building ERPs) - used by gufi_docs tool",
908
+ },
909
+ };
910
+ }
911
+ // 2. Check if we're in a view directory (.gufi-view.json)
912
+ const viewMeta = loadViewMetaFromCwd();
913
+ if (viewMeta) {
914
+ return generateViewContextMcp(viewMeta.viewId, params.full);
915
+ }
916
+ // 3. Fallback: Return packages overview
957
917
  const response = await developerRequest("/my-packages");
958
918
  const packages = response.data || [];
959
919
  return {
960
920
  type: "packages_overview",
921
+ summary: `You have ${packages.length} package(s). Specify one to get detailed context.`,
961
922
  packages: packages.map((p) => ({
962
923
  id: p.pk_id,
963
924
  name: p.name,
964
925
  version: p.version,
965
926
  status: p.status,
966
927
  })),
967
- hint: "Specify package_id, view_id, or company_id for detailed context",
928
+ next_actions: [
929
+ "Get package context: gufi_context({ package_id: 'X' })",
930
+ "Get view context: gufi_context({ view_id: 'Y' })",
931
+ "Pull a view locally: gufi view:pull <id> (then gufi_context will auto-detect)",
932
+ ],
968
933
  };
969
934
  }
970
935
  },
@@ -1354,6 +1319,15 @@ const toolHandlers = {
1354
1319
  content: f.content,
1355
1320
  is_entry_point: f.is_entry_point,
1356
1321
  })),
1322
+ _hint: {
1323
+ cli_workflow: [
1324
+ `gufi view:pull ${params.view_id} # Download files to local folder`,
1325
+ "# Edit files locally with your editor",
1326
+ "gufi view:push # Upload changes back to Gufi",
1327
+ "gufi view:watch # Auto-sync on file changes",
1328
+ ],
1329
+ note: "For large views, consider using CLI commands instead of MCP tools",
1330
+ },
1357
1331
  };
1358
1332
  },
1359
1333
  async gufi_view_file_update(params) {
@@ -1592,8 +1566,33 @@ async function generateViewContextMcp(viewId, includeConcepts) {
1592
1566
  tableStructures[dsKey] = tableInfo;
1593
1567
  }
1594
1568
  }
1569
+ // Build summary and next_actions
1570
+ const dsCount = Object.keys(dataSources).length;
1571
+ const autoCount = automations.length;
1572
+ const firstTable = Object.values(dataSources)[0];
1573
+ const summary = [
1574
+ `View "${view.name}" (ID: ${viewId})`,
1575
+ pkg ? `Package: "${pkg.name}"` : "Independent view",
1576
+ dsCount > 0 ? `${dsCount} dataSource(s): ${Object.keys(dataSources).join(", ")}` : "No dataSources configured",
1577
+ autoCount > 0 ? `${autoCount} automation(s) available` : "No automations",
1578
+ ].join(" | ");
1579
+ const nextActions = [];
1580
+ // Always first: pull for local editing
1581
+ nextActions.push(`Edit locally: gufi view:pull ${viewId} && gufi view:watch`);
1582
+ // If has tables, suggest viewing data
1583
+ if (firstTable) {
1584
+ nextActions.push(`View data: gufi_rows({ table: "${firstTable}", limit: 5 })`);
1585
+ }
1586
+ // If has automations, suggest viewing them
1587
+ if (autoCount > 0 && viewCompanyId) {
1588
+ nextActions.push(`See automations: gufi_automations({ company_id: "${viewCompanyId}" })`);
1589
+ }
1590
+ // Always: docs for field types
1591
+ nextActions.push(`Field types reference: gufi_docs({ topic: "fields" })`);
1595
1592
  const result = {
1596
1593
  type: "view",
1594
+ summary,
1595
+ next_actions: nextActions,
1597
1596
  view_id: viewId,
1598
1597
  name: view.name,
1599
1598
  view_type: view.view_type || "marketplace_view",
@@ -1639,8 +1638,33 @@ async function generatePackageContextMcp(packageId, includeConcepts) {
1639
1638
  source_module_id: mod.source_module_id,
1640
1639
  });
1641
1640
  }
1641
+ // Build summary and next_actions
1642
+ const summary = [
1643
+ `Package "${pkg.name}" (ID: ${packageId})`,
1644
+ `Version: ${pkg.version || "0.1.0"}`,
1645
+ `Status: ${pkg.status || "draft"}`,
1646
+ `${modulesInfo.length} module(s)`,
1647
+ `${views.length} view(s)`,
1648
+ ].join(" | ");
1649
+ const nextActions = [];
1650
+ // If has views, suggest editing one
1651
+ if (views.length > 0) {
1652
+ const firstView = views[0];
1653
+ nextActions.push(`Edit a view: gufi view:pull ${firstView.view_id} && gufi view:watch`);
1654
+ nextActions.push(`Get view context: gufi_context({ view_id: "${firstView.view_id}" })`);
1655
+ }
1656
+ // If has sandbox company, suggest exploring data
1657
+ if (pkg.sandbox_company_id) {
1658
+ nextActions.push(`Explore sandbox data: gufi_schema({ company_id: "${pkg.sandbox_company_id}" })`);
1659
+ }
1660
+ // If draft, suggest publishing workflow
1661
+ if (pkg.status === "draft" || !pkg.status) {
1662
+ nextActions.push(`When ready: gufi package:sync ${packageId} && gufi package:publish ${packageId}`);
1663
+ }
1642
1664
  const result = {
1643
1665
  type: "package",
1666
+ summary,
1667
+ next_actions: nextActions,
1644
1668
  package_id: packageId,
1645
1669
  name: pkg.name,
1646
1670
  version: pkg.version || "0.1.0",
@@ -1714,8 +1738,35 @@ async function generateCompanyContextMcp(companyId, includeConcepts) {
1714
1738
  entities,
1715
1739
  });
1716
1740
  }
1741
+ // Build summary and next_actions
1742
+ const totalEntities = modulesInfo.reduce((acc, m) => acc + (m.entities?.length || 0), 0);
1743
+ const summary = [
1744
+ `Company ID: ${companyId}`,
1745
+ `${modulesInfo.length} module(s)`,
1746
+ `${totalEntities} table(s)`,
1747
+ `${automations.length} automation(s)`,
1748
+ ].join(" | ");
1749
+ const nextActions = [];
1750
+ // Suggest viewing data from first table
1751
+ if (modulesInfo.length > 0 && modulesInfo[0].entities?.length > 0) {
1752
+ const firstTable = modulesInfo[0].entities[0].table;
1753
+ if (firstTable) {
1754
+ nextActions.push(`View data: gufi_rows({ table: "${firstTable}", limit: 5 })`);
1755
+ }
1756
+ }
1757
+ // If has modules, suggest editing one
1758
+ if (modulesInfo.length > 0 && modulesInfo[0].id) {
1759
+ nextActions.push(`Edit module structure: gufi_module({ module_id: "${modulesInfo[0].id}" })`);
1760
+ }
1761
+ // If has automations, suggest viewing them
1762
+ if (automations.length > 0) {
1763
+ nextActions.push(`View automation code: gufi_automation({ automation_id: "${automations[0].id}" })`);
1764
+ }
1765
+ nextActions.push(`Field types reference: gufi_docs({ topic: "fields" })`);
1717
1766
  const result = {
1718
1767
  type: "company",
1768
+ summary,
1769
+ next_actions: nextActions,
1719
1770
  company_id: companyId,
1720
1771
  modules: modulesInfo,
1721
1772
  automations: automations.map((a) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gufi-cli",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "CLI for developing Gufi Marketplace views locally with Claude Code",
5
5
  "bin": {
6
6
  "gufi": "./bin/gufi.js"