Skip to content

Commit e8efdbe

Browse files
authored
Merge pull request #128 from devoption/codex/feat-32-mcp-foundation
feat: install and configure Laravel MCP
2 parents 829d9d5 + 0e470dd commit e8efdbe

8 files changed

Lines changed: 211 additions & 74 deletions

File tree

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ The Laravel AI SDK is installed and its conversation storage migrations are part
9393

9494
The current AI foundation test uses agent fakes, so the repo test suite does not require live provider credentials just to verify the integration.
9595

96+
### Laravel MCP Foundation
97+
98+
Katra now includes Laravel MCP as an explicit application dependency.
99+
100+
- 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.
101+
- Katra registers a local MCP handle named `katra` that points at `App\Mcp\Servers\KatraServer`.
102+
- 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.
103+
- MCP matters for interoperability, tool exposure, and external integrations, but it should not become the center of Katra's architecture.
104+
- Start the local MCP server with `php artisan mcp:start katra`.
105+
- The current smoke coverage lives in `tests/Feature/McpSmokeTest.php`.
106+
96107
### Surreal-Backed Migrations
97108

98109
Katra now includes a first Laravel-compatible Surreal schema driver for migration work.

app/Mcp/Servers/KatraServer.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace App\Mcp\Servers;
4+
5+
use App\Mcp\Tools\DescribeWorkspace;
6+
use Laravel\Mcp\Server;
7+
use Laravel\Mcp\Server\Attributes\Instructions;
8+
use Laravel\Mcp\Server\Attributes\Name;
9+
use Laravel\Mcp\Server\Attributes\Version;
10+
11+
#[Name('Katra MCP Server')]
12+
#[Version('0.0.1')]
13+
#[Instructions('Use this server for lightweight Katra interoperability tasks. It is intended to support integrations and tooling, not to become the center of Katra\'s product architecture.')]
14+
class KatraServer extends Server
15+
{
16+
protected array $tools = [
17+
DescribeWorkspace::class,
18+
];
19+
20+
protected array $resources = [
21+
//
22+
];
23+
24+
protected array $prompts = [
25+
//
26+
];
27+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace App\Mcp\Tools;
4+
5+
use Illuminate\Contracts\JsonSchema\JsonSchema;
6+
use Illuminate\Support\Arr;
7+
use Laravel\Mcp\Request;
8+
use Laravel\Mcp\Response;
9+
use Laravel\Mcp\Server\Attributes\Description;
10+
use Laravel\Mcp\Server\Tool;
11+
use Laravel\Mcp\Server\Tools\Annotations\IsIdempotent;
12+
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
13+
14+
#[Description('Summarize the current Katra workspace configuration and MCP role.')]
15+
#[IsReadOnly]
16+
#[IsIdempotent]
17+
class DescribeWorkspace extends Tool
18+
{
19+
public function handle(Request $request): Response
20+
{
21+
$workspaceName = (string) config('app.name');
22+
$workspaceUrl = (string) config('app.url');
23+
$runtimeTargets = Arr::join([
24+
'desktop-local',
25+
'server',
26+
'container',
27+
'kubernetes-oriented',
28+
], ', ', ', and ');
29+
30+
return Response::text(
31+
"{$workspaceName} is available at {$workspaceUrl}. ".
32+
'Laravel MCP is configured here as an interoperability layer for Katra v2, not the center of the product architecture. '.
33+
"The current planned runtime targets are {$runtimeTargets}."
34+
);
35+
}
36+
37+
/**
38+
* Get the tool's input schema.
39+
*
40+
* @return array<string, JsonSchema>
41+
*/
42+
public function schema(JsonSchema $schema): array
43+
{
44+
return [
45+
//
46+
];
47+
}
48+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"laravel/ai": "^0.3.2",
1414
"laravel/fortify": "^1.36",
1515
"laravel/framework": "^13.0",
16+
"laravel/mcp": "^0.6.3",
1617
"laravel/pennant": "^1.0",
1718
"laravel/tinker": "^3.0",
1819
"nativephp/desktop": "dev-l13-compatibility",

composer.lock

Lines changed: 74 additions & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/mcp.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
return [
4+
5+
/*
6+
|--------------------------------------------------------------------------
7+
| Redirect Domains
8+
|--------------------------------------------------------------------------
9+
|
10+
| These domains are the domains that OAuth clients are permitted to use
11+
| for redirect URIs. Each domain should be specified with its scheme
12+
| and host. Domains not in this list will raise validation errors.
13+
|
14+
| An "*" may be used to allow all domains.
15+
|
16+
*/
17+
18+
'redirect_domains' => [
19+
// 'https://example.com',
20+
'http://localhost',
21+
'http://127.0.0.1',
22+
'https://localhost',
23+
'https://127.0.0.1',
24+
],
25+
26+
];

routes/ai.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
use App\Mcp\Servers\KatraServer;
4+
use Laravel\Mcp\Facades\Mcp;
5+
6+
Mcp::local('katra', KatraServer::class);

tests/Feature/McpSmokeTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
use App\Mcp\Servers\KatraServer;
4+
use App\Mcp\Tools\DescribeWorkspace;
5+
6+
test('the katra mcp server exposes a lightweight workspace description tool', function () {
7+
KatraServer::tool(DescribeWorkspace::class)
8+
->assertOk()
9+
->assertName('describe-workspace')
10+
->assertDescription('Summarize the current Katra workspace configuration and MCP role.')
11+
->assertSee([
12+
config('app.name'),
13+
config('app.url'),
14+
'interoperability layer',
15+
'not the center',
16+
'desktop-local',
17+
]);
18+
});

0 commit comments

Comments
 (0)