> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel AI agents now support MCP servers

> A walkthrough of the MCP client feature added to Laravel AI SDK and Laravel MCP. You can now plug MCP server tools straight into your agent's tools().

## Overview

In June 2026, the [official Laravel blog](https://laravel.com/blog/laravel-ai-agents-now-support-mcp-servers) announced that AI agents built with the Laravel AI SDK can now connect to **MCP (Model Context Protocol) servers**.

Until now, Laravel MCP provided the ability to expose your Laravel app **as an MCP server**. This release adds the opposite direction: your Laravel app can act **as an MCP client** and connect to other MCP servers.

<Info>
  For the details of how MCP itself works, see the [Laravel MCP documentation](https://laravel.com/docs/mcp). This page focuses on the client feature.
</Info>

## Why this landed in Laravel MCP rather than in the AI SDK itself

MCP is a wide-ranging protocol that covers transport negotiation, handshakes, and authentication flows. Implementing it directly inside the AI SDK would prevent reuse in scenarios where you want to talk to an MCP server without an agent — queue jobs or console commands, for example.

The Laravel team therefore split the feature in two.

```mermaid theme={null}
graph LR
    A["laravel/mcp<br>MCP client"] --> B["Connection, auth, handshake"]
    C["laravel/ai<br>Thin integration layer"] --> D["Add MCP tools directly<br>into an agent's tools()"]
    A --> C
```

* **`laravel/mcp`**: the MCP client itself, responsible for connection, negotiation, authentication, and tool invocation.
* **`laravel/ai`**: a thin integration layer that lets agents use that client from `tools()` without friction.

Each is useful on its own, and together they let agents treat MCP server tools exactly like hand-written ones.

## Connecting to an MCP server

Both STDIO servers (started as a local process) and remote servers over HTTP are supported.

```php theme={null}
use Laravel\Mcp\Client;

// Local server (STDIO)
$client = Client::local('npx', ['-y', '@modelcontextprotocol/puppeteer']);
$tools = $client->tools();

// Remote server (Streamable HTTP)
$client = Client::web('https://nightwatch.laravel.com/mcp');
$tools = $client->tools();
```

The client handles the connection, handshake, and protocol version negotiation, so your application only needs to call `tools()`.

## Authentication

### Bearer token

```php theme={null}
$tools = Client::web('https://mcp.example.com')
    ->withToken($token)
    ->tools();
```

### OAuth

Many hosted MCP servers, such as Nightwatch, require OAuth. Register a named client in a service provider.

```php theme={null}
use Laravel\Mcp\Client;
use Laravel\Mcp\Facades\Mcp;

Mcp::registerClient('nightwatch', fn () =>
    Client::web('https://nightwatch.laravel.com/mcp')->withOAuth()
);
```

Wire up the OAuth routes and callback handling.

```php theme={null}
use Laravel\Mcp\Facades\Mcp;
use Laravel\Mcp\Client\OAuth\TokenSet;

Mcp::oAuthRoutesFor('nightwatch', function (string $provider, TokenSet $token) {
    auth()->user()->update([
        'mcp_nightwatch_token' => encrypt($token->accessToken),
        'mcp_nightwatch_refresh' => encrypt($token->refreshToken),
    ]);

    return redirect('/dashboard');
}, middleware: 'auth');
```

This generates `mcp.oauth.nightwatch.connect` and the matching callback route. On the Blade side, all you need is a connect button.

```blade theme={null}
<a href="{{ route('mcp.oauth.nightwatch.connect') }}">
    Connect Nightwatch
</a>
```

Once the user logs in and grants access, your callback closure receives the token. You never have to deal with redirect URLs or PKCE details yourself.

For unattended background workloads, the client credentials grant is also available.

```php theme={null}
$token = Mcp::client('billing')->oAuthClient()->clientCredentials();
```

## Plugging it into an agent

The key point is that you can drop MCP tools into an agent's `tools()` method without changing anything else.

```php theme={null}
use Laravel\Mcp\Facades\Mcp;
use App\Tools\SendSlackMessage;

class SupportAgent extends Agent
{
    public function instructions(): string
    {
        return 'You help triage production issues.';
    }

    public function tools(): array
    {
        return [
            ...Mcp::client('nightwatch')
                ->withToken(auth()->user()->mcp_nightwatch_token)
                ->tools(),
            new SendSlackMessage,
        ];
    }
}
```

Laravel AI detects the MCP tools inside the `tools()` array and wraps them so they match the agent's tool contract. It converts MCP input schemas into Laravel's JSON schema, performs remote invocation when the model calls a tool, and normalizes the results on the way back. Errors, structured data, plain text, and streaming updates are all handled automatically, so no MCP details leak into your agent code.

You can even mix multiple transports inside a single agent.

```php theme={null}
public function tools(): array
{
    return [
        ...Mcp::client('nightwatch')->tools(),
        ...Client::local('npx', ['-y', '@modelcontextprotocol/server-puppeteer'])->tools(),
        new SendSlackMessage,
    ];
}
```

On top of that, tool classes you wrote for your own Laravel MCP server can be handed straight to an agent without a client connection at all. In other words, you can reuse the same tool both for external exposure and for your agent.

```php theme={null}
use App\Mcp\Tools\CurrentWeatherTool;

public function tools(): array
{
    return [
        new CurrentWeatherTool,
        new SendSlackMessage,
    ];
}
```

## Caching the tool list

Fetching the tool list involves a round trip to the server. For remote servers behind OAuth in particular, it's wasteful to make that call on every prompt. Because the tool list doesn't change often, it's a good caching target.

```php theme={null}
public function tools(): array
{
    $tools = Cache::remember('mcp.nightwatch.tools', now()->addHour(), fn () =>
        Mcp::client('nightwatch')->tools()
    );

    return [...$tools, new SendSlackMessage];
}
```

MCP tools are returned as plain data, so they continue to work when restored from the cache.

## Testing

Even without a running MCP server, you can test agents with Laravel AI's fake helpers. MCP tool names follow an `mcp_tools_<name>` convention, so a tool called `search` appears as `mcp_tools_search`.

```php theme={null}
use Laravel\Ai\Responses\Data\ToolCall;

SupportAgent::fake([
    new ToolCall('call_1', 'mcp_tools_search', ['query' => 'laravel']),
    'Found the issue.',
]);

$response = (new SupportAgent)->prompt('Find the latest error');

expect($response->toolCalls)->toHaveCount(1);
expect($response->toolResults->first()->result)->toContain('Found');
```

The agent's normal loop continues to run — only what the model says is faked out. The tool invocations themselves still travel through the MCP layer, so you exercise the same code path as production without any network.

## What's supported today

This initial release supports tools and prompts over both the STDIO and Streamable HTTP transports. Authentication supports bearer tokens and OAuth. Coverage is expected to grow alongside MCP itself.

## Related pages

<CardGroup cols={2}>
  <Card title="Building a custom AI SDK provider" href="/en/advanced/ai-sdk-custom-provider" icon="plug">
    How to implement a custom provider for AI services not supported out of the box.
  </Card>

  <Card title="Getting started with Laravel Nightwatch" href="/en/blog/nightwatch-introduction" icon="binoculars">
    A walkthrough of Nightwatch, the hosted monitoring service used as an example in this article.
  </Card>
</CardGroup>


## Related topics

- [June 2026 Laravel updates](/en/blog/changelog/202606.md)
- [Creating a Custom Agent for Boost](/en/advanced/boost-custom-agent.md)
- [Advanced Topics](/en/advanced/index.md)
- [Laravel and AI development](/en/ai.md)
- [Laravel MCP](/en/mcp.md)
