- Introducción
- Instalación
- Creación de Servidores
- Herramientas
- Prompts
- Recursos
- Autenticación
- Autorización
- Pruebas de Servidores
#Introducción
Laravel MCP ofrece una forma simple y elegante para que los clientes de IA interactúen con su aplicación Laravel a través del Model Context Protocol. Proporciona una interfaz expresiva y fluida para definir servidores, herramientas, recursos y prompts que permiten interacciones impulsadas por IA con su aplicación.
#Instalación
Para comenzar, instale Laravel MCP en su proyecto usando el gestor de paquetes Composer:
composer require laravel/mcp
#Publicar Rutas
Después de instalar Laravel MCP, ejecute el comando Artisan vendor:publish para publicar el archivo routes/ai.php donde definirá sus servidores MCP:
php artisan vendor:publish --tag=ai-routes
Este comando crea el archivo routes/ai.php en el directorio routes de su aplicación, que usará para registrar sus servidores MCP.
#Creación de Servidores
Puede crear un servidor MCP usando el comando Artisan make:mcp-server. Los servidores actúan como el punto central de comunicación que expone las capacidades MCP como herramientas, recursos y prompts a los clientes de IA:
php artisan make:mcp-server WeatherServer
Este comando creará una nueva clase de servidor en el directorio app/Mcp/Servers. La clase de servidor generada extiende la clase base Laravel\Mcp\Server de Laravel MCP y proporciona propiedades para registrar herramientas, recursos y prompts:
<?php
namespace App\Mcp\Servers;
use Laravel\Mcp\Server;
class WeatherServer extends Server
{
/**
* Las herramientas registradas con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Tool>>
*/
protected array $tools = [
// ExampleTool::class,
];
/**
* Los recursos registrados con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Resource>>
*/
protected array $resources = [
// ExampleResource::class,
];
/**
* Los prompts registrados con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Prompt>>
*/
protected array $prompts = [
// ExamplePrompt::class,
];
}
#Registro de Servidores
Una vez que haya creado un servidor, debe registrarlo en su archivo routes/ai.php para hacerlo accesible. Laravel MCP ofrece dos métodos para registrar servidores: web para servidores accesibles vía HTTP y local para servidores de línea de comandos.
#Servidores Web
Los servidores web son los tipos más comunes y son accesibles mediante solicitudes HTTP POST, lo que los hace ideales para clientes de IA remotos o integraciones basadas en web. Registre un servidor web usando el método web:
use App\Mcp\Servers\WeatherServer;
use Laravel\Mcp\Facades\Mcp;
Mcp::web('/mcp/weather', WeatherServer::class);
Al igual que con las rutas normales, puede aplicar middleware para proteger sus servidores web:
Mcp::web('/mcp/weather', WeatherServer::class)
->middleware(['throttle:mcp']);
#Servidores Locales
Los servidores locales se ejecutan como comandos Artisan, perfectos para desarrollo, pruebas o integraciones locales con asistentes de IA. Registre un servidor local usando el método local:
use App\Mcp\Servers\WeatherServer;
use Laravel\Mcp\Facades\Mcp;
Mcp::local('weather', WeatherServer::class);
Una vez registrado, normalmente no debería necesitar ejecutar manualmente mcp:start. En su lugar, configure su cliente MCP (agente IA) para iniciar el servidor. El comando mcp:start está diseñado para ser invocado por el cliente, que manejará el inicio y parada del servidor según sea necesario:
php artisan mcp:start weather
#Herramientas
Las herramientas permiten que su servidor exponga funcionalidades que los clientes de IA pueden invocar. Permiten que los modelos de lenguaje realicen acciones, ejecuten código o interactúen con sistemas externos.
#Creación de Herramientas
Para crear una herramienta, ejecute el comando Artisan make:mcp-tool:
php artisan make:mcp-tool CurrentWeatherTool
Después de crear una herramienta, regístrela en la propiedad $tools de su servidor:
<?php
namespace App\Mcp\Servers;
use App\Mcp\Tools\CurrentWeatherTool;
use Laravel\Mcp\Server;
class WeatherServer extends Server
{
/**
* Las herramientas registradas con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Tool>>
*/
protected array $tools = [
CurrentWeatherTool::class,
];
}
#Nombre, Título y Descripción de la Herramienta
Por defecto, el nombre y título de la herramienta se derivan del nombre de la clase. Por ejemplo, CurrentWeatherTool tendrá un nombre current-weather y un título Current Weather Tool. Puede personalizar estos valores definiendo las propiedades $name y $title en su herramienta:
class CurrentWeatherTool extends Tool
{
/**
* El nombre de la herramienta.
*/
protected string $name = 'get-optimistic-weather';
/**
* El título de la herramienta.
*/
protected string $title = 'Get Optimistic Weather Forecast';
// ...
}
Las descripciones de las herramientas no se generan automáticamente. Siempre debe proporcionar una descripción significativa definiendo la propiedad $description en su herramienta:
class CurrentWeatherTool extends Tool
{
/**
* La descripción de la herramienta.
*/
protected string $description = 'Fetches the current weather forecast for a specified location.';
//
}
La descripción es una parte crítica de los metadatos de la herramienta, ya que ayuda a los modelos de IA a entender cuándo y cómo usar la herramienta de manera efectiva.
#Esquemas de Entrada para Herramientas
Las herramientas pueden definir esquemas de entrada para especificar qué argumentos aceptan de los clientes de IA. Use el constructor Illuminate\JsonSchema\JsonSchema de Laravel para definir los requisitos de entrada de su herramienta:
<?php
namespace App\Mcp\Tools;
use Illuminate\JsonSchema\JsonSchema;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Obtiene el esquema de entrada de la herramienta.
*
* @return array<string, JsonSchema>
*/
public function schema(JsonSchema $schema): array
{
return [
'location' => $schema->string()
->description('The location to get the weather for.')
->required(),
'units' => $schema->enum(['celsius', 'fahrenheit'])
->description('The temperature units to use.')
->default('celsius'),
];
}
}
#Validación de Argumentos de Herramientas
Las definiciones de JSON Schema proporcionan una estructura básica para los argumentos de herramientas, pero también puede querer aplicar reglas de validación más complejas.
Laravel MCP se integra perfectamente con las funciones de validación de Laravel. Puede validar los argumentos entrantes dentro del método handle de su herramienta:
<?php
namespace App\Mcp\Tools;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Manejar la solicitud de la herramienta.
*/
public function handle(Request $request): Response
{
$validated = $request->validate([
'location' => 'required|string|max:100',
'units' => 'in:celsius,fahrenheit',
]);
// Obtener datos del clima usando los argumentos validados...
}
}
En caso de fallo en la validación, los clientes de IA actuarán según los mensajes de error que proporcione. Por ello, es fundamental ofrecer mensajes de error claros y accionables:
$validated = $request->validate([
'location' => ['required','string','max:100'],
'units' => 'in:celsius,fahrenheit',
],[
'location.required' => 'You must specify a location to get the weather for. For example, "New York City" or "Tokyo".',
'units.in' => 'You must specify either "celsius" or "fahrenheit" for the units.',
]);
#Inyección de Dependencias en Herramientas
El contenedor de servicios de Laravel se usa para resolver todas las herramientas. Como resultado, puede usar type-hint para cualquier dependencia que su herramienta necesite en su constructor. Las dependencias declaradas se resolverán e inyectarán automáticamente en la instancia de la herramienta:
<?php
namespace App\Mcp\Tools;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Crear una nueva instancia de herramienta.
*/
public function __construct(
protected WeatherRepository $weather,
) {}
// ...
}
Además de la inyección en el constructor, también puede usar type-hint para dependencias en el método handle() de su herramienta. El contenedor de servicios resolverá e inyectará automáticamente las dependencias cuando se llame al método:
<?php
namespace App\Mcp\Tools;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Manejar la solicitud de la herramienta.
*/
public function handle(Request $request, WeatherRepository $weather): Response
{
$location = $request->get('location');
$forecast = $weather->getForecastFor($location);
// ...
}
}
#Anotaciones de Herramientas
Puede mejorar sus herramientas con anotaciones para proporcionar metadatos adicionales a los clientes de IA. Estas anotaciones ayudan a los modelos de IA a entender el comportamiento y las capacidades de la herramienta. Las anotaciones se agregan a las herramientas mediante atributos:
<?php
namespace App\Mcp\Tools;
use Laravel\Mcp\Server\Tools\Annotations\IsIdempotent;
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
use Laravel\Mcp\Server\Tool;
#[IsIdempotent]
#[IsReadOnly]
class CurrentWeatherTool extends Tool
{
//
}
Las anotaciones disponibles incluyen:
| Anotación | Tipo | Descripción |
|---|---|---|
#[IsReadOnly] |
boolean | Indica que la herramienta no modifica su entorno. |
#[IsDestructive] |
boolean | Indica que la herramienta puede realizar actualizaciones destructivas (solo relevante si no es de solo lectura). |
#[IsIdempotent] |
boolean | Indica que llamadas repetidas con los mismos argumentos no tienen efecto adicional (cuando no es de solo lectura). |
#[IsOpenWorld] |
boolean | Indica que la herramienta puede interactuar con entidades externas. |
#Registro Condicional de Herramientas
Puede registrar herramientas condicionalmente en tiempo de ejecución implementando el método shouldRegister en su clase de herramienta. Este método le permite determinar si una herramienta debe estar disponible según el estado de la aplicación, configuración o parámetros de la solicitud:
<?php
namespace App\Mcp\Tools;
use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Determinar si la herramienta debe registrarse.
*/
public function shouldRegister(Request $request): bool
{
return $request?->user()?->subscribed() ?? false;
}
}
Cuando el método shouldRegister de una herramienta devuelve false, no aparecerá en la lista de herramientas disponibles y no podrá ser invocada por los clientes de IA.
#Respuestas de Herramientas
Las herramientas deben devolver una instancia de Laravel\Mcp\Response. La clase Response proporciona varios métodos convenientes para crear diferentes tipos de respuestas:
Para respuestas de texto simples, use el método text:
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
/**
* Manejar la solicitud de la herramienta.
*/
public function handle(Request $request): Response
{
// ...
return Response::text('Weather Summary: Sunny, 72°F');
}
Para indicar que ocurrió un error durante la ejecución de la herramienta, use el método error:
return Response::error('Unable to fetch weather data. Please try again.');
#Respuestas con Múltiples Contenidos
Las herramientas pueden devolver múltiples contenidos retornando un arreglo de instancias Response:
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
/**
* Manejar la solicitud de la herramienta.
*
* @return array<int, \Laravel\Mcp\Response>
*/
public function handle(Request $request): array
{
// ...
return [
Response::text('Weather Summary: Sunny, 72°F'),
Response::text('**Detailed Forecast**\n- Morning: 65°F\n- Afternoon: 78°F\n- Evening: 70°F')
];
}
#Respuestas en Streaming
Para operaciones de larga duración o transmisión de datos en tiempo real, las herramientas pueden devolver un generador desde su método handle. Esto permite enviar actualizaciones intermedias al cliente antes de la respuesta final:
<?php
namespace App\Mcp\Tools;
use Generator;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Tool;
class CurrentWeatherTool extends Tool
{
/**
* Manejar la solicitud de la herramienta.
*
* @return \Generator<int, \Laravel\Mcp\Response>
*/
public function handle(Request $request): Generator
{
$locations = $request->array('locations');
foreach ($locations as $index => $location) {
yield Response::notification('processing/progress', [
'current' => $index + 1,
'total' => count($locations),
'location' => $location,
]);
yield Response::text($this->forecastFor($location));
}
}
}
Al usar servidores basados en web, las respuestas en streaming abren automáticamente un flujo SSE (Server-Sent Events), enviando cada mensaje generado como un evento al cliente.
#Prompts
Prompts permiten que su servidor comparta plantillas reutilizables que los clientes de IA pueden usar para interactuar con modelos de lenguaje. Proporcionan una forma estandarizada de estructurar consultas e interacciones comunes.
#Creación de Prompts
Para crear un prompt, ejecute el comando Artisan make:mcp-prompt:
php artisan make:mcp-prompt DescribeWeatherPrompt
Después de crear un prompt, regístrelo en la propiedad $prompts de su servidor:
<?php
namespace App\Mcp\Servers;
use App\Mcp\Prompts\DescribeWeatherPrompt;
use Laravel\Mcp\Server;
class WeatherServer extends Server
{
/**
* Los prompts registrados con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Prompt>>
*/
protected array $prompts = [
DescribeWeatherPrompt::class,
];
}
#Nombre, Título y Descripción del Prompt
Por defecto, el nombre y título del prompt se derivan del nombre de la clase. Por ejemplo, DescribeWeatherPrompt tendrá un nombre describe-weather y un título Describe Weather Prompt. Puede personalizar estos valores definiendo las propiedades $name y $title en su prompt:
class DescribeWeatherPrompt extends Prompt
{
/**
* El nombre del prompt.
*/
protected string $name = 'weather-assistant';
/**
* El título del prompt.
*/
protected string $title = 'Weather Assistant Prompt';
// ...
}
Las descripciones de los prompts no se generan automáticamente. Siempre debe proporcionar una descripción significativa definiendo la propiedad $description en sus prompts:
class DescribeWeatherPrompt extends Prompt
{
/**
* La descripción del prompt.
*/
protected string $description = 'Generates a natural-language explanation of the weather for a given location.';
//
}
La descripción es una parte crítica de los metadatos del prompt, ya que ayuda a los modelos de IA a entender cuándo y cómo aprovechar mejor el prompt.
#Argumentos de Prompts
Los prompts pueden definir argumentos que permiten a los clientes de IA personalizar la plantilla del prompt con valores específicos. Use el método arguments para definir qué argumentos acepta su prompt:
<?php
namespace App\Mcp\Prompts;
use Laravel\Mcp\Server\Prompt;
use Laravel\Mcp\Server\Prompts\Argument;
class DescribeWeatherPrompt extends Prompt
{
/**
* Obtener los argumentos del prompt.
*
* @return array<int, \Laravel\Mcp\Server\Prompts\Argument>
*/
public function arguments(): array
{
return [
new Argument(
name: 'tone',
description: 'The tone to use in the weather description (e.g., formal, casual, humorous).',
required: true,
),
];
}
}
#Validación de Argumentos de Prompts
Los argumentos de los prompts se validan automáticamente según su definición, pero también puede querer aplicar reglas de validación más complejas.
Laravel MCP se integra perfectamente con las funciones de validación de Laravel. Puede validar los argumentos entrantes dentro del método handle de su prompt:
<?php
namespace App\Mcp\Prompts;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Prompt;
class DescribeWeatherPrompt extends Prompt
{
/**
* Manejar la solicitud del prompt.
*/
public function handle(Request $request): Response
{
$validated = $request->validate([
'tone' => 'required|string|max:50',
]);
$tone = $validated['tone'];
// Generar la respuesta del prompt usando el tono dado...
}
}
En caso de fallo en la validación, los clientes de IA actuarán según los mensajes de error que proporcione. Por ello, es fundamental ofrecer mensajes de error claros y accionables:
$validated = $request->validate([
'tone' => ['required','string','max:50'],
],[
'tone.*' => 'You must specify a tone for the weather description. Examples include "formal", "casual", or "humorous".',
]);
#Inyección de Dependencias en Prompts
El contenedor de servicios de Laravel se usa para resolver todos los prompts. Como resultado, puede usar type-hint para cualquier dependencia que su prompt necesite en su constructor. Las dependencias declaradas se resolverán e inyectarán automáticamente en la instancia del prompt:
<?php
namespace App\Mcp\Prompts;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Prompt;
class DescribeWeatherPrompt extends Prompt
{
/**
* Crear una nueva instancia de prompt.
*/
public function __construct(
protected WeatherRepository $weather,
) {}
//
}
Además de la inyección en el constructor, también puede usar type-hint para dependencias en el método handle() de su prompt. El contenedor de servicios resolverá e inyectará automáticamente las dependencias cuando se llame al método:
<?php
namespace App\Mcp\Prompts;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Prompt;
class DescribeWeatherPrompt extends Prompt
{
/**
* Manejar la solicitud del prompt.
*/
public function handle(Request $request, WeatherRepository $weather): Response
{
$isAvailable = $weather->isServiceAvailable();
// ...
}
}
#Registro Condicional de Prompts
Puede registrar prompts condicionalmente en tiempo de ejecución implementando el método shouldRegister en su clase de prompt. Este método le permite determinar si un prompt debe estar disponible según el estado de la aplicación, configuración o parámetros de la solicitud:
<?php
namespace App\Mcp\Prompts;
use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Prompt;
class CurrentWeatherPrompt extends Prompt
{
/**
* Determinar si el prompt debe registrarse.
*/
public function shouldRegister(Request $request): bool
{
return $request?->user()?->subscribed() ?? false;
}
}
Cuando el método shouldRegister de un prompt devuelve false, no aparecerá en la lista de prompts disponibles y no podrá ser invocado por los clientes de IA.
#Respuestas de Prompts
Los prompts pueden devolver una única instancia de Laravel\Mcp\Response o un iterable de instancias Laravel\Mcp\Response. Estas respuestas encapsulan el contenido que se enviará al cliente de IA:
<?php
namespace App\Mcp\Prompts;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Prompt;
class DescribeWeatherPrompt extends Prompt
{
/**
* Manejar la solicitud del prompt.
*
* @return array<int, \Laravel\Mcp\Response>
*/
public function handle(Request $request): array
{
$tone = $request->string('tone');
$systemMessage = "You are a helpful weather assistant. Please provide a weather description in a {$tone} tone.";
$userMessage = "What is the current weather like in New York City?";
return [
Response::text($systemMessage)->asAssistant(),
Response::text($userMessage),
];
}
}
Puede usar el método asAssistant() para indicar que un mensaje de respuesta debe tratarse como proveniente del asistente IA, mientras que los mensajes regulares se tratan como entrada del usuario.
#Recursos
Recursos permiten que su servidor exponga datos y contenido que los clientes de IA pueden leer y usar como contexto al interactuar con modelos de lenguaje. Proporcionan una forma de compartir información estática o dinámica como documentación, configuración o cualquier dato que ayude a informar las respuestas de IA.
#Creación de Recursos
Para crear un recurso, ejecute el comando Artisan make:mcp-resource:
php artisan make:mcp-resource WeatherGuidelinesResource
Después de crear un recurso, regístrelo en la propiedad $resources de su servidor:
<?php
namespace App\Mcp\Servers;
use App\Mcp\Resources\WeatherGuidelinesResource;
use Laravel\Mcp\Server;
class WeatherServer extends Server
{
/**
* Los recursos registrados con este servidor MCP.
*
* @var array<int, class-string<\Laravel\Mcp\Server\Resource>>
*/
protected array $resources = [
WeatherGuidelinesResource::class,
];
}
#Nombre, Título y Descripción del Recurso
Por defecto, el nombre y título del recurso se derivan del nombre de la clase. Por ejemplo, WeatherGuidelinesResource tendrá un nombre weather-guidelines y un título Weather Guidelines Resource. Puede personalizar estos valores definiendo las propiedades $name y $title en su recurso:
class WeatherGuidelinesResource extends Resource
{
/**
* El nombre del recurso.
*/
protected string $name = 'weather-api-docs';
/**
* El título del recurso.
*/
protected string $title = 'Weather API Documentation';
// ...
}
Las descripciones de los recursos no se generan automáticamente. Siempre debe proporcionar una descripción significativa definiendo la propiedad $description en su recurso:
class WeatherGuidelinesResource extends Resource
{
/**
* La descripción del recurso.
*/
protected string $description = 'Comprehensive guidelines for using the Weather API.';
//
}
La descripción es una parte crítica de los metadatos del recurso, ya que ayuda a los modelos de IA a entender cuándo y cómo usar el recurso de manera efectiva.
#URI y Tipo MIME del Recurso
Cada recurso se identifica por un URI único y tiene un tipo MIME asociado que ayuda a los clientes de IA a entender el formato del recurso.
Por defecto, el URI del recurso se genera basado en el nombre del recurso, por lo que WeatherGuidelinesResource tendrá un URI weather://resources/weather-guidelines. El tipo MIME por defecto es text/plain.
Puede personalizar estos valores definiendo las propiedades $uri y $mimeType en su recurso:
<?php
namespace App\Mcp\Resources;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* El URI del recurso.
*/
protected string $uri = 'weather://resources/guidelines';
/**
* El tipo MIME del recurso.
*/
protected string $mimeType = 'application/pdf';
}
El URI y el tipo MIME ayudan a los clientes de IA a determinar cómo procesar e interpretar adecuadamente el contenido del recurso.
#Solicitud de Recursos
A diferencia de herramientas y prompts, los recursos no pueden definir esquemas de entrada o argumentos. Sin embargo, aún puede interactuar con el objeto de solicitud dentro del método handle de su recurso:
<?php
namespace App\Mcp\Resources;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* Manejar la solicitud del recurso.
*/
public function handle(Request $request): Response
{
// ...
}
}
#Inyección de Dependencias en Recursos
El contenedor de servicios de Laravel se usa para resolver todos los recursos. Como resultado, puede usar type-hint para cualquier dependencia que su recurso necesite en su constructor. Las dependencias declaradas se resolverán e inyectarán automáticamente en la instancia del recurso:
<?php
namespace App\Mcp\Resources;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* Crear una nueva instancia de recurso.
*/
public function __construct(
protected WeatherRepository $weather,
) {}
// ...
}
Además de la inyección en el constructor, también puede usar type-hint para dependencias en el método handle() de su recurso. El contenedor de servicios resolverá e inyectará automáticamente las dependencias cuando se llame al método:
<?php
namespace App\Mcp\Resources;
use App\Repositories\WeatherRepository;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* Manejar la solicitud del recurso.
*/
public function handle(WeatherRepository $weather): Response
{
$guidelines = $weather->guidelines();
return Response::text($guidelines);
}
}
#Registro Condicional de Recursos
Puede registrar recursos condicionalmente en tiempo de ejecución implementando el método shouldRegister en su clase de recurso. Este método le permite determinar si un recurso debe estar disponible según el estado de la aplicación, configuración o parámetros de la solicitud:
<?php
namespace App\Mcp\Resources;
use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* Determinar si el recurso debe registrarse.
*/
public function shouldRegister(Request $request): bool
{
return $request?->user()?->subscribed() ?? false;
}
}
Cuando el método shouldRegister de un recurso devuelve false, no aparecerá en la lista de recursos disponibles y no podrá ser accedido por los clientes de IA.
#Respuestas de Recursos
Los recursos deben devolver una instancia de Laravel\Mcp\Response. La clase Response proporciona varios métodos convenientes para crear diferentes tipos de respuestas:
Para contenido de texto simple, use el método text:
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
/**
* Manejar la solicitud del recurso.
*/
public function handle(Request $request): Response
{
// ...
return Response::text($weatherData);
}
#Respuestas Blob
Para devolver contenido blob, use el método blob, proporcionando el contenido blob:
return Response::blob(file_get_contents(storage_path('weather/radar.png')));
Al devolver contenido blob, el tipo MIME será determinado por el valor de la propiedad $mimeType en la clase del recurso:
<?php
namespace App\Mcp\Resources;
use Laravel\Mcp\Server\Resource;
class WeatherGuidelinesResource extends Resource
{
/**
* El tipo MIME del recurso.
*/
protected string $mimeType = 'image/png';
//
}
#Respuestas de Error
Para indicar que ocurrió un error durante la obtención del recurso, use el método error():
return Response::error('Unable to fetch weather data for the specified location.');
#Autenticación
Puede autenticar servidores web MCP con middleware igual que lo haría para rutas. Esto requerirá que un usuario se autentique antes de usar cualquier capacidad del servidor.
Hay dos formas de autenticar el acceso a su servidor MCP: autenticación simple basada en token mediante Laravel Sanctum, o cualquier otro token API arbitrario que se pase mediante el encabezado HTTP Authorization. O bien, puede autenticar mediante OAuth usando Laravel Passport.
#OAuth 2.1
La forma más robusta de proteger sus servidores MCP basados en web es con OAuth a través de Laravel Passport.
Al autenticar su servidor MCP vía OAuth, invocará el método Mcp::oauthRoutes en su archivo routes/ai.php para registrar las rutas necesarias para el descubrimiento OAuth2 y el registro de clientes. Luego, aplique el middleware auth:api de Passport a su ruta Mcp::web en su archivo routes/ai.php:
use App\Mcp\Servers\WeatherExample;
use Laravel\Mcp\Facades\Mcp;
Mcp::oauthRoutes();
Mcp::web('/mcp/weather', WeatherExample::class)
->middleware('auth:api');
#Nueva Instalación de Passport
Si su aplicación aún no usa Laravel Passport, comience siguiendo los pasos de instalación y despliegue de Passport. Debe tener un modelo OAuthenticatable, un nuevo guard de autenticación y las claves de Passport antes de continuar.
Luego, debe publicar la vista de autorización proporcionada por Laravel MCP para Passport:
php artisan vendor:publish --tag=mcp-views
Después, indique a Passport que use esta vista mediante el método Passport::authorizationView. Normalmente, este método se invoca en el método boot del AppServiceProvider de su aplicación:
use Laravel\Passport\Passport;
/**
* Inicializar servicios de la aplicación.
*/
public function boot(): void
{
Passport::authorizationView(function ($parameters) {
return view('mcp.authorize', $parameters);
});
}
Esta vista se mostrará al usuario final durante la autenticación para rechazar o aprobar el intento de autenticación del agente IA.
En este escenario, simplemente usamos OAuth como una capa de traducción al modelo autenticable subyacente. Ignoramos muchos aspectos de OAuth, como los scopes.
#Uso de una Instalación Existente de Passport
Si su aplicación ya usa Laravel Passport, Laravel MCP debería funcionar sin problemas dentro de su instalación existente, pero los scopes personalizados no están soportados actualmente ya que OAuth se usa principalmente como capa de traducción al modelo autenticable subyacente.
Laravel MCP, mediante el método Mcp::oauthRoutes() mencionado arriba, añade, anuncia y usa un único scope mcp:use.
#Passport vs. Sanctum
OAuth2.1 es el mecanismo de autenticación documentado en la especificación del Model Context Protocol, y es el más ampliamente soportado entre los clientes MCP. Por esa razón, recomendamos usar Passport cuando sea posible.
Si su aplicación ya usa Sanctum, agregar Passport puede ser complicado. En este caso, recomendamos usar Sanctum sin Passport hasta que tenga un requisito claro y necesario para usar un cliente MCP que solo soporte OAuth.
#Sanctum
Si desea proteger su servidor MCP usando Sanctum, simplemente agregue el middleware de autenticación de Sanctum a su servidor en su archivo routes/ai.php. Luego, asegúrese de que sus clientes MCP proporcionen un encabezado Authorization: Bearer <token> para garantizar una autenticación exitosa:
use App\Mcp\Servers\WeatherExample;
use Laravel\Mcp\Facades\Mcp;
Mcp::web('/mcp/demo', WeatherExample::class)
->middleware('auth:sanctum');
#Autenticación MCP Personalizada
Si su aplicación emite sus propios tokens API personalizados, puede autenticar su servidor MCP asignando cualquier middleware que desee a sus rutas Mcp::web. Su middleware personalizado puede inspeccionar manualmente el encabezado Authorization para autenticar la solicitud MCP entrante.
#Autorización
Puede acceder al usuario actualmente autenticado mediante el método $request->user(), lo que le permite realizar chequeos de autorización dentro de sus herramientas y recursos MCP:
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
/**
* Manejar la solicitud de la herramienta.
*/
public function handle(Request $request): Response
{
if (! $request->user()->can('read-weather')) {
return Response::error('Permission denied.');
}
// ...
}
#Pruebas de Servidores
Puede probar sus servidores MCP usando el Inspector MCP incorporado o escribiendo pruebas unitarias.
#Inspector MCP
El Inspector MCP es una herramienta interactiva para probar y depurar sus servidores MCP. Úselo para conectarse a su servidor, verificar la autenticación y probar herramientas, recursos y prompts.
Puede ejecutar el inspector para cualquier servidor registrado (por ejemplo, un servidor local llamado "weather"):
php artisan mcp:inspector weather
Este comando lanza el Inspector MCP y proporciona la configuración del cliente que puede copiar en su cliente MCP para asegurar que todo esté configurado correctamente. Si su servidor web está protegido por un middleware de autenticación, asegúrese de incluir los encabezados requeridos, como un token bearer Authorization, al conectarse.
#Pruebas Unitarias
Puede escribir pruebas unitarias para sus servidores MCP, herramientas, recursos y prompts.
Para comenzar, cree un nuevo caso de prueba e invoque el primitivo deseado en el servidor que lo registra. Por ejemplo, para probar una herramienta en el WeatherServer:
test('tool', function () {
$response = WeatherServer::tool(CurrentWeatherTool::class, [
'location' => 'New York City',
'units' => 'fahrenheit',
]);
$response
->assertOk()
->assertSee('The current weather in New York City is 72°F and sunny.');
});
/**
* Probar una herramienta.
*/
public function test_tool(): void
{
$response = WeatherServer::tool(CurrentWeatherTool::class, [
'location' => 'New York City',
'units' => 'fahrenheit',
]);
$response
->assertOk()
->assertSee('The current weather in New York City is 72°F and sunny.');
}
De manera similar, puede probar prompts y recursos:
$response = WeatherServer::prompt(...);
$response = WeatherServer::resource(...);
También puede actuar como un usuario autenticado encadenando el método actingAs antes de invocar el primitivo:
$response = WeatherServer::actingAs($user)->tool(...);
Una vez que reciba la respuesta, puede usar varios métodos de aserción para verificar el contenido y el estado de la respuesta.
Puede afirmar que una respuesta fue exitosa usando el método assertOk. Esto verifica que la respuesta no tenga errores:
$response->assertOk();
Puede afirmar que una respuesta contiene texto específico usando el método assertSee:
$response->assertSee('The current weather in New York City is 72°F and sunny.');
Puede afirmar que una respuesta contiene un error usando el método assertHasErrors:
$response->assertHasErrors();
$response->assertHasErrors([
'Something went wrong.',
]);
Puede afirmar que una respuesta no contiene errores usando el método assertHasNoErrors:
$response->assertHasNoErrors();
Puede afirmar que una respuesta contiene metadatos específicos usando los métodos assertName(), assertTitle() y assertDescription():
$response->assertName('current-weather');
$response->assertTitle('Current Weather Tool');
$response->assertDescription('Fetches the current weather forecast for a specified location.');
Puede afirmar que se enviaron notificaciones usando los métodos assertSentNotification y assertNotificationCount:
$response->assertSentNotification('processing/progress', [
'step' => 1,
'total' => 5,
]);
$response->assertSentNotification('processing/progress', [
'step' => 2,
'total' => 5,
]);
$response->assertNotificationCount(5);
Finalmente, si desea inspeccionar el contenido bruto de la respuesta, puede usar los métodos dd o dump para mostrar la respuesta con fines de depuración:
$response->dd();
$response->dump();