Skip to content

Commit 2722380

Browse files
authored
Merge branch 'main' into feat/essence
2 parents 9519cd2 + 8dc64a8 commit 2722380

File tree

19 files changed

+77
-93
lines changed

19 files changed

+77
-93
lines changed

.gitattributes.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
* text=auto
2+
3+
*.blade.php diff=html
4+
*.css diff=css
5+
*.html diff=html
6+
*.md diff=markdown
7+
*.php diff=php
8+
9+
/.github export-ignore
10+
/art export-ignore
11+
/tests export-ignore
12+
.editorconfig export-ignore
13+
.gitattributes export-ignore
14+
.gitignore export-ignore
15+
CHANGELOG.md export-ignore
16+
phpstan.neon.dist export-ignore
17+
phpunit.xml.dist export-ignore
18+
UPGRADE.md export-ignore

README.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Next, register your server in `routes/ai.php`:
6767

6868
```php
6969
use App\Mcp\Servers\DemoServer;
70-
use Laravel\Mcp\Server\Facades\Mcp;
70+
use Laravel\Mcp\Facades\Mcp;
7171

7272
Mcp::local('demo', DemoServer::class);
7373
```
@@ -247,22 +247,20 @@ To register a web-based MCP server that can be accessed via HTTP POST requests,
247247

248248
```php
249249
use App\Mcp\Servers\ExampleServer;
250-
use Laravel\Mcp\Server\Facades\Mcp;
250+
use Laravel\Mcp\Facades\Mcp;
251251

252-
Mcp::web('demo', ExampleServer::class);
252+
Mcp::web('/mcp/demo', ExampleServer::class);
253253
```
254254

255255
This will make `ExampleServer` available at the `/mcp/demo` endpoint.
256256

257-
> **Security Note:** Exposing a local development server via `Mcp::web()` can make your application vulnerable to DNS rebinding attacks. If you must expose a local MCP server over HTTP, it is critical to validate the `Host` and `Origin` headers on incoming requests to ensure they are coming from a trusted source.
258-
259257
### Local Servers
260258

261259
To register a local MCP server that can be run as an Artisan command:
262260

263261
```php
264262
use App\Mcp\Servers\ExampleServer;
265-
use Laravel\Mcp\Server\Facades\Mcp;
263+
use Laravel\Mcp\Facades\Mcp;
266264

267265
Mcp::local('demo', ExampleServer::class);
268266
```
@@ -275,12 +273,12 @@ php artisan mcp:start demo
275273

276274
## Authentication
277275

278-
Web-based MCP servers can be protected using [Laravel Passport](laravel.com/docs/passport), turning your MCP server into an OAuth2 protected resource.
276+
Web-based MCP servers can be protected using [Laravel Passport](https://laravel.com/docs/passport), turning your MCP server into an OAuth2 protected resource.
279277

280278
If you already have Passport set up for your app, all you need to do is add the `Mcp::oauthRoutes()` helper to your `routes/web.php` file. This registers the required OAuth2 discovery and client registration endpoints. The method accepts an optional route prefix, which defaults to `oauth`.
281279

282280
```php
283-
use Laravel\Mcp\Server\Facades\Mcp;
281+
use Laravel\Mcp\Facades\Mcp;
284282

285283
Mcp::oauthRoutes();
286284
```
@@ -289,9 +287,9 @@ Then, apply the `auth:api` middleware to your server registration in `routes/ai.
289287

290288
```php
291289
use App\Mcp\Servers\ExampleServer;
292-
use Laravel\Mcp\Server\Facades\Mcp;
290+
use Laravel\Mcp\Facades\Mcp;
293291

294-
Mcp::web('demo', ExampleServer::class)
292+
Mcp::web('/mcp/demo', ExampleServer::class)
295293
->middleware('auth:api');
296294
```
297295

routes/ai.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
use Laravel\Mcp\Server\Facades\Mcp;
3+
use Laravel\Mcp\Facades\Mcp;
44

5-
// Mcp::web('demo', \App\Mcp\Servers\PublicServer::class); // Available at /mcp/demo
6-
// Mcp::local('demo', \App\Mcp\Servers\LocalServer::class); // Start with ./artisan mcp:start demo
5+
// Mcp::web('/mcp/demo', \App\Mcp\Servers\PublicServer::class);
6+
// Mcp::local('demo', \App\Mcp\Servers\LocalServer::class);

src/Server/Facades/Mcp.php renamed to src/Facades/Mcp.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Laravel\Mcp\Server\Facades;
5+
namespace Laravel\Mcp\Facades;
66

77
use Illuminate\Support\Facades\Facade;
88

src/Server.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,16 @@ abstract class Server
5050
],
5151
];
5252

53-
/**
54-
* The name of the MCP server.
55-
*/
56-
public string $serverName = 'Laravel MCP Server';
53+
public string $name = 'Laravel MCP Server';
5754

58-
/**
59-
* The version of the MCP server.
60-
*/
61-
public string $serverVersion = '0.0.1';
55+
public string $version = '0.0.1';
6256

6357
/**
64-
* The instructions for the AI.
58+
* Instructions describing how to use the server and its features.
59+
*
60+
* This can be used by clients to improve the LLM’s understanding of available tools, resources, etc.
61+
* It can be thought of like a "hint" to the model.
62+
* For example, this information MAY be added to the system prompt.
6563
*/
6664
public string $instructions = 'This MCP server lets AI agents interact with our Laravel application.';
6765

@@ -149,8 +147,8 @@ public function handle(string $rawMessage)
149147
$context = new ServerContext(
150148
supportedProtocolVersions: $this->supportedProtocolVersion,
151149
serverCapabilities: $this->capabilities,
152-
serverName: $this->serverName,
153-
serverVersion: $this->serverVersion,
150+
serverName: $this->name,
151+
serverVersion: $this->version,
154152
instructions: $this->instructions,
155153
maxPaginationLength: $this->maxPaginationLength,
156154
defaultPaginationLength: $this->defaultPaginationLength,

src/Server/McpServiceProvider.php

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@
1414

1515
class McpServiceProvider extends ServiceProvider
1616
{
17-
/**
18-
* Register any application services.
19-
*
20-
* @return void
21-
*/
22-
public function register()
17+
public function register(): void
2318
{
2419
$this->app->singleton('mcp', fn () => new Registrar);
2520

@@ -34,12 +29,7 @@ public function register()
3429
}
3530
}
3631

37-
/**
38-
* Bootstrap any application services.
39-
*
40-
* @return void
41-
*/
42-
public function boot()
32+
public function boot(): void
4333
{
4434
if ($this->app->runningInConsole()) {
4535
$this->offerPublishing();
@@ -48,19 +38,13 @@ public function boot()
4838
$this->loadAiRoutes();
4939
}
5040

51-
/**
52-
* Register the migrations and publishing for the package.
53-
*/
5441
protected function offerPublishing(): void
5542
{
5643
$this->publishes([
5744
__DIR__.'/../../routes/ai.php' => base_path('routes/ai.php'),
5845
], 'ai-routes');
5946
}
6047

61-
/**
62-
* Load the AI routes file if it exists.
63-
*/
6448
protected function loadAiRoutes(): void
6549
{
6650
$path = base_path('routes/ai.php');
@@ -73,6 +57,6 @@ protected function loadAiRoutes(): void
7357
return;
7458
}
7559

76-
Route::prefix('mcp')->group($path);
60+
Route::group([], $path);
7761
}
7862
}

src/Server/Methods/Initialize.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,21 @@ public function handle(JsonRpcRequest $request, ServerContext $context): JsonRpc
3131
);
3232
}
3333

34-
$protocol = $requestedVersion ?? $context->supportedProtocolVersions[0];
35-
36-
return JsonRpcResponse::create($request->id, [
37-
'protocolVersion' => $protocol,
34+
$protocolVersion = $requestedVersion ?? $context->supportedProtocolVersions[0];
35+
$initResult = [
36+
'protocolVersion' => $protocolVersion,
3837
'capabilities' => $context->serverCapabilities,
3938
'serverInfo' => [
4039
'name' => $context->serverName,
4140
'version' => $context->serverVersion,
4241
],
4342
'instructions' => $context->instructions,
44-
]);
43+
];
44+
45+
if (in_array($protocolVersion, ['2024-11-05', '2025-03-26'], true)) {
46+
unset($initResult['instructions']);
47+
}
48+
49+
return JsonRpcResponse::create($request->id, $initResult);
4550
}
4651
}

src/Server/Prompt.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ abstract public function handle(array $arguments): PromptResult;
1818

1919
public function arguments(): Arguments
2020
{
21-
return (new Arguments)->add(
21+
return new Arguments([
2222
new Argument(
2323
name: 'best_cheese',
2424
description: 'The best cheese',
2525
required: false,
2626
),
27-
);
27+
]);
2828
}
2929

3030
public function description(): string

src/Server/Registrar.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ class Registrar
2020
protected array $registeredWebServers = [];
2121

2222
/**
23-
* Register an web-based MCP server running over HTTP.
23+
* Register a web-based MCP server running over HTTP.
2424
*/
25-
public function web(string $handle, string $serverClass): Route
25+
public function web(string $route, string $serverClass): Route
2626
{
27-
$this->registeredWebServers[$handle] = $serverClass;
27+
$this->registeredWebServers[$route] = $serverClass;
2828

29-
return Router::post($handle, fn () => $this->bootServer(
29+
return Router::post($route, fn () => $this->bootServer(
3030
$serverClass,
3131
fn () => new HttpTransport(request())
32-
))->name('mcp-server.'.$handle);
32+
))->name('mcp-server.'.$route);
3333
}
3434

3535
/**
@@ -96,9 +96,6 @@ public function oauthRoutes($oauthPrefix = 'oauth')
9696
});
9797
}
9898

99-
/**
100-
* Boot the MCP server.
101-
*/
10299
private function bootServer(string $serverClass, callable $transportFactory)
103100
{
104101
$transport = $transportFactory();

src/Server/Resource.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ abstract class Resource implements Arrayable
1313
{
1414
protected string $description = '';
1515

16-
protected $content;
16+
protected string|Content $content;
1717

1818
abstract public function read(): string|Content;
1919

0 commit comments

Comments
 (0)