Giới thiệu

Laravel MCP cung cấp một cách đơn giản, nhẹ nhàng để các AI client tương tác với ứng dụng Laravel của bạn thông qua Model Context Protocol. Nó cung cấp một interface dễ hiểu, rõ ràng để định nghĩa các server, tool, resource và prompt cho phép AI tương tác với ứng dụng của bạn.

Cài đặt

Để bắt đầu, hãy cài đặt Laravel MCP vào project của bạn bằng trình quản lý package Composer:

composer require laravel/mcp

Export routes

Sau khi cài đặt Laravel MCP, hãy chạy lệnh Artisan vendor:publish để export ra file routes/ai.php nơi bạn sẽ định nghĩa các MCP server của bạn:

php artisan vendor:publish --tag=ai-routes

Lệnh này sẽ tạo file routes/ai.php trong thư mục routes của ứng dụng, nơi bạn sẽ sử dụng để đăng ký các MCP server của bạn.

Tạo servers

Bạn có thể tạo một MCP server bằng lệnh Artisan make:mcp-server. Các server đóng vai trò là trung tâm giao tiếp để hiển thị các khả năng của MCP như tool, resource và prompt cho các AI client:

php artisan make:mcp-server WeatherServer

Lệnh này sẽ tạo ra một class server mới trong thư mục app/Mcp/Servers. Class server được tạo sẽ kế thừa class Laravel\Mcp\Server base của Laravel MCP và cung cấp các thuộc tính để cấu hình server cũng như đăng ký tool, resource và prompt:

<?php

namespace App\Mcp\Servers;

use Laravel\Mcp\Server\Attributes\Instructions;
use Laravel\Mcp\Server\Attributes\Name;
use Laravel\Mcp\Server\Attributes\Version;
use Laravel\Mcp\Server;

#[Name('Weather Server')]
#[Version('1.0.0')]
#[Instructions('This server provides weather information and forecasts.')]
class WeatherServer extends Server
{
    /**
     * The tools registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Tool>>
     */
    protected array $tools = [
        // GetCurrentWeatherTool::class,
    ];

    /**
     * The resources registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Resource>>
     */
    protected array $resources = [
        // WeatherGuidelinesResource::class,
    ];

    /**
     * The prompts registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Prompt>>
     */
    protected array $prompts = [
        // DescribeWeatherPrompt::class,
    ];
}

Đăng ký server

Sau khi bạn đã tạo một server, bạn phải đăng ký nó trong file routes/ai.php để nó có thể được truy cập. Laravel MCP cung cấp hai phương thức để đăng ký server: web cho các server có thể truy cập qua HTTP và local cho các server command line.

Web Servers

Web server là loại server phổ biến nhất và có thể truy cập được thông qua các request HTTP POST, làm cho chúng trở nên lý tưởng cho các remote AI client hoặc các tích hợp dựa trên web. Đăng ký một web server bằng phương thức web:

use App\Mcp\Servers\WeatherServer;
use Laravel\Mcp\Facades\Mcp;

Mcp::web('/mcp/weather', WeatherServer::class);

Giống như các route thông thường, bạn có thể áp dụng middleware để bảo vệ các web server của bạn:

Mcp::web('/mcp/weather', WeatherServer::class)
    ->middleware(['throttle:mcp']);

Local Servers

Local server sẽ chạy dưới dạng các lệnh Artisan, rất phù hợp để xây dựng các trợ lý AI local như Laravel Boost. Bạn có thể đăng ký một local server bằng phương thức local:

use App\Mcp\Servers\WeatherServer;
use Laravel\Mcp\Facades\Mcp;

Mcp::local('weather', WeatherServer::class);

Sau khi đã đăng ký, thông thường bạn không cần phải tự chạy lệnh Artisan mcp:start một cách thủ công. Thay vào đó, hãy cấu hình MCP client (AI agent) của bạn để khởi động server hoặc sử dụng MCP Inspector.

Tools

Tool cho phép server của bạn hiển thị các chức năng mà AI client có thể gọi. Chúng cho phép các model thực hiện các hành động, chạy code hoặc tương tác với các hệ thống bên ngoài:

<?php

namespace App\Mcp\Tools;

use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Tool;

#[Description('Fetches the current weather forecast for a specified location.')]
class CurrentWeatherTool extends Tool
{
    /**
     * Handle the tool request.
     */
    public function handle(Request $request): Response
    {
        $location = $request->get('location');

        // Get weather...

        return Response::text('The weather is...');
    }

    /**
     * Get the tool's input schema.
     *
     * @return array<string, \Illuminate\JsonSchema\Types\Type>
     */
    public function schema(JsonSchema $schema): array
    {
        return [
            'location' => $schema->string()
                ->description('The location to get the weather for.')
                ->required(),
        ];
    }
}

Tạo Tools

Để tạo một tool, hãy chạy lệnh Artisan make:mcp-tool:

php artisan make:mcp-tool CurrentWeatherTool

Sau khi tạo một tool, hãy đăng ký nó trong thuộc tính $tools của server của bạn:

<?php

namespace App\Mcp\Servers;

use App\Mcp\Tools\CurrentWeatherTool;
use Laravel\Mcp\Server;

class WeatherServer extends Server
{
    /**
     * The tools registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Tool>>
     */
    protected array $tools = [
        CurrentWeatherTool::class,
    ];
}

Tool Name, Title, and Description

Mặc định, tên và tiêu đề của tool sẽ được lấy từ tên class. Ví dụ: CurrentWeatherTool sẽ có tên là current-weather và tiêu đề là Current Weather Tool. Bạn có thể tùy chỉnh các giá trị này bằng cách sử dụng các thuộc tính NameTitle:

use Laravel\Mcp\Server\Attributes\Name;
use Laravel\Mcp\Server\Attributes\Title;

#[Name('get-optimistic-weather')]
#[Title('Get Optimistic Weather Forecast')]
class CurrentWeatherTool extends Tool
{
    // ...
}

Mô tả của tool không được tự động tạo ra. Bạn nên cung cấp một mô tả có ý nghĩa bằng cách sử dụng thuộc tính Description:

use Laravel\Mcp\Server\Attributes\Description;

#[Description('Fetches the current weather forecast for a specified location.')]
class CurrentWeatherTool extends Tool
{
    //
}

[!NOTE] Mô tả là một phần quan trọng trong metadata của tool, vì nó giúp các mô hình AI hiểu khi nào và làm thế nào để sử dụng tool một cách hiệu quả.

Tool Input Schemas

Tool có thể định nghĩa các input schema để chỉ định những tham số mà chúng chấp nhận từ các AI client. Sử dụng builder Illuminate\Contracts\JsonSchema\JsonSchema của Laravel để định nghĩa các yêu cầu input cho tool của bạn:

<?php

namespace App\Mcp\Tools;

use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Get the tool's input schema.
     *
     * @return array<string, \Illuminate\JsonSchema\Types\Type>
     */
    public function schema(JsonSchema $schema): array
    {
        return [
            'location' => $schema->string()
                ->description('The location to get the weather for.')
                ->required(),

            'units' => $schema->string()
                ->enum(['celsius', 'fahrenheit'])
                ->description('The temperature units to use.')
                ->default('celsius'),
        ];
    }
}

Tool Output Schemas

Tool có thể định nghĩa output schema để chỉ định cấu trúc các response của chúng. Điều này giúp tích hợp tốt hơn với các AI client cần kết quả tool có thể cấu trúc được. Sử dụng phương thức outputSchema để định nghĩa cấu trúc output cho tool của bạn:

<?php

namespace App\Mcp\Tools;

use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Get the tool's output schema.
     *
     * @return array<string, \Illuminate\JsonSchema\Types\Type>
     */
    public function outputSchema(JsonSchema $schema): array
    {
        return [
            'temperature' => $schema->number()
                ->description('Temperature in Celsius')
                ->required(),

            'conditions' => $schema->string()
                ->description('Weather conditions')
                ->required(),

            'humidity' => $schema->integer()
                ->description('Humidity percentage')
                ->required(),
        ];
    }
}

Validating Tool Arguments

Các định nghĩa JSON Schema cung cấp cấu trúc cơ bản cho các tham số của tool, nhưng bạn cũng có thể muốn thực thi một số quy tắc xác thực phức tạp hơn.

Laravel MCP tích hợp sẵn với các tính năng xác thực của Laravel. Bạn có thể xác thực các tham số tool trong phương thức handle của tool:

<?php

namespace App\Mcp\Tools;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Handle the tool request.
     */
    public function handle(Request $request): Response
    {
        $validated = $request->validate([
            'location' => 'required|string|max:100',
            'units' => 'in:celsius,fahrenheit',
        ]);

        // Fetch weather data using the validated arguments...
    }
}

Khi xác thực thất bại, các AI client sẽ hành động dựa trên các thông báo lỗi mà bạn cung cấp. Vì vậy, việc cung cấp các thông báo lỗi rõ ràng và có thể chạy được là rất quan trọng:

$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.',
]);

Tool Dependency Injection

Service container của Laravel được sử dụng để resolve tất cả các tool. Do đó, bạn có thể khai báo bất kỳ dependency nào mà tool của bạn có thể cần trong constructor của nó. Các dependency được khai báo sẽ tự động được resolve và tích hợp vào instance của tool:

<?php

namespace App\Mcp\Tools;

use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Create a new tool instance.
     */
    public function __construct(
        protected WeatherRepository $weather,
    ) {}

    // ...
}

Ngoài việc constructor injection, bạn cũng có thể khai báo các dependency trong phương thức handle() của tool. Service container sẽ tự động resolve và tích hợp các dependency khi phương thức được gọi:

<?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
{
    /**
     * Handle the tool request.
     */
    public function handle(Request $request, WeatherRepository $weather): Response
    {
        $location = $request->get('location');

        $forecast = $weather->getForecastFor($location);

        // ...
    }
}

Tool Annotations

Bạn có thể nâng cấp các tool của bạn bằng các annotation để cung cấp thêm metadata cho các AI client. Những annotation này giúp các mô hình AI hiểu được hành vi và khả năng của tool. Các annotation được thêm vào tool thông qua các attribute:

<?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
{
    //
}

Các annotation có sẵn là:

Annotation Type Description
#[IsReadOnly] boolean Cho biết tool không thay đổi môi trường của nó.
#[IsDestructive] boolean Cho biết tool có thể thực hiện các cập nhật gây mất dữ liệu (chỉ có ý nghĩa khi không phải read-only).
#[IsIdempotent] boolean Cho biết các lần gọi lặp lại với cùng một tham số thì không có tác dụng thêm nào khác (khi không phải read-only).
#[IsOpenWorld] boolean Cho biết tool có thể tương tác với các thực thể bên ngoài.

Giá trị của các annotation có thể được thiết lập một cách rõ ràng bằng các tham số boolean:

use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
use Laravel\Mcp\Server\Tools\Annotations\IsDestructive;
use Laravel\Mcp\Server\Tools\Annotations\IsOpenWorld;
use Laravel\Mcp\Server\Tools\Annotations\IsIdempotent;
use Laravel\Mcp\Server\Tool;

#[IsReadOnly(true)]
#[IsDestructive(false)]
#[IsOpenWorld(false)]
#[IsIdempotent(true)]
class CurrentWeatherTool extends Tool
{
    //
}

Đăng ký Conditional Tool

Bạn có thể đăng ký các tool theo điều kiện khi runtime bằng cách implement phương thức shouldRegister trong class tool của bạn. Phương thức này cho phép bạn xác định xem một tool có sẵn sàng hay không dựa trên trạng thái ứng dụng, cấu hình hoặc các tham số mà nó yêu cầu:

<?php

namespace App\Mcp\Tools;

use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Determine if the tool should be registered.
     */
    public function shouldRegister(Request $request): bool
    {
        return $request?->user()?->subscribed() ?? false;
    }
}

Khi phương thức shouldRegister của một tool trả về false, nó sẽ không xuất hiện trong danh sách các tool có sẵn và không thể được gọi bởi các AI client.

Tool Responses

Tool phải trả về một instance của Laravel\Mcp\Response. Class Response cung cấp một số phương thức tiện lợi để tạo ra các loại response khác nhau:

Đối với các response văn bản đơn giản, hãy sử dụng phương thức text:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;

/**
 * Handle the tool request.
 */
public function handle(Request $request): Response
{
    // ...

    return Response::text('Weather Summary: Sunny, 72°F');
}

Để chỉ ra rằng có lỗi xảy ra trong quá trình thực thi tool, hãy sử dụng phương thức error:

return Response::error('Unable to fetch weather data. Please try again.');

Để trả về nội dung hình ảnh hoặc âm thanh, hãy sử dụng các phương thức imageaudio:

return Response::image(file_get_contents(storage_path('weather/radar.png')), 'image/png');

return Response::audio(file_get_contents(storage_path('weather/alert.mp3')), 'audio/mp3');

Bạn cũng có thể load nội dung hình ảnh và âm thanh trực tiếp từ một disk trong filesystem của Laravel bằng phương thức fromStorage. MIME type của file sẽ được tự động nhận diện:

return Response::fromStorage('weather/radar.png');

Nếu cần, bạn có thể chỉ định một disk cụ thể hoặc ghi đè MIME type:

return Response::fromStorage('weather/radar.png', disk: 's3');

return Response::fromStorage('weather/radar.png', mimeType: 'image/webp');

Multiple Content Responses

Tool có thể trả về nhiều phần nội dung bằng cách trả về một mảng các instance Response:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;

/**
 * Handle the tool request.
 *
 * @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")
    ];
}

Structured Responses

Tool có thể trả về nội dung có cấu trúc thông qua phương thức structured. Điều này cung cấp dữ liệu có cấu trúc cho các AI client trong khi vẫn duy trì khả năng tương thích dưới dạng văn bản JSON:

return Response::structured([
    'temperature' => 22.5,
    'conditions' => 'Partly cloudy',
    'humidity' => 65,
]);

Nếu bạn cần cung cấp văn bản tùy chỉnh cùng với nội dung có cấu trúc, hãy sử dụng phương thức withStructuredContent trên response factory:

return Response::make(
    Response::text('Weather is 22.5°C and sunny')
)->withStructuredContent([
    'temperature' => 22.5,
    'conditions' => 'Sunny',
]);

Streaming Responses

Đối với các tác vụ chạy dài hoặc stream dữ liệu thời gian thực, tool có thể trả về một generator từ phương thức handle của chúng. Điều này cho phép gửi các bản cập nhật cho client trước khi có response cuối cùng:

<?php

namespace App\Mcp\Tools;

use Generator;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Tool;

class CurrentWeatherTool extends Tool
{
    /**
     * Handle the tool request.
     *
     * @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));
        }
    }
}

Khi sử dụng các web server, các response dạng stream sẽ tự động mở một stream SSE (Server-Sent Events), gửi mỗi message yield dưới dạng một event tới client.

Prompts

Prompt cho phép server của bạn chia sẻ các template prompt có thể tái sử dụng mà các AI client có thể dùng để tương tác với các mô hình ngôn ngữ. Chúng cung cấp một cách chuẩn hóa để cấu trúc các truy vấn và tương tác phổ biến.

Tạo Prompts

Để tạo một prompt, hãy chạy lệnh Artisan make:mcp-prompt:

php artisan make:mcp-prompt DescribeWeatherPrompt

Sau khi tạo một prompt, hãy đăng ký nó trong thuộc tính $prompts của server của bạn:

<?php

namespace App\Mcp\Servers;

use App\Mcp\Prompts\DescribeWeatherPrompt;
use Laravel\Mcp\Server;

class WeatherServer extends Server
{
    /**
     * The prompts registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Prompt>>
     */
    protected array $prompts = [
        DescribeWeatherPrompt::class,
    ];
}

Prompt Name, Title, and Description

Mặc định, tên và tiêu đề của prompt được lấy từ tên class. Ví dụ: DescribeWeatherPrompt sẽ có tên là describe-weather và tiêu đề là Describe Weather Prompt. Bạn có thể tùy chỉnh các giá trị này bằng cách sử dụng các thuộc tính NameTitle:

use Laravel\Mcp\Server\Attributes\Name;
use Laravel\Mcp\Server\Attributes\Title;

#[Name('weather-assistant')]
#[Title('Weather Assistant Prompt')]
class DescribeWeatherPrompt extends Prompt
{
    // ...
}

Mô tả của prompt không được tự động tạo ra. Bạn nên cung cấp một mô tả có ý nghĩa bằng cách sử dụng thuộc tính Description:

use Laravel\Mcp\Server\Attributes\Description;

#[Description('Generates a natural-language explanation of the weather for a given location.')]
class DescribeWeatherPrompt extends Prompt
{
    //
}

[!NOTE] Mô tả là một phần quan trọng của metadata của prompt, vì nó giúp các mô hình AI hiểu khi nào và làm thế nào để sử dụng prompt hiệu quả nhất.

Prompt Arguments

Prompt có thể định nghĩa các tham số cho phép AI client tùy chỉnh template prompt với các giá trị cụ thể. Sử dụng phương thức arguments để định nghĩa những tham số mà prompt của bạn chấp nhận:

<?php

namespace App\Mcp\Prompts;

use Laravel\Mcp\Server\Prompt;
use Laravel\Mcp\Server\Prompts\Argument;

class DescribeWeatherPrompt extends Prompt
{
    /**
     * Get the prompt's arguments.
     *
     * @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,
            ),
        ];
    }
}

Validating Prompt Arguments

Các tham số của prompt sẽ được tự động xác thực dựa trên định nghĩa của chúng, nhưng bạn cũng có thể muốn áp dụng các quy tắc xác thực phức tạp hơn.

Laravel MCP tích hợp sẵn các tính năng xác thực của Laravel. Bạn có thể xác thực các tham số prompt trong phương thức handle của prompt:

<?php

namespace App\Mcp\Prompts;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Prompt;

class DescribeWeatherPrompt extends Prompt
{
    /**
     * Handle the prompt request.
     */
    public function handle(Request $request): Response
    {
        $validated = $request->validate([
            'tone' => 'required|string|max:50',
        ]);

        $tone = $validated['tone'];

        // Generate the prompt response using the given tone...
    }
}

Khi xác thực thất bại, các AI client sẽ hành động dựa trên các thông báo lỗi mà bạn cung cấp. Vì vậy, việc cung cấp các thông báo lỗi rõ ràng và có thể thực thi được là rất quan trọng:

$validated = $request->validate([
    'tone' => ['required','string','max:50'],
],[
    'tone.*' => 'You must specify a tone for the weather description. Examples include "formal", "casual", or "humorous".',
]);

Prompt Dependency Injection

Service container của Laravel được sử dụng để resolve tất cả các prompt. Do đó, bạn có thể khai báo bất kỳ dependency nào mà prompt của bạn có thể cần trong constructor của nó. Các dependency được khai báo sẽ tự động được resolve và tích hợp vào instance của prompt:

<?php

namespace App\Mcp\Prompts;

use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Prompt;

class DescribeWeatherPrompt extends Prompt
{
    /**
     * Create a new prompt instance.
     */
    public function __construct(
        protected WeatherRepository $weather,
    ) {}

    //
}

Ngoài việc constructor injection, bạn cũng có thể khai báo các dependency trong phương thức handle() của prompt. Service container sẽ tự động resolve và tích hợp các dependency khi phương thức được gọi:

<?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
{
    /**
     * Handle the prompt request.
     */
    public function handle(Request $request, WeatherRepository $weather): Response
    {
        $isAvailable = $weather->isServiceAvailable();

        // ...
    }
}

Đăng ký Conditional Prompt

Bạn có thể đăng ký các prompt theo điều kiện khi runtime bằng cách implement phương thức shouldRegister trong class prompt của bạn. Phương thức này cho phép bạn xác định xem một prompt có sẵn sàng hay không dựa trên trạng thái ứng dụng, cấu hình hoặc các tham số mà nó yêu cầu:

<?php

namespace App\Mcp\Prompts;

use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Prompt;

class CurrentWeatherPrompt extends Prompt
{
    /**
     * Determine if the prompt should be registered.
     */
    public function shouldRegister(Request $request): bool
    {
        return $request?->user()?->subscribed() ?? false;
    }
}

Khi phương thức shouldRegister của một prompt trả về false, nó sẽ không xuất hiện trong danh sách các prompt có sẵn và không thể được gọi bởi các AI client.

Prompt Responses

Prompt có thể trả về một Laravel\Mcp\Response hoặc một tập hợp các instance Laravel\Mcp\Response. Những response này chứa nội dung sẽ được gửi tới AI client:

<?php

namespace App\Mcp\Prompts;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Prompt;

class DescribeWeatherPrompt extends Prompt
{
    /**
     * Handle the prompt request.
     *
     * @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),
        ];
    }
}

Bạn có thể sử dụng phương thức asAssistant() để chỉ ra một response message sẽ được coi là đến từ trợ lý AI, trong khi các message thông thường sẽ được coi là input từ người dùng.

Resources

Resource cho phép server của bạn đưa ra những dữ liệu và nội dung mà AI client có thể đọc và sử dụng làm ngữ cảnh khi tương tác với các mô hình ngôn ngữ. Chúng cung cấp một cách để chia sẻ thông tin tĩnh hoặc động như tài liệu, cấu hình hoặc bất kỳ dữ liệu nào giúp cung cấp thông tin cho các phản hồi của AI.

Tạo Resources

Để tạo một resource, hãy chạy lệnh Artisan make:mcp-resource:

php artisan make:mcp-resource WeatherGuidelinesResource

Sau khi tạo một resource, hãy đăng ký nó trong thuộc tính $resources của server của bạn:

<?php

namespace App\Mcp\Servers;

use App\Mcp\Resources\WeatherGuidelinesResource;
use Laravel\Mcp\Server;

class WeatherServer extends Server
{
    /**
     * The resources registered with this MCP server.
     *
     * @var array<int, class-string<\Laravel\Mcp\Server\Resource>>
     */
    protected array $resources = [
        WeatherGuidelinesResource::class,
    ];
}

Resource Name, Title, and Description

Mặc định, tên và tiêu đề của resource được lấy từ tên class. Ví dụ: WeatherGuidelinesResource sẽ có tên là weather-guidelines và tiêu đề là Weather Guidelines Resource. Bạn có thể tùy chỉnh các giá trị này bằng cách sử dụng các thuộc tính NameTitle:

use Laravel\Mcp\Server\Attributes\Name;
use Laravel\Mcp\Server\Attributes\Title;

#[Name('weather-api-docs')]
#[Title('Weather API Documentation')]
class WeatherGuidelinesResource extends Resource
{
    // ...
}

Mô tả resource không được tự động tạo ra. Bạn nên luôn cung cấp một mô tả có ý nghĩa bằng cách sử dụng thuộc tính Description:

use Laravel\Mcp\Server\Attributes\Description;

#[Description('Comprehensive guidelines for using the Weather API.')]
class WeatherGuidelinesResource extends Resource
{
    //
}

[!NOTE] Mô tả là một phần quan trọng trong metadata của resource, vì nó giúp các model AI hiểu khi nào và làm thế nào để sử dụng resource một cách hiệu quả.

Resource Templates

Resource template cho phép server của bạn tạo các resource động khớp với các pattern URI có biến. Thay vì định nghĩa một URI tĩnh cho mỗi resource, bạn có thể tạo một resource duy nhất để xử lý nhiều URI dựa trên một pattern cụ thể.

Creating Resource Templates

Để tạo một resource template, hãy implement interface HasUriTemplate trong class resource của bạn và định nghĩa một phương thức uriTemplate trả về một instance UriTemplate:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Attributes\MimeType;
use Laravel\Mcp\Server\Contracts\HasUriTemplate;
use Laravel\Mcp\Server\Resource;
use Laravel\Mcp\Support\UriTemplate;

#[Description('Access user files by ID')]
#[MimeType('text/plain')]
class UserFileResource extends Resource implements HasUriTemplate
{
    /**
     * Get the URI template for this resource.
     */
    public function uriTemplate(): UriTemplate
    {
        return new UriTemplate('file://users/{userId}/files/{fileId}');
    }

    /**
     * Handle the resource request.
     */
    public function handle(Request $request): Response
    {
        $userId = $request->get('userId');
        $fileId = $request->get('fileId');

        // Fetch and return the file content...

        return Response::text($content);
    }
}

Khi một resource implement interface HasUriTemplate, nó sẽ được đăng ký như một resource template thay vì là một resource tĩnh. Các AI client sau đó có thể yêu cầu resource bằng các URI khớp với pattern template, các biến từ URI sẽ được tự động trích xuất và đưa vào trong phương thức handle của resource.

URI Template Syntax

URI template sử dụng các biến được set trong dấu ngoặc nhọn để định nghĩa các biến trong URI:

new UriTemplate('file://users/{userId}');
new UriTemplate('file://users/{userId}/files/{fileId}');
new UriTemplate('https://api.example.com/{version}/{resource}/{id}');

Accessing Template Variables

Khi một URI khớp với resource template của bạn, các biến sẽ được trích xuất và tự động được thêm vào request và có thể lấy ra được bằng phương thức get:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Contracts\HasUriTemplate;
use Laravel\Mcp\Server\Resource;
use Laravel\Mcp\Support\UriTemplate;

class UserProfileResource extends Resource implements HasUriTemplate
{
    public function uriTemplate(): UriTemplate
    {
        return new UriTemplate('file://users/{userId}/profile');
    }

    public function handle(Request $request): Response
    {
        // Access the extracted variable
        $userId = $request->get('userId');

        // Access the full URI if needed
        $uri = $request->uri();

        // Fetch user profile...

        return Response::text("Profile for user {$userId}");
    }
}

Đối tượng Request cung cấp cả các biến được trích xuất và URI gốc, mang lại cho bạn đầy đủ ngữ cảnh để bạn xử lý request resource.

Resource URI and MIME Type

Mỗi resource được xác định bởi một URI duy nhất và có một MIME type giúp AI client hiểu được định dạng của resource.

Mặc định, URI của resource được tạo dựa trên tên của resource, vì vậy WeatherGuidelinesResource sẽ có URI là weather://resources/weather-guidelines. MIME type mặc định là text/plain.

Bạn có thể tùy chỉnh các giá trị này bằng cách sử dụng các thuộc tính UriMimeType:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Server\Attributes\MimeType;
use Laravel\Mcp\Server\Attributes\Uri;
use Laravel\Mcp\Server\Resource;

#[Uri('weather://resources/guidelines')]
#[MimeType('application/pdf')]
class WeatherGuidelinesResource extends Resource
{
}

URI và MIME type giúp các AI client xác định cách xử lý và diễn giải nội dung resource một cách hợp lý.

Resource Request

Không giống như các tool và prompt, resource không thể định nghĩa input schema hoặc tham số. Tuy nhiên, bạn vẫn có thể tương tác với đối tượng request trong phương thức handle của resource:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Resource;

class WeatherGuidelinesResource extends Resource
{
    /**
     * Handle the resource request.
     */
    public function handle(Request $request): Response
    {
        // ...
    }
}

Resource Dependency Injection

Service container của Laravel được sử dụng để resolve tất cả các resource. Do đó, bạn có thể khai báo bất kỳ dependency nào mà resource của bạn có thể cần trong constructor của nó. Các dependency được khai báo sẽ tự động được resolve và tích hợp vào instance của resource:

<?php

namespace App\Mcp\Resources;

use App\Repositories\WeatherRepository;
use Laravel\Mcp\Server\Resource;

class WeatherGuidelinesResource extends Resource
{
    /**
     * Create a new resource instance.
     */
    public function __construct(
        protected WeatherRepository $weather,
    ) {}

    // ...
}

Ngoài constructor injection, bạn cũng có thể khai báo các dependency trong phương thức handle() của resource. Service container sẽ tự động resolve và tích hợp các dependency khi phương thức được gọi:

<?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
{
    /**
     * Handle the resource request.
     */
    public function handle(WeatherRepository $weather): Response
    {
        $guidelines = $weather->guidelines();

        return Response::text($guidelines);
    }
}

Resource Annotations

Bạn có thể nâng cấp các resource bằng các annotation để cung cấp thêm metadata cho các AI client. Các annotation được thêm vào resource thông qua các thuộc tính:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Enums\Role;
use Laravel\Mcp\Server\Annotations\Audience;
use Laravel\Mcp\Server\Annotations\LastModified;
use Laravel\Mcp\Server\Annotations\Priority;
use Laravel\Mcp\Server\Resource;

#[Audience(Role::User)]
#[LastModified('2025-01-12T15:00:58Z')]
#[Priority(0.9)]
class UserDashboardResource extends Resource
{
    //
}

Các annotation có sẵn là:

Annotation Type Description
#[Audience] Role hoặc mảng Chỉ định đối tượng nhắm tới (Role::User, Role::Assistant, hoặc cả hai).
#[Priority] float Điểm số bằng số từ 0.0 đến 1.0 thể hiện mức độ quan trọng của resource.
#[LastModified] string Timestamp ISO 8601 cho biết lần cuối resource được cập nhật.

Đăng ký Conditional Resource

Bạn có thể đăng ký các resource theo điều kiện khi runtime bằng cách implement phương thức shouldRegister trong class resource của bạn. Phương thức này cho phép bạn xác định xem một resource có sẵn sàng hay không dựa trên trạng thái ứng dụng, cấu hình hoặc các tham số mà nó yêu cầu:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Request;
use Laravel\Mcp\Server\Resource;

class WeatherGuidelinesResource extends Resource
{
    /**
     * Determine if the resource should be registered.
     */
    public function shouldRegister(Request $request): bool
    {
        return $request?->user()?->subscribed() ?? false;
    }
}

Khi phương thức shouldRegister của một resource trả về false, nó sẽ không xuất hiện trong danh sách các resource có sẵn và không thể được gọi bởi các AI client.

Resource Responses

Resource phải trả về một instance của Laravel\Mcp\Response. Class Response cung cấp một số phương thức tiện lợi để tạo ra các loại response khác nhau:

Đối với nội dung text đơn giản, hãy sử dụng phương thức text:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;

/**
 * Handle the resource request.
 */
public function handle(Request $request): Response
{
    // ...

    return Response::text($weatherData);
}

Blob Responses

Để trả về content dạng blob, hãy sử dụng phương thức blob, cung cấp nội dung blob:

return Response::blob(file_get_contents(storage_path('weather/radar.png')));

Khi trả về nội dung blob, MIME type sẽ được xác định bởi MIME type mà bạn đã cấu hình cho resource:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Server\Attributes\MimeType;
use Laravel\Mcp\Server\Resource;

#[MimeType('image/png')]
class WeatherGuidelinesResource extends Resource
{
    //
}

Error Responses

Để chỉ ra có lỗi xảy ra trong quá trình truy xuất resource, hãy sử dụng phương thức error():

return Response::error('Unable to fetch weather data for the specified location.');

Apps

Laravel MCP hỗ trợ MCP Apps, một extension của Model Context Protocol cho phép các tool tạo ra các ứng dụng HTML bên trong các iframe được cô lập trên các host hỗ trợ. Điều này cho phép bạn xây dựng các dashboard, form, hình ảnh trực quan và các trải nghiệm phong phú khác vượt xa các phản hồi bằng văn bản thuần túy.

Một MCP app chứa hai phần hoạt động cùng nhau:

  • Một app resource trả về HTML độc lập cho ứng dụng của bạn.
  • Một tool được liên kết với app resource bằng thuộc tính #[RendersApp]. Khi tool được gọi, host sẽ lấy và hiển thị resource được liên kết.

Tạo App Resources

Bạn có thể tạo ra một app resource bằng lệnh Artisan make:mcp-app-resource:

php artisan make:mcp-app-resource WeatherDashboardApp

Lệnh này sẽ tạo ra hai file: một class PHP trong app/Mcp/Resources và một Blade view trong resources/views/mcp. Tên view sẽ được suy ra tự động từ tên class. Ví dụ, WeatherDashboardApp sẽ ánh xạ tới mcp.weather-dashboard-app:

<?php

namespace App\Mcp\Resources;

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\AppMeta;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\AppResource;

#[Description('An interactive weather dashboard.')]
#[AppMeta]
class WeatherDashboardApp extends AppResource
{
    /**
     * Handle the app resource request.
     */
    public function handle(Request $request): Response
    {
        return Response::view('mcp.weather-dashboard-app', [
            'title' => $this->title(),
        ]);
    }
}

AppResource sẽ kế thừa class Resource và tự động cấu hình URI scheme ui:// và MIME type text/html;profile=mcp-app theo yêu cầu của đặc tả MCP Apps. Giống như bất kỳ resource nào khác, bạn phải đăng ký nó trong mảng $resources của server.

File blade view được tạo ra sẽ sử dụng component <x-mcp::app>, component này sẽ render ra một file HTML hoàn chỉnh với MCP SDK client-side được tích hợp sẵn và sẵn sàng để sử dụng:

<x-mcp::app :title="$title">
    <x-slot:head>
        <script type="module">
        createMcpApp(async (app) => {
            document.getElementById('run-btn').addEventListener('click', async () => {
                const result = await app.callServerTool('get-weather-data', {});
                document.getElementById('output').textContent = result.content[0]?.text ?? '';
            });
        });
        </script>
    </x-slot:head>

    <div id="app">
        <button id="run-btn">Refresh</button>
        <p id="output"></p>
    </div>
</x-mcp::app>

Biến global createMcpApp được cung cấp bởi SDK và sẽ xử lý việc kết nối iframe với server, áp dụng chủ đề của host và cung cấp các helper như callServerTool, sendMessage, openLink và các event callback. Để biết đầy đủ API client-side, hãy tham khảo đặc tả MCP Apps.

Liên kết Apps từ Tools

Để hiển thị một app resource, hãy liên kết một tool với nó bằng thuộc tính #[RendersApp]. Khi tool được gọi, Laravel MCP sẽ thêm URI của resource vào metadata của tool để host có thể render app trong một iframe được sandbox:

<?php

namespace App\Mcp\Tools;

use App\Mcp\Resources\WeatherDashboardApp;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\RendersApp;
use Laravel\Mcp\Server\Tool;

#[RendersApp(resource: WeatherDashboardApp::class)]
class ShowWeatherDashboard extends Tool
{
    /**
     * Handle the tool request.
     */
    public function handle(Request $request): Response
    {
        return Response::text('Weather dashboard loaded.');
    }
}

Laravel MCP tự động thêm khả năng io.modelcontextprotocol/ui vào mỗi khi có bất kỳ AppResource nào được đăng ký, vì vậy bạn không cần thêm bất kỳ cấu hình server nào nữa.

App Tool Visibility

Mỗi tool #[RendersApp] có thể giới hạn những ai có thể gọi nó thông qua tham số visibility. Điều này hữu ích cho việc hiển thị các tool private, chỉ dành cho app mà UI sẽ gọi để load hoặc làm mới dữ liệu mà không hiển thị các tool đó cho các model:

use Laravel\Mcp\Server\Attributes\RendersApp;
use Laravel\Mcp\Server\Ui\Enums\Visibility;

#[RendersApp(resource: WeatherDashboardApp::class, visibility: [Visibility::App])]
class GetWeatherData extends Tool
{
    // ...
}

Enum Visibility có hai trường hợp, ModelApp, và mặc định là cả hai. Sử dụng [Visibility::App] cho các hành động backend mà UI gọi trực tiếp, hoặc [Visibility::Model] để tạo một tool không hoạt động với UI.

Cấu hình App

Thuộc tính #[AppMeta] trên app resource của bạn sẽ cấu hình Content Security Policy của iframe, các quyền của trình duyệt và bất kỳ script thư viện nào sẽ được thêm vào trong <head> của view:

use Laravel\Mcp\Server\Attributes\AppMeta;
use Laravel\Mcp\Server\Ui\Enums\Library;
use Laravel\Mcp\Server\Ui\Enums\Permission;

#[AppMeta(
    connectDomains: ['https://api.weather.com'],
    permissions: [Permission::Geolocation],
    libraries: [Library::Tailwind, Library::Alpine],
)]
class WeatherDashboardApp extends AppResource
{
    // ...
}

Enum Library sẽ chứa các script CDN được cấu hình sẵn cho một số thư viện front-end phổ biến, chẳng hạn như Library::TailwindLibrary::Alpine, và các CDN này sẽ được tự động merge vào CSP. Enum Permission sẽ chứa các quyền của trình duyệt như Camera, Microphone, GeolocationClipboardWrite.

Đối với cấu hình cần phải tính toán hoặc động, hãy ghi đè phương thức appMeta trên resource của bạn bằng các builder AppMeta, CspPermissions từ namespace Laravel\Mcp\Server\Ui.

Tạo Apps cùng Boost

Laravel MCP có chứa một tham chiếu skill Boost dành riêng cho việc xây dựng MCP Apps. Nếu bạn đã cài đặt Laravel Boost, AI coding agent của bạn có thể gọi skill mcp-development và yêu cầu nó tạo khung cho app resource, Blade view và tool được liên kết cho bạn.

Để xem tham chiếu protocol đầy đủ, bao gồm toàn bộ API client-side và chi tiết schema, hãy xem tài liệu MCP Apps chính thức.

Metadata

Laravel MCP cũng hỗ trợ field _meta như được định nghĩa trong đặc tả MCP, field này có thể được yêu cầu bởi một số MCP client hoặc một số MCP server. Metadata có thể được áp dụng cho tất cả các chức năng của MCP, bao gồm tool, resource, prompt và cả các response tương ứng.

Bạn có thể thêm metadata vào từng nội dung response bằng phương thức withMeta:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;

/**
 * Handle the tool request.
 */
public function handle(Request $request): Response
{
    return Response::text('The weather is sunny.')
        ->withMeta(['source' => 'weather-api', 'cached' => true]);
}

Đối với metadata kết quả áp dụng cho toàn bộ response, hãy bọc các response của bạn bằng Response::make và gọi withMeta trên instance response được trả về:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\ResponseFactory;

/**
 * Handle the tool request.
 */
public function handle(Request $request): ResponseFactory
{
    return Response::make(
        Response::text('The weather is sunny.')
    )->withMeta(['request_id' => '12345']);
}

Để thêm metadata vào tool, resource hoặc prompt, hãy định nghĩa một thuộc tính $meta trong class:

use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Tool;

#[Description('Fetches the current weather forecast.')]
class CurrentWeatherTool extends Tool
{
    protected ?array $meta = [
        'version' => '2.0',
        'author' => 'Weather Team',
    ];

    // ...
}

Authentication

Giống như các route thông thường, bạn có thể xác thực các web MCP server bằng middleware. Xác thực MCP server sẽ yêu cầu người dùng phải xác thực trước khi sử dụng bất kỳ khả năng nào của server.

Có hai cách để xác thực quyền truy cập vào MCP server của bạn: xác thực dựa trên token đơn giản thông qua Laravel Sanctum, hoặc bất kỳ token nào khác được truyền qua header HTTP Authorization. Hoặc, bạn có thể xác thực qua OAuth bằng cách sử dụng Laravel Passport.

OAuth 2.1

Cách mạnh mẽ nhất để bảo vệ các MCP server dựa trên nền tảng web là sử dụng OAuth thông qua Laravel Passport.

Khi xác thực MCP server của bạn qua OAuth, hãy gọi phương thức Mcp::oauthRoutes trong file routes/ai.php để đăng ký các route của OAuth2 và đăng ký các route client cần thiết. Sau đó, dùng middleware auth:api của Passport cho route Mcp::web trong file routes/ai.php của bạn:

use App\Mcp\Servers\WeatherExample;
use Laravel\Mcp\Facades\Mcp;

Mcp::oauthRoutes();

Mcp::web('/mcp/weather', WeatherExample::class)
    ->middleware('auth:api');

view#### New Passport Installation

Nếu ứng dụng của bạn chưa sử dụng Laravel Passport, hãy làm theo hướng dẫn cài đặt và triển khai Passport để thêm Passport vào ứng dụng của bạn. Bạn nên chuẩn bị sẵn model OAuthenticatable, một guard xác thực mới và các key của passport trước khi tiếp tục.

Tiếp theo, bạn nên export các view authorization của Passport mà Laravel MCP cung cấp:

php artisan vendor:publish --tag=mcp-views

Sau đó, hướng dẫn Passport sử dụng các view này bằng phương thức Passport::authorizationView. Thông thường, phương thức này nên được gọi trong phương thức boot của AppServiceProvider trong ứng dụng của bạn:

use Laravel\Passport\Passport;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Passport::authorizationView(function ($parameters) {
        return view('mcp.authorize', $parameters);
    });
}

View này sẽ được hiển thị cho người dùng trong quá trình xác thực để từ chối hoặc chấp nhận xác thực của AI agent.

Authorization screen example

[!NOTE] Trong trường hợp này, chúng ta chỉ đơn giản sử dụng OAuth như một lớp chuyển đổi sang model xác thực cở bản. Chúng ta đang bỏ qua nhiều khía cạnh khác của OAuth, chẳng hạn như scope.

Using an Existing Passport Installation

Nếu ứng dụng của bạn đã sử dụng Laravel Passport, Laravel MCP sẽ hoạt động liền mạch trong bản cài đặt Passport hiện có của bạn, nhưng các scope tùy chỉnh hiện không được hỗ trợ vì OAuth chủ yếu được sử dụng như một lớp chuyển đổi sang model xác thực cở bản.

Laravel MCP, thông qua phương thức Mcp::oauthRoutes như đã thảo luận ở trên, sẽ thêm, và sử dụng một scope mcp:use duy nhất.

Passport vs. Sanctum

OAuth2.1 là cơ chế xác thực được tài liệu hóa trong đặc tả Model Context Protocol và được hỗ trợ rộng rãi nhất trong số các MCP client. Vì lý do đó, chúng tôi khuyên bạn nên sử dụng Passport nếu có thể.

Nếu ứng dụng của bạn đã sử dụng Sanctum thì việc thêm Passport có thể phiền phức. Trong trường hợp này, chúng tôi khuyên bạn nên sử dụng Sanctum mà không cần Passport cho đến khi bạn có một yêu cầu rõ ràng và cần thiết phải sử dụng một MCP client hỗ trợ OAuth.

Sanctum

Nếu bạn muốn bảo vệ MCP server của bạn bằng Sanctum, chỉ cần thêm middleware xác thực của Sanctum vào server của bạn trong file routes/ai.php. Sau đó, đảm bảo các MCP client của bạn cung cấp một header Authorization: Bearer <token> để đảm bảo xác thực thành công:

use App\Mcp\Servers\WeatherExample;
use Laravel\Mcp\Facades\Mcp;

Mcp::web('/mcp/demo', WeatherExample::class)
    ->middleware('auth:sanctum');

Custom MCP Authentication

Nếu ứng dụng của bạn tự cấp phát các API token tùy chỉnh, bạn có thể xác thực MCP server của bạn bằng cách gán bất kỳ middleware nào bạn muốn cho các route Mcp::web của bạn. Middleware tùy chỉnh của bạn có thể kiểm tra header Authorization một cách thủ công để xác thực yêu cầu MCP gửi đến.

Authorization

Bạn có thể truy cập người dùng hiện đã xác thực thông qua phương thức $request->user(), cho phép bạn thực hiện các kiểm tra quyền trong các tool và resource MCP của bạn:

use Laravel\Mcp\Request;
use Laravel\Mcp\Response;

/**
 * Handle the tool request.
 */
public function handle(Request $request): Response
{
    if (! $request->user()->can('read-weather')) {
        return Response::error('Permission denied.');
    }

    // ...
}

Testing Servers

Bạn có thể test các MCP server của bạn bằng MCP Inspector có sẵn hoặc bằng cách viết các unit test.

MCP Inspector

MCP Inspector là một công cụ tương tác để test và debug các MCP server của bạn. Sử dụng nó để kết nối với server của bạn, kiểm tra quá trình xác thực và dùng thử các tool, resource cũng như prompt.

Bạn có thể chạy inspector cho bất kỳ server nào đã được đăng ký:

# Web server...
php artisan mcp:inspector mcp/weather

# Local server named "weather"...
php artisan mcp:inspector weather

Lệnh này sẽ khởi chạy MCP Inspector và cung cấp các cấu hình client mà bạn có thể copy vào MCP client của bạn để đảm bảo mọi thứ được cấu hình chính xác. Nếu web server của bạn được bảo vệ bởi một middleware xác thực, hãy đảm bảo nó đã chứa các header cần thiết, chẳng hạn như header Authorization, khi kết nối.

Unit Tests

Bạn có thể viết các unit test cho các MCP server, tool, resource và prompt của bạn.

Để bắt đầu, hãy tạo một bài test case mới và gọi chức năng mong muốn trên server đã đăng ký nó. Ví dụ, để test một tool trên 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.');
});
/**
 * Test a tool.
 */
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.');
}

Tương tự, bạn có thể test các prompt và resource:

$response = WeatherServer::prompt(...);
$response = WeatherServer::resource(...);

Bạn cũng có thể thêm người dùng bằng cách thêm phương thức actingAs trước khi gọi chức năng:

$response = WeatherServer::actingAs($user)->tool(...);

Sau khi nhận được phản hồi, bạn có thể sử dụng các phương thức kiểm tra khác nhau để xác minh nội dung và trạng thái của phản hồi.

Bạn có thể kiểm tra một phản hồi là thành công bằng phương thức assertOk. Điều này kiểm tra xem phản hồi có lỗi nào không:

$response->assertOk();

Bạn có thể kiểm tra một phản hồi chứa text cụ thể bằng phương thức assertSee:

$response->assertSee('The current weather in New York City is 72°F and sunny.');

Bạn có thể kiểm tra một phản hồi chứa lỗi bằng phương thức assertHasErrors:

$response->assertHasErrors();

$response->assertHasErrors([
    'Something went wrong.',
]);

Bạn có thể kiểm tra một phản hồi không chứa lỗi bằng phương thức assertHasNoErrors:

$response->assertHasNoErrors();

Bạn có thể kiểm tra một phản hồi chứa metadata cụ thể bằng các phương thức assertName(), assertTitle()assertDescription():

$response->assertName('current-weather');
$response->assertTitle('Current Weather Tool');
$response->assertDescription('Fetches the current weather forecast for a specified location.');

Bạn có thể kiểm tra các thông báo đã được gửi bằng các phương thức assertSentNotificationassertNotificationCount:

$response->assertSentNotification('processing/progress', [
    'step' => 1,
    'total' => 5,
]);

$response->assertSentNotification('processing/progress', [
    'step' => 2,
    'total' => 5,
]);

$response->assertNotificationCount(5);

Cuối cùng, nếu bạn muốn kiểm tra nội dung phản hồi raw, bạn có thể sử dụng các phương thức dd hoặc dump để output ra phản hồi cho mục đích debug:

$response->dd();
$response->dump();
AI SDK Boost
© 2023 by Logo page doc-vn