From 636220143b690be356a56eb9563af4e04a5c8136 Mon Sep 17 00:00:00 2001 From: Derek Bourgeois Date: Thu, 26 Mar 2026 19:13:38 -0400 Subject: [PATCH 1/2] feat: add laravel mcp foundation --- README.md | 16 +++ app/Mcp/Servers/KatraServer.php | 27 +++++ app/Mcp/Tools/DescribeWorkspace.php | 48 +++++++++ composer.json | 1 + composer.lock | 148 ++++++++++++++-------------- config/mcp.php | 24 +++++ routes/ai.php | 6 ++ tests/Feature/McpSmokeTest.php | 18 ++++ 8 files changed, 214 insertions(+), 74 deletions(-) create mode 100644 app/Mcp/Servers/KatraServer.php create mode 100644 app/Mcp/Tools/DescribeWorkspace.php create mode 100644 config/mcp.php create mode 100644 routes/ai.php create mode 100644 tests/Feature/McpSmokeTest.php diff --git a/README.md b/README.md index 8d65d30..c57a5ee 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,22 @@ The Laravel AI SDK is installed and its conversation storage migrations are part The current AI foundation test uses agent fakes, so the repo test suite does not require live provider credentials just to verify the integration. +### Laravel MCP Foundation + +Katra now includes Laravel MCP as an explicit application dependency. + +- The application publishes `config/mcp.php` and `routes/ai.php` so MCP setup lives in the same Laravel configuration surface as the rest of the app. +- Katra registers a local MCP handle named `katra` that points at `App\Mcp\Servers\KatraServer`. +- The current example tool, `App\Mcp\Tools\DescribeWorkspace`, is intentionally small and read-only. It exists as a smoke-tested interoperability example, not as a parallel product surface. +- MCP matters for interoperability, tool exposure, and external integrations, but it should not become the center of Katra's architecture. +- Start the local MCP server with: + +```bash +php artisan mcp:start katra +``` + +- The current smoke coverage lives in `tests/Feature/McpSmokeTest.php`. + ### Surreal-Backed Migrations Katra now includes a first Laravel-compatible Surreal schema driver for migration work. diff --git a/app/Mcp/Servers/KatraServer.php b/app/Mcp/Servers/KatraServer.php new file mode 100644 index 0000000..f491a46 --- /dev/null +++ b/app/Mcp/Servers/KatraServer.php @@ -0,0 +1,27 @@ + + */ + public function schema(JsonSchema $schema): array + { + return [ + // + ]; + } +} diff --git a/composer.json b/composer.json index 53360c2..c5e0879 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "laravel/ai": "^0.3.2", "laravel/fortify": "^1.36", "laravel/framework": "^13.0", + "laravel/mcp": "^0.6.3", "laravel/pennant": "^1.0", "laravel/tinker": "^3.0", "nativephp/desktop": "dev-l13-compatibility", diff --git a/composer.lock b/composer.lock index ce585dc..397e9d7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "88cc1f927b6c0e8175532a2a535b0aea", + "content-hash": "c27a0d705703a70b225ef6e4da8c55e8", "packages": [ { "name": "bacon/bacon-qr-code", @@ -1589,6 +1589,79 @@ }, "time": "2026-03-18T17:10:25+00:00" }, + { + "name": "laravel/mcp", + "version": "v0.6.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/mcp.git", + "reference": "f822c5eb5beed19adb2e5bfe2f46f8c977ecea42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/mcp/zipball/f822c5eb5beed19adb2e5bfe2f46f8c977ecea42", + "reference": "f822c5eb5beed19adb2e5bfe2f46f8c977ecea42", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/console": "^11.45.3|^12.41.1|^13.0", + "illuminate/container": "^11.45.3|^12.41.1|^13.0", + "illuminate/contracts": "^11.45.3|^12.41.1|^13.0", + "illuminate/http": "^11.45.3|^12.41.1|^13.0", + "illuminate/json-schema": "^12.41.1|^13.0", + "illuminate/routing": "^11.45.3|^12.41.1|^13.0", + "illuminate/support": "^11.45.3|^12.41.1|^13.0", + "illuminate/validation": "^11.45.3|^12.41.1|^13.0", + "php": "^8.2" + }, + "require-dev": { + "laravel/pint": "^1.20", + "orchestra/testbench": "^9.15|^10.8|^11.0", + "pestphp/pest": "^3.8.5|^4.3.2", + "phpstan/phpstan": "^2.1.27", + "rector/rector": "^2.2.4" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" + }, + "providers": [ + "Laravel\\Mcp\\Server\\McpServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Mcp\\": "src/", + "Laravel\\Mcp\\Server\\": "src/Server/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Rapidly build MCP servers for your Laravel applications.", + "homepage": "https://github.com/laravel/mcp", + "keywords": [ + "laravel", + "mcp" + ], + "support": { + "issues": "https://github.com/laravel/mcp/issues", + "source": "https://github.com/laravel/mcp" + }, + "time": "2026-03-19T12:37:13+00:00" + }, { "name": "laravel/pennant", "version": "v1.22.0", @@ -7386,79 +7459,6 @@ }, "time": "2026-03-17T16:42:14+00:00" }, - { - "name": "laravel/mcp", - "version": "v0.6.3", - "source": { - "type": "git", - "url": "https://github.com/laravel/mcp.git", - "reference": "8a2c97ec1184e16029080e3f6172a7ca73de4df9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/mcp/zipball/8a2c97ec1184e16029080e3f6172a7ca73de4df9", - "reference": "8a2c97ec1184e16029080e3f6172a7ca73de4df9", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-mbstring": "*", - "illuminate/console": "^11.45.3|^12.41.1|^13.0", - "illuminate/container": "^11.45.3|^12.41.1|^13.0", - "illuminate/contracts": "^11.45.3|^12.41.1|^13.0", - "illuminate/http": "^11.45.3|^12.41.1|^13.0", - "illuminate/json-schema": "^12.41.1|^13.0", - "illuminate/routing": "^11.45.3|^12.41.1|^13.0", - "illuminate/support": "^11.45.3|^12.41.1|^13.0", - "illuminate/validation": "^11.45.3|^12.41.1|^13.0", - "php": "^8.2" - }, - "require-dev": { - "laravel/pint": "^1.20", - "orchestra/testbench": "^9.15|^10.8|^11.0", - "pestphp/pest": "^3.8.5|^4.3.2", - "phpstan/phpstan": "^2.1.27", - "rector/rector": "^2.2.4" - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" - }, - "providers": [ - "Laravel\\Mcp\\Server\\McpServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Mcp\\": "src/", - "Laravel\\Mcp\\Server\\": "src/Server/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Rapidly build MCP servers for your Laravel applications.", - "homepage": "https://github.com/laravel/mcp", - "keywords": [ - "laravel", - "mcp" - ], - "support": { - "issues": "https://github.com/laravel/mcp/issues", - "source": "https://github.com/laravel/mcp" - }, - "time": "2026-03-12T12:46:43+00:00" - }, { "name": "laravel/pail", "version": "v1.2.6", diff --git a/config/mcp.php b/config/mcp.php new file mode 100644 index 0000000..aab2041 --- /dev/null +++ b/config/mcp.php @@ -0,0 +1,24 @@ + [ + '*', + // 'https://example.com', + // 'http://localhost', + ], + +]; diff --git a/routes/ai.php b/routes/ai.php new file mode 100644 index 0000000..b33e05f --- /dev/null +++ b/routes/ai.php @@ -0,0 +1,6 @@ +assertOk() + ->assertName('describe-workspace') + ->assertDescription('Summarize the current Katra workspace configuration and MCP role.') + ->assertSee([ + config('app.name'), + config('app.url'), + 'interoperability layer', + 'not the center of the product architecture', + 'desktop-local, server, container, and kubernetes-oriented', + ]); +}); From 0e470dd62cffe2e839b1b419fd73707b5b030cc8 Mon Sep 17 00:00:00 2001 From: Derek Bourgeois Date: Thu, 26 Mar 2026 19:21:48 -0400 Subject: [PATCH 2/2] fix: tighten laravel mcp defaults --- README.md | 7 +------ config/mcp.php | 6 ++++-- tests/Feature/McpSmokeTest.php | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c57a5ee..f3f308f 100644 --- a/README.md +++ b/README.md @@ -101,12 +101,7 @@ Katra now includes Laravel MCP as an explicit application dependency. - Katra registers a local MCP handle named `katra` that points at `App\Mcp\Servers\KatraServer`. - The current example tool, `App\Mcp\Tools\DescribeWorkspace`, is intentionally small and read-only. It exists as a smoke-tested interoperability example, not as a parallel product surface. - MCP matters for interoperability, tool exposure, and external integrations, but it should not become the center of Katra's architecture. -- Start the local MCP server with: - -```bash -php artisan mcp:start katra -``` - +- Start the local MCP server with `php artisan mcp:start katra`. - The current smoke coverage lives in `tests/Feature/McpSmokeTest.php`. ### Surreal-Backed Migrations diff --git a/config/mcp.php b/config/mcp.php index aab2041..59991d5 100644 --- a/config/mcp.php +++ b/config/mcp.php @@ -16,9 +16,11 @@ */ 'redirect_domains' => [ - '*', // 'https://example.com', - // 'http://localhost', + 'http://localhost', + 'http://127.0.0.1', + 'https://localhost', + 'https://127.0.0.1', ], ]; diff --git a/tests/Feature/McpSmokeTest.php b/tests/Feature/McpSmokeTest.php index 6a715fa..b71a8ab 100644 --- a/tests/Feature/McpSmokeTest.php +++ b/tests/Feature/McpSmokeTest.php @@ -12,7 +12,7 @@ config('app.name'), config('app.url'), 'interoperability layer', - 'not the center of the product architecture', - 'desktop-local, server, container, and kubernetes-oriented', + 'not the center', + 'desktop-local', ]); });