@cristiancorreau/forge 3.0.1 → 3.2.0
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/CHANGELOG.md +38 -0
- package/README.md +265 -109
- package/assets/adapters/claude-code/commands/laravel-eloquent.md +7 -0
- package/assets/adapters/claude-code/commands/laravel-mcp.md +7 -0
- package/assets/adapters/claude-code/commands/laravel-pest.md +7 -0
- package/assets/adapters/claude-code/commands/laravel-security.md +7 -0
- package/assets/adapters/claude-code/commands/laravel-verify.md +7 -0
- package/assets/core/hooks/pre-bash-check.js +46 -0
- package/assets/core/hooks/pre-edit-check.js +24 -1
- package/assets/core/schemas/project.schema.json +3 -1
- package/assets/core/skills/laravel-eloquent/SKILL.md +453 -0
- package/assets/core/skills/laravel-mcp/SKILL.md +468 -0
- package/assets/core/skills/laravel-pest/SKILL.md +686 -0
- package/assets/core/skills/laravel-security/SKILL.md +658 -0
- package/assets/core/skills/laravel-verify/SKILL.md +462 -0
- package/assets/manifest.json +27 -2
- package/assets/profiles/astro/agents/frontend-engineer.md +2 -0
- package/assets/profiles/django/agents/api-engineer.md +2 -0
- package/assets/profiles/expo/agents/mobile-engineer.md +2 -0
- package/assets/profiles/express/agents/api-engineer.md +2 -0
- package/assets/profiles/fastapi/agents/api-engineer.md +2 -0
- package/assets/profiles/flask/agents/api-engineer.md +2 -0
- package/assets/profiles/flutter/agents/mobile-engineer.md +12 -10
- package/assets/profiles/go-gin/agents/api-engineer.md +3 -1
- package/assets/profiles/hono-drizzle/agents/api-engineer.md +2 -0
- package/assets/profiles/laravel/README.md +16 -2
- package/assets/profiles/laravel/agents/api-engineer.md +2 -0
- package/assets/profiles/laravel/agents/fullstack-engineer.md +4 -2
- package/assets/profiles/laravel/agents/laravel-specialist.md +607 -0
- package/assets/profiles/laravel/agents/laravel-test-engineer.md +448 -0
- package/assets/profiles/nestjs/agents/api-engineer.md +3 -1
- package/assets/profiles/nextjs-admin/agents/admin-engineer.md +2 -0
- package/assets/profiles/playwright-crawler/agents/scanner-engineer.md +2 -0
- package/assets/profiles/rails/agents/fullstack-engineer.md +2 -0
- package/assets/profiles/rust/agents/api-engineer.md +2 -0
- package/assets/profiles/springboot/agents/api-engineer.md +11 -9
- package/assets/profiles/sveltekit/agents/frontend-engineer.md +4 -2
- package/assets/profiles/vuenuxt/agents/frontend-engineer.md +12 -10
- package/assets/profiles/wordpress/agents/divi-engineer.md +2 -0
- package/assets/profiles/wordpress/agents/elementor-engineer.md +2 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +187 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/mcp.d.ts +42 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +141 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/update.d.ts +30 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +180 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +40 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/lib/catalog.d.ts +7 -0
- package/dist/lib/catalog.d.ts.map +1 -1
- package/dist/lib/catalog.js +20 -0
- package/dist/lib/catalog.js.map +1 -1
- package/dist/lib/mcp-tools.d.ts +37 -0
- package/dist/lib/mcp-tools.d.ts.map +1 -0
- package/dist/lib/mcp-tools.js +124 -0
- package/dist/lib/mcp-tools.js.map +1 -0
- package/dist/lib/skill-security.d.ts +66 -0
- package/dist/lib/skill-security.d.ts.map +1 -0
- package/dist/lib/skill-security.js +225 -0
- package/dist/lib/skill-security.js.map +1 -0
- package/dist/lib/skill-source.d.ts +29 -0
- package/dist/lib/skill-source.d.ts.map +1 -0
- package/dist/lib/skill-source.js +94 -0
- package/dist/lib/skill-source.js.map +1 -0
- package/dist/tui/dashboard.d.ts.map +1 -1
- package/dist/tui/dashboard.js +3 -6
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/tui/panel.d.ts.map +1 -1
- package/dist/tui/panel.js +3 -6
- package/dist/tui/panel.js.map +1 -1
- package/dist/tui/wizard.d.ts.map +1 -1
- package/dist/tui/wizard.js +3 -13
- package/dist/tui/wizard.js.map +1 -1
- package/dist/ui/colors.d.ts +3 -1
- package/dist/ui/colors.d.ts.map +1 -1
- package/dist/ui/colors.js +11 -2
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/header.d.ts.map +1 -1
- package/dist/ui/header.js +4 -3
- package/dist/ui/header.js.map +1 -1
- package/dist/ui/theme.d.ts +24 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +32 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# Skill: laravel-mcp
|
|
2
|
+
|
|
3
|
+
Laravel para agentes y MCP: instala Laravel Boost (MCP de desarrollo), construye tu propio
|
|
4
|
+
servidor MCP con `laravel/mcp`, usa el AI SDK first-party (`laravel/ai`) para agentes con
|
|
5
|
+
tool-calling y embeddings, y expón tu app a clientes de IA de forma segura. Actívalo cuando el
|
|
6
|
+
proyecto sea Laravel y haya que integrar IA, MCP o introspección por agentes.
|
|
7
|
+
|
|
8
|
+
Triggers: /laravel-mcp, "laravel boost", "servidor mcp laravel", "exponer mi app a un agente",
|
|
9
|
+
"laravel ai sdk", "agente laravel", "tool calling laravel", "embeddings laravel", "pgvector laravel",
|
|
10
|
+
"rag laravel", "boost install", "make:mcp-server", "make:agent".
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Cuándo usar este skill
|
|
15
|
+
|
|
16
|
+
- Al instalar **Laravel Boost** para que el agente tenga introspección del proyecto (schema, rutas, logs, docs).
|
|
17
|
+
- Al construir **tu propio servidor MCP** con `laravel/mcp` para exponer tu app a clientes externos (Claude, ChatGPT, editores).
|
|
18
|
+
- Al construir **features de IA dentro de la app** con el AI SDK (`laravel/ai`): agentes, tool-calling, structured output.
|
|
19
|
+
- Al implementar **búsqueda semántica / RAG** con embeddings y pgvector.
|
|
20
|
+
- Al decidir **cómo exponer la app a agentes de forma segura** (auth, scopes, tools read-only).
|
|
21
|
+
|
|
22
|
+
> Las versiones recientes de Laravel usan estructura slim: no existe `app/Http/Kernel.php` ni
|
|
23
|
+
> `app/Console/Kernel.php`; todo el middleware se configura en `bootstrap/app.php` dentro de
|
|
24
|
+
> `->withMiddleware(...)`. Verifica leyendo `bootstrap/app.php` y la documentación oficial de tu
|
|
25
|
+
> versión instalada (`laravel.com/docs/{tu-versión}.x`), y confirma el requisito de PHP de tu versión.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Los tres paquetes de IA — NO son intercambiables
|
|
30
|
+
|
|
31
|
+
| Paquete | Qué hace | Quién lo usa | Producción |
|
|
32
|
+
|---------|----------|--------------|------------|
|
|
33
|
+
| **AI SDK** (`laravel/ai`) | Construir features de IA **dentro** de tu app | Tu app y sus usuarios finales | Sí |
|
|
34
|
+
| **Boost** (`laravel/boost`) | Ayudar a los **agentes** a escribir mejor código Laravel | Tú, el desarrollador | **Solo `--dev`** |
|
|
35
|
+
| **MCP** (`laravel/mcp`) | **Exponer** la funcionalidad de tu app a clientes de IA externos | Clientes externos (Claude, ChatGPT) | Sí |
|
|
36
|
+
|
|
37
|
+
Una app de producción puede usar los tres. **Boost está construido sobre `laravel/mcp`.** Las tools del
|
|
38
|
+
AI SDK (`Laravel\Ai\Contracts\Tool`) y las tools de MCP (`Laravel\Mcp\Server\Tool`) son clases distintas
|
|
39
|
+
con propósitos distintos: no las mezcles.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Guidelines vs Skills (concepto transversal)
|
|
44
|
+
|
|
45
|
+
- **Guidelines** = se cargan **upfront** (al inicio del contexto). Son convenciones version-aware que el
|
|
46
|
+
agente recibe siempre. Boost las inyecta automáticamente según las versiones detectadas del proyecto.
|
|
47
|
+
- **Skills** = se cargan **on-demand** (cuando hacen falta). Son capacidades especializadas que el agente
|
|
48
|
+
activa por trigger, sin pesar en el contexto base.
|
|
49
|
+
|
|
50
|
+
Boost provee ambos: AI Guidelines (siempre presentes, version-aware) y Agent Skills (bajo demanda).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 1 — Laravel Boost: introspección del proyecto para el agente (dev-only)
|
|
55
|
+
|
|
56
|
+
Boost levanta un servidor MCP **de desarrollo** que le da al agente herramientas para inspeccionar el
|
|
57
|
+
proyecto real. Nunca afecta producción.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
composer require laravel/boost --dev
|
|
61
|
+
php artisan boost:install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`boost:install` detecta el stack, instala las AI Guidelines version-aware y registra el servidor MCP en
|
|
65
|
+
los clientes soportados (Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot, Junie).
|
|
66
|
+
|
|
67
|
+
Registro manual en Claude Code (si hace falta):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
claude mcp add -s local -t stdio laravel-boost php artisan boost:mcp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
El servidor MCP corre con:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
php artisan boost:mcp
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Tools que expone Boost
|
|
80
|
+
|
|
81
|
+
La tabla oficial *Available MCP Tools* lista **11 herramientas** (el "15+" que circula es copy de marketing):
|
|
82
|
+
|
|
83
|
+
| Tool | Para qué |
|
|
84
|
+
|------|----------|
|
|
85
|
+
| Application Info | versiones de PHP/Laravel, paquetes, modelos detectados |
|
|
86
|
+
| Database Schema | estructura de tablas/columnas/índices |
|
|
87
|
+
| Database Query | ejecutar queries de lectura contra la BD del proyecto |
|
|
88
|
+
| Database Connections | conexiones configuradas |
|
|
89
|
+
| Route Inspector | inspeccionar rutas registradas |
|
|
90
|
+
| Tinker | evaluar código en el contexto de la app |
|
|
91
|
+
| Read Log Entries | leer entradas de `laravel.log` |
|
|
92
|
+
| Last Error | el último error capturado |
|
|
93
|
+
| Browser Logs | logs del navegador (frontend) |
|
|
94
|
+
| Get Absolute URL | resolver URLs absolutas del proyecto |
|
|
95
|
+
| Search Docs | búsqueda **version-aware** sobre 17.000+ chunks indexados por embeddings del ecosistema Laravel |
|
|
96
|
+
|
|
97
|
+
> No afirmes "15+ tools" como hecho. La tabla oficial lista 11 herramientas.
|
|
98
|
+
|
|
99
|
+
### Mantener Boost actualizado y agregar skills del catálogo
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
php artisan boost:update --discover
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`--discover` re-detecta el stack y refresca guidelines. Para sumar una Agent Skill del catálogo a tu
|
|
106
|
+
proyecto se usa el comando de Boost contra un repo `owner/repo`:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
php artisan boost:add-skill owner/repo
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 2 — laravel/mcp: construye TU PROPIO servidor MCP
|
|
115
|
+
|
|
116
|
+
Expón tu app a clientes de IA externos. Instala el paquete y publica las rutas de IA:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
composer require laravel/mcp
|
|
120
|
+
php artisan vendor:publish --tag=ai-routes # crea routes/ai.php
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Crear el servidor
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
php artisan make:mcp-server WeatherServer
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```php
|
|
130
|
+
<?php
|
|
131
|
+
|
|
132
|
+
namespace App\Mcp\Servers;
|
|
133
|
+
|
|
134
|
+
use App\Mcp\Tools\CurrentWeatherTool;
|
|
135
|
+
use Laravel\Mcp\Server;
|
|
136
|
+
use Laravel\Mcp\Server\Attributes\Instructions;
|
|
137
|
+
use Laravel\Mcp\Server\Attributes\Name;
|
|
138
|
+
use Laravel\Mcp\Server\Attributes\Version;
|
|
139
|
+
|
|
140
|
+
#[Name('Weather Server')]
|
|
141
|
+
#[Version('1.0.0')]
|
|
142
|
+
#[Instructions('Expone clima actual y pronósticos a clientes de IA. Solo lectura.')]
|
|
143
|
+
class WeatherServer extends Server
|
|
144
|
+
{
|
|
145
|
+
// Tres primitivas de MCP: Tools (acciones), Resources (contexto), Prompts (plantillas)
|
|
146
|
+
protected array $tools = [
|
|
147
|
+
CurrentWeatherTool::class,
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
protected array $resources = [
|
|
151
|
+
// ForecastResource::class,
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
protected array $prompts = [
|
|
155
|
+
// WeatherReportPrompt::class,
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Crear una tool MCP
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
php artisan make:mcp-tool CurrentWeatherTool
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```php
|
|
167
|
+
<?php
|
|
168
|
+
|
|
169
|
+
namespace App\Mcp\Tools;
|
|
170
|
+
|
|
171
|
+
use Laravel\Mcp\Request;
|
|
172
|
+
use Laravel\Mcp\Response;
|
|
173
|
+
use Laravel\Mcp\Server\Attributes\Description;
|
|
174
|
+
use Laravel\Mcp\Server\Tool;
|
|
175
|
+
use Illuminate\JsonSchema\JsonSchema;
|
|
176
|
+
|
|
177
|
+
#[Description('Devuelve el clima actual de una ciudad.')]
|
|
178
|
+
class CurrentWeatherTool extends Tool
|
|
179
|
+
{
|
|
180
|
+
public function handle(Request $request): Response
|
|
181
|
+
{
|
|
182
|
+
$city = $request->get('city');
|
|
183
|
+
|
|
184
|
+
// Lógica real (solo lectura). NUNCA mutar estado en una tool read-only.
|
|
185
|
+
$temp = app(WeatherService::class)->currentTemp($city);
|
|
186
|
+
|
|
187
|
+
return Response::text("El clima en {$city} es {$temp}°C.");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public function schema(JsonSchema $schema): array
|
|
191
|
+
{
|
|
192
|
+
return [
|
|
193
|
+
'city' => $schema->string()
|
|
194
|
+
->description('Nombre de la ciudad')
|
|
195
|
+
->required(),
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Registrar el servidor (stdio local vs HTTP remoto)
|
|
202
|
+
|
|
203
|
+
En `routes/ai.php`:
|
|
204
|
+
|
|
205
|
+
```php
|
|
206
|
+
<?php
|
|
207
|
+
|
|
208
|
+
use App\Mcp\Servers\WeatherServer;
|
|
209
|
+
use Laravel\Mcp\Facades\Mcp;
|
|
210
|
+
|
|
211
|
+
// HTTP remoto (clientes externos, ChatGPT/Claude): expón por una ruta web
|
|
212
|
+
Mcp::web('/mcp/weather', WeatherServer::class);
|
|
213
|
+
|
|
214
|
+
// stdio local (editores, desarrollo): nombre lógico del servidor
|
|
215
|
+
Mcp::local('weather', WeatherServer::class);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- **stdio** (`Mcp::local`): para editores y uso local, sin red.
|
|
219
|
+
- **HTTP** (`Mcp::web`): para clientes remotos. **Requiere autenticación** (ver sección de seguridad).
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 3 — AI SDK (`laravel/ai`): agentes con tool-calling y structured output
|
|
224
|
+
|
|
225
|
+
El AI SDK es el sucesor first-party de Prism: **AI SDK es a Prism lo que Eloquent es a Query Builder.**
|
|
226
|
+
No uses Prism directamente para features nuevas en Laravel.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
composer require laravel/ai
|
|
230
|
+
php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
|
|
231
|
+
php artisan migrate
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Config en `config/ai.php`. Es **provider-agnostic** vía el enum `Laravel\Ai\Enums\Lab`
|
|
235
|
+
(`Lab::Anthropic`, `Lab::OpenAI`, `Lab::Gemini`, …).
|
|
236
|
+
|
|
237
|
+
### Crear un agente
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
php artisan make:agent SalesCoach
|
|
241
|
+
php artisan make:agent SalesCoach --structured # para structured output
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```php
|
|
245
|
+
<?php
|
|
246
|
+
|
|
247
|
+
namespace App\Ai\Agents;
|
|
248
|
+
|
|
249
|
+
use App\Ai\Tools\RandomNumberGenerator;
|
|
250
|
+
use Laravel\Ai\Attributes\MaxSteps;
|
|
251
|
+
use Laravel\Ai\Attributes\Model;
|
|
252
|
+
use Laravel\Ai\Attributes\Provider;
|
|
253
|
+
use Laravel\Ai\Contracts\Agent;
|
|
254
|
+
use Laravel\Ai\Contracts\HasTools;
|
|
255
|
+
use Laravel\Ai\Concerns\Promptable;
|
|
256
|
+
use Laravel\Ai\Enums\Lab;
|
|
257
|
+
|
|
258
|
+
#[Provider(Lab::Anthropic)]
|
|
259
|
+
#[Model('claude-sonnet-4-6')]
|
|
260
|
+
#[MaxSteps(10)] // acota loops descontrolados de tool-calling
|
|
261
|
+
class SalesCoach implements Agent, HasTools
|
|
262
|
+
{
|
|
263
|
+
use Promptable;
|
|
264
|
+
|
|
265
|
+
public function instructions(): string
|
|
266
|
+
{
|
|
267
|
+
return 'Eres un coach de ventas. Responde conciso y accionable.';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
public function tools(): array
|
|
271
|
+
{
|
|
272
|
+
return [
|
|
273
|
+
new RandomNumberGenerator(),
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Capacidades opt-in vía contratos: `HasTools`, `Conversational`, `HasStructuredOutput`,
|
|
280
|
+
`HasProviderOptions`. Atributos de control: `#[MaxSteps(10)]`, `#[Provider]`, `#[Model]`,
|
|
281
|
+
`#[MaxTokens]`, `#[Temperature]`.
|
|
282
|
+
|
|
283
|
+
Invocar el agente:
|
|
284
|
+
|
|
285
|
+
```php
|
|
286
|
+
$response = (new SalesCoach)->prompt('¿Cómo abro una llamada en frío?');
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Crear una tool del AI SDK
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
php artisan make:tool RandomNumberGenerator
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```php
|
|
296
|
+
<?php
|
|
297
|
+
|
|
298
|
+
namespace App\Ai\Tools;
|
|
299
|
+
|
|
300
|
+
use Laravel\Ai\Contracts\Tool;
|
|
301
|
+
use Laravel\Ai\Tools\Request;
|
|
302
|
+
use Illuminate\JsonSchema\JsonSchema;
|
|
303
|
+
|
|
304
|
+
class RandomNumberGenerator implements Tool
|
|
305
|
+
{
|
|
306
|
+
public function description(): string
|
|
307
|
+
{
|
|
308
|
+
return 'Genera un número aleatorio entre min y max.';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
public function handle(Request $request): int
|
|
312
|
+
{
|
|
313
|
+
return random_int($request->integer('min'), $request->integer('max'));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
public function schema(JsonSchema $schema): array
|
|
317
|
+
{
|
|
318
|
+
return [
|
|
319
|
+
'min' => $schema->integer()->required(),
|
|
320
|
+
'max' => $schema->integer()->required(),
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
> **Scoping de tools por agente**: evita el bloat de contexto declarando solo las tools que cada agente
|
|
327
|
+
> necesita. Guía de Taylor: mantén el total de tools **bastante por debajo de ~50**.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 4 — Embeddings y vector search con pgvector (RAG / semántica)
|
|
332
|
+
|
|
333
|
+
### Migración con pgvector
|
|
334
|
+
|
|
335
|
+
```php
|
|
336
|
+
<?php
|
|
337
|
+
|
|
338
|
+
use Illuminate\Database\Migrations\Migration;
|
|
339
|
+
use Illuminate\Database\Schema\Blueprint;
|
|
340
|
+
use Illuminate\Support\Facades\Schema;
|
|
341
|
+
|
|
342
|
+
return new class extends Migration
|
|
343
|
+
{
|
|
344
|
+
public function up(): void
|
|
345
|
+
{
|
|
346
|
+
Schema::ensureVectorExtensionExists();
|
|
347
|
+
|
|
348
|
+
Schema::create('documents', function (Blueprint $table) {
|
|
349
|
+
$table->id();
|
|
350
|
+
$table->text('body');
|
|
351
|
+
$table->vector('embedding', dimensions: 1536)->index();
|
|
352
|
+
$table->timestamps();
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Generar embeddings
|
|
359
|
+
|
|
360
|
+
```php
|
|
361
|
+
use Illuminate\Support\Str;
|
|
362
|
+
use Laravel\Ai\Embeddings;
|
|
363
|
+
|
|
364
|
+
// Helper directo
|
|
365
|
+
$vector = Str::of($document->body)->toEmbeddings();
|
|
366
|
+
|
|
367
|
+
// API con caché y batch
|
|
368
|
+
$vectors = Embeddings::for([$a->body, $b->body])
|
|
369
|
+
->cache(3600)
|
|
370
|
+
->generate();
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Providers de embeddings: OpenAI, Gemini, Cohere, Mistral, Jina, VoyageAI, Ollama, Bedrock.
|
|
374
|
+
|
|
375
|
+
### Consultar por similitud
|
|
376
|
+
|
|
377
|
+
```php
|
|
378
|
+
use App\Models\Document;
|
|
379
|
+
|
|
380
|
+
// El string se auto-embebe; minSimilarity filtra el ruido
|
|
381
|
+
$matches = Document::query()
|
|
382
|
+
->whereVectorSimilarTo('embedding', 'cómo cancelo mi suscripción', minSimilarity: 0.4)
|
|
383
|
+
->orderByVectorDistance('embedding', 'cómo cancelo mi suscripción')
|
|
384
|
+
->limit(5)
|
|
385
|
+
->get();
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Operadores disponibles: `whereVectorSimilarTo()`, `selectVectorDistance()`,
|
|
389
|
+
`whereVectorDistanceLessThan()`, `orderByVectorDistance()`.
|
|
390
|
+
|
|
391
|
+
### RAG con la tool built-in `SimilaritySearch`
|
|
392
|
+
|
|
393
|
+
Conecta el AI SDK con tu tabla vectorial para que el agente recupere contexto:
|
|
394
|
+
|
|
395
|
+
```php
|
|
396
|
+
use Laravel\Ai\Tools\SimilaritySearch;
|
|
397
|
+
use App\Models\Document;
|
|
398
|
+
|
|
399
|
+
public function tools(): array
|
|
400
|
+
{
|
|
401
|
+
return [
|
|
402
|
+
SimilaritySearch::usingModel(Document::class, 'embedding'),
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## 5 — Exponer tu app a agentes de forma segura
|
|
410
|
+
|
|
411
|
+
### Autenticación de servidores MCP
|
|
412
|
+
|
|
413
|
+
- **HTTP (`Mcp::web`)** → **Passport (OAuth 2.1)** recomendado por máxima compatibilidad con clientes de IA.
|
|
414
|
+
- **Token simple** → **Sanctum** si solo necesitas tokens de acceso, sin la complejidad de OAuth.
|
|
415
|
+
|
|
416
|
+
```php
|
|
417
|
+
// routes/ai.php — proteger un servidor MCP HTTP
|
|
418
|
+
Mcp::web('/mcp/weather', WeatherServer::class)
|
|
419
|
+
->middleware(['auth:api']); // Passport / Sanctum guard
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Elección de paquete de auth (regla 2026):
|
|
423
|
+
|
|
424
|
+
- **Sanctum** = default para la mayoría de APIs: tokens livianos + cookie SPA + mobile, soporta abilities/scopes, sin OAuth.
|
|
425
|
+
- **Passport** = servidor OAuth2/OAuth 2.1 completo: úsalo **solo** para clientes de terceros, "Log in with X", autorización delegada o M2M (client-credentials). Para MCP HTTP es la opción de máxima compatibilidad.
|
|
426
|
+
- **Fortify** = backend de session-auth headless (sin UI) para apps web first-party. No emite tokens de API.
|
|
427
|
+
|
|
428
|
+
### Scopes y tools read-only
|
|
429
|
+
|
|
430
|
+
```php
|
|
431
|
+
// Exigir un scope/ability específico antes de exponer la tool
|
|
432
|
+
public function handle(Request $request): Response
|
|
433
|
+
{
|
|
434
|
+
abort_unless($request->user()?->tokenCan('weather:read'), 403);
|
|
435
|
+
|
|
436
|
+
return Response::text(/* ... solo lectura ... */);
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
✓ Tools de lectura por defecto. Las que mutan estado requieren scope explícito y verificación de ownership.
|
|
442
|
+
✓ Nunca confíes en argumentos de la tool para autorizar: re-verifica auth y permisos en handle().
|
|
443
|
+
✓ Limita el surface: registra en $tools solo lo que el cliente externo realmente necesita.
|
|
444
|
+
✗ No expongas Tinker ni queries arbitrarias a clientes externos (eso es de Boost, que es dev-only).
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Señales de alerta — STOP y consultar
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
✗ Crear o referenciar app/Http/Kernel.php — las versiones recientes de Laravel usan estructura slim sin ese archivo; el middleware va en bootstrap/app.php (verifícalo leyendo bootstrap/app.php).
|
|
453
|
+
✗ Mezclar Laravel\Ai\Contracts\Tool (AI SDK) con Laravel\Mcp\Server\Tool (MCP) — son clases distintas.
|
|
454
|
+
✗ Usar Prism directamente para features nuevas — el AI SDK lo supersede.
|
|
455
|
+
✗ Instalar Boost sin --dev, o exponer boost:mcp a clientes externos — Boost es dev-only.
|
|
456
|
+
✗ Exponer un servidor MCP HTTP sin autenticación — siempre auth:api (Passport/Sanctum).
|
|
457
|
+
✗ Afirmar "Boost tiene 15+ MCP tools" como hecho — la tabla oficial lista 11.
|
|
458
|
+
✗ Agente sin #[MaxSteps] declarado — riesgo de loop infinito de tool-calling.
|
|
459
|
+
✗ Tabla vectorial sin Schema::ensureVectorExtensionExists() ni ->index() en la columna vector.
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Relación con otros skills
|
|
465
|
+
|
|
466
|
+
- Se apoya en `security-audit` para revisar la auth y los scopes de cualquier servidor MCP HTTP expuesto.
|
|
467
|
+
- `db-migrate` cubre las migraciones (incluida la de pgvector) si la feature toca el schema.
|
|
468
|
+
- `new-feature` lo invoca cuando una feature de Laravel requiere integración de IA, MCP o RAG.
|