Skip to content

Commit 5d37baa

Browse files
committed
fix: docs
1 parent b0a523a commit 5d37baa

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed

docs-v2/content/en/mcp/mcp.md

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,311 @@ class ProductRepository extends Repository
12011201
}
12021202
```
12031203

1204+
## Actions and Getters Integration
1205+
1206+
Laravel Restify's MCP integration automatically discovers and exposes repository **Actions** and **Getters** as MCP tools, providing AI agents with access to custom business logic and data operations.
1207+
1208+
### Auto-Discovery System
1209+
1210+
The MCP server automatically discovers actions and getters attached to your repositories during the boot process:
1211+
1212+
```php
1213+
protected function discoverRepositoryTools(): void
1214+
{
1215+
collect(Restify::$repositories)
1216+
->filter(function (string $repository) {
1217+
return in_array(McpTools::class, class_uses_recursive($repository));
1218+
})
1219+
->each(function (string $repository) {
1220+
$repositoryInstance = app($repository);
1221+
1222+
// Discover and register action tools
1223+
$repositoryInstance->resolveActions(app(McpRequest::class))
1224+
->each(function (Action $action) use ($repository) {
1225+
$this->addTool(new ActionTool($repository, $action));
1226+
});
1227+
1228+
// Discover and register getter tools
1229+
$repositoryInstance->resolveGetters(app(McpRequest::class))
1230+
->each(function (Getter $getter) use ($repository) {
1231+
$this->addTool(new GetterTool($repository, $getter));
1232+
});
1233+
});
1234+
}
1235+
```
1236+
1237+
### Enabling Actions and Getters
1238+
1239+
To enable actions and getters for MCP, simply add them to your repository as usual:
1240+
1241+
```php
1242+
use Binaryk\LaravelRestify\MCP\Concerns\McpTools;
1243+
1244+
class PostRepository extends Repository
1245+
{
1246+
use McpTools;
1247+
1248+
public function actions(RestifyRequest $request): array
1249+
{
1250+
return [
1251+
PublishPostAction::make(),
1252+
ArchivePostAction::make(),
1253+
BulkUpdateStatusAction::make(),
1254+
];
1255+
}
1256+
1257+
public function getters(RestifyRequest $request): array
1258+
{
1259+
return [
1260+
PostAnalyticsGetter::make(),
1261+
PopularPostsGetter::make(),
1262+
RecentCommentsGetter::make(),
1263+
];
1264+
}
1265+
}
1266+
```
1267+
1268+
These will be automatically discovered and exposed as MCP tools:
1269+
- `posts-publish-post-action-tool`
1270+
- `posts-archive-post-action-tool`
1271+
- `posts-bulk-update-status-action-tool`
1272+
- `posts-post-analytics-getter-tool`
1273+
- `posts-popular-posts-getter-tool`
1274+
- `posts-recent-comments-getter-tool`
1275+
1276+
### Validation Rules for Actions and Getters
1277+
1278+
**IMPORTANT**: For the MCP system to properly identify and validate parameters, your actions and getters should define validation rules using the `rules()` method:
1279+
1280+
#### Action Rules Example
1281+
1282+
```php
1283+
<?php
1284+
1285+
use Binaryk\LaravelRestify\Actions\Action;
1286+
1287+
class PublishPostAction extends Action
1288+
{
1289+
public function rules(): array
1290+
{
1291+
return [
1292+
'publish_date' => ['required', 'date', 'after:now'],
1293+
'notify_subscribers' => ['boolean'],
1294+
'featured' => ['boolean'],
1295+
'category_id' => ['integer', 'exists:categories,id'],
1296+
'tags' => ['array'],
1297+
'tags.*' => ['string', 'max:50'],
1298+
];
1299+
}
1300+
1301+
public function handle(RestifyRequest $request, $models): mixed
1302+
{
1303+
foreach ($models as $post) {
1304+
$post->update([
1305+
'status' => 'published',
1306+
'published_at' => $request->input('publish_date'),
1307+
'featured' => $request->boolean('featured'),
1308+
'category_id' => $request->input('category_id'),
1309+
]);
1310+
1311+
if ($request->boolean('notify_subscribers')) {
1312+
dispatch(new NotifySubscribersJob($post));
1313+
}
1314+
}
1315+
1316+
return response()->json(['message' => 'Posts published successfully']);
1317+
}
1318+
}
1319+
```
1320+
1321+
#### Getter Rules Example
1322+
1323+
```php
1324+
<?php
1325+
1326+
use Binaryk\LaravelRestify\Getters\Getter;
1327+
1328+
class PostAnalyticsGetter extends Getter
1329+
{
1330+
public function rules(): array
1331+
{
1332+
return [
1333+
'date_from' => ['required', 'date'],
1334+
'date_to' => ['required', 'date', 'after:date_from'],
1335+
'group_by' => ['string', 'in:day,week,month'],
1336+
'include_drafts' => ['boolean'],
1337+
'categories' => ['array'],
1338+
'categories.*' => ['integer', 'exists:categories,id'],
1339+
];
1340+
}
1341+
1342+
public function handle(RestifyRequest $request): mixed
1343+
{
1344+
$query = Post::whereBetween('created_at', [
1345+
$request->input('date_from'),
1346+
$request->input('date_to')
1347+
]);
1348+
1349+
if (!$request->boolean('include_drafts')) {
1350+
$query->where('status', 'published');
1351+
}
1352+
1353+
if ($request->filled('categories')) {
1354+
$query->whereIn('category_id', $request->input('categories'));
1355+
}
1356+
1357+
return $query->selectRaw('
1358+
DATE(created_at) as date,
1359+
COUNT(*) as post_count,
1360+
AVG(view_count) as avg_views,
1361+
SUM(like_count) as total_likes
1362+
')
1363+
->groupBy('date')
1364+
->orderBy('date')
1365+
->get();
1366+
}
1367+
}
1368+
```
1369+
1370+
### Schema Generation from Rules
1371+
1372+
The MCP system uses the `rules()` method to automatically generate proper tool schemas with appropriate field types and validation:
1373+
1374+
```php
1375+
// Action with rules
1376+
public function rules(): array
1377+
{
1378+
return [
1379+
'title' => ['required', 'string', 'max:255'],
1380+
'priority' => ['integer', 'min:1', 'max:5'],
1381+
'due_date' => ['date', 'after:today'],
1382+
'notify_assignees' => ['boolean'],
1383+
'attachments' => ['array'],
1384+
];
1385+
}
1386+
1387+
// Results in MCP tool schema:
1388+
// - title: required string field
1389+
// - priority: number field (integer)
1390+
// - due_date: string field (date format)
1391+
// - notify_assignees: boolean field
1392+
// - attachments: array field
1393+
```
1394+
1395+
### Rules Method Requirements
1396+
1397+
#### For Actions
1398+
- **REQUIRED**: Actions must implement `rules()` method for proper MCP schema generation
1399+
- **Field Types**: The system maps Laravel validation rules to appropriate MCP field types
1400+
- **Validation**: Rules are enforced when AI agents call the action tools
1401+
1402+
#### For Getters
1403+
- **OPTIONAL**: Getters can implement `rules()` method for parameter validation
1404+
- **Flexibility**: If no `rules()` method exists, basic schema is generated
1405+
- **Best Practice**: Define rules for getters that accept parameters
1406+
1407+
### Rule-to-Schema Mapping
1408+
1409+
| Laravel Rule | MCP Field Type | Description |
1410+
|--------------|----------------|-------------|
1411+
| `boolean` | `boolean` | True/false values |
1412+
| `integer`, `numeric` | `number` | Numeric values |
1413+
| `array` | `array` | Array of values |
1414+
| `required` | Required field | Field marked as required |
1415+
| All others | `string` | Default string field |
1416+
1417+
### Advanced Rule Examples
1418+
1419+
#### Complex Action Rules
1420+
1421+
```php
1422+
class BulkProcessPostsAction extends Action
1423+
{
1424+
public function rules(): array
1425+
{
1426+
return [
1427+
'action_type' => ['required', 'string', 'in:publish,draft,archive,delete'],
1428+
'post_ids' => ['required', 'array', 'min:1'],
1429+
'post_ids.*' => ['integer', 'exists:posts,id'],
1430+
'scheduled_at' => ['nullable', 'date', 'after:now'],
1431+
'reason' => ['required_if:action_type,archive,delete', 'string', 'max:500'],
1432+
'send_notification' => ['boolean'],
1433+
'backup_before_delete' => ['required_if:action_type,delete', 'boolean'],
1434+
];
1435+
}
1436+
}
1437+
```
1438+
1439+
#### Parameterized Getter Rules
1440+
1441+
```php
1442+
class CustomReportGetter extends Getter
1443+
{
1444+
public function rules(): array
1445+
{
1446+
return [
1447+
'report_type' => ['required', 'string', 'in:sales,traffic,engagement'],
1448+
'date_range' => ['required', 'string', 'in:today,week,month,quarter,year,custom'],
1449+
'start_date' => ['required_if:date_range,custom', 'date'],
1450+
'end_date' => ['required_if:date_range,custom', 'date', 'after:start_date'],
1451+
'format' => ['string', 'in:json,csv,pdf'],
1452+
'include_metadata' => ['boolean'],
1453+
'filters' => ['array'],
1454+
'filters.*.field' => ['required', 'string'],
1455+
'filters.*.operator' => ['required', 'string', 'in:equals,contains,greater_than,less_than'],
1456+
'filters.*.value' => ['required'],
1457+
];
1458+
}
1459+
}
1460+
```
1461+
1462+
### Best Practices for Rules
1463+
1464+
#### 1. Always Define Rules for Actions
1465+
```php
1466+
// ✅ Good: Clear validation rules
1467+
public function rules(): array
1468+
{
1469+
return [
1470+
'email' => ['required', 'email'],
1471+
'role' => ['required', 'in:admin,user,moderator'],
1472+
'active' => ['boolean'],
1473+
];
1474+
}
1475+
1476+
// ❌ Bad: No rules defined
1477+
public function rules(): array
1478+
{
1479+
return []; // MCP can't generate proper schema
1480+
}
1481+
```
1482+
1483+
#### 2. Use Descriptive Rule Combinations
1484+
```php
1485+
public function rules(): array
1486+
{
1487+
return [
1488+
'priority' => ['required', 'integer', 'min:1', 'max:10'],
1489+
'tags' => ['array', 'max:5'],
1490+
'tags.*' => ['string', 'max:50', 'alpha_dash'],
1491+
'deadline' => ['nullable', 'date', 'after:today'],
1492+
];
1493+
}
1494+
```
1495+
1496+
#### 3. Handle Conditional Requirements
1497+
```php
1498+
public function rules(): array
1499+
{
1500+
return [
1501+
'notification_type' => ['required', 'in:email,sms,push'],
1502+
'email' => ['required_if:notification_type,email', 'email'],
1503+
'phone' => ['required_if:notification_type,sms', 'regex:/^\+?[1-9]\d{1,14}$/'],
1504+
'device_token' => ['required_if:notification_type,push', 'string'],
1505+
];
1506+
}
1507+
```
1508+
12041509
### Integration with Field Visibility Controls
12051510

12061511
MCP field methods work seamlessly with Laravel Restify's existing field visibility system:

0 commit comments

Comments
 (0)