Skip to content

Commit 83087c2

Browse files
committed
feat: add 'models' to application info tool
1 parent dae7a98 commit 83087c2

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

src/Mcp/Tools/ApplicationInfo.php

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,27 @@
22

33
namespace Laravel\Boost\Mcp\Tools;
44

5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Facades\Log;
57
use Laravel\Mcp\Server\Tool;
68
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
79
use Laravel\Mcp\Server\Tools\ToolInputSchema;
810
use Laravel\Mcp\Server\Tools\ToolResult;
11+
use Laravel\Roster\Package;
912
use Laravel\Roster\Roster;
13+
use ReflectionClass;
14+
use Symfony\Component\Finder\Finder;
1015

1116
#[IsReadOnly]
1217
class ApplicationInfo extends Tool
1318
{
14-
public function __construct(protected Roster $roster) {}
19+
public function __construct(protected Roster $roster)
20+
{
21+
}
1522

1623
public function description(): string
1724
{
18-
return 'Get comprehensive application information including PHP version, Laravel version, database engine, and all installed packages with their versions. You should use this tool on each new chat, and use the package & version data to write version specific code for the packages that exist.';
25+
return 'Get comprehensive application information including PHP version, Laravel version, database engine, all installed packages with their versions, and all Eloquent models in the application. You should use this tool on each new chat, and use the package & version data to write version specific code for the packages that exist.';
1926
}
2027

2128
public function schema(ToolInputSchema $schema): ToolInputSchema
@@ -24,23 +31,59 @@ public function schema(ToolInputSchema $schema): ToolInputSchema
2431
}
2532

2633
/**
27-
* @param array<string> $arguments
34+
* @param array<string> $arguments
2835
*/
2936
public function handle(array $arguments): ToolResult
3037
{
31-
$packages = [];
32-
foreach ($this->roster->packages() as $package) {
33-
$packages[] = [
34-
'name' => $package->name(),
35-
'version' => $package->version(),
36-
];
37-
}
38-
3938
return ToolResult::json([
4039
'php_version' => PHP_VERSION,
4140
'laravel_version' => app()->version(),
4241
'database_engine' => config('database.default'),
43-
'packages' => $packages,
42+
'packages' => $this->roster->packages()->map(fn(Package $package) => ['name' => $package->name(), 'version' => $package->version()]),
43+
'models' => $this->discoverModels(),
4444
]);
4545
}
46+
47+
/**
48+
* Discover all Eloquent models in the application
49+
*
50+
* @return array<string, string>
51+
*/
52+
private function discoverModels(): array
53+
{
54+
$models = [];
55+
$appPath = app_path();
56+
57+
if (!is_dir($appPath)) {
58+
return ['app-path-isnt-a-directory:' . $appPath];
59+
}
60+
61+
$finder = Finder::create()
62+
->in($appPath)
63+
->files()
64+
->name('*.php');
65+
66+
foreach ($finder as $file) {
67+
$relativePath = $file->getRelativePathname();
68+
$namespace = app()->getNamespace();
69+
$className = $namespace . str_replace(
70+
['/', '.php'],
71+
['\\', ''],
72+
$relativePath
73+
);
74+
75+
try {
76+
if (class_exists($className)) {
77+
$reflection = new ReflectionClass($className);
78+
if ($reflection->isSubclassOf(Model::class) && !$reflection->isAbstract()) {
79+
$models[$className] = $appPath . DIRECTORY_SEPARATOR . $relativePath;
80+
}
81+
}
82+
} catch (\Throwable) {
83+
// Ignore exceptions and errors from class loading/reflection
84+
}
85+
}
86+
87+
return $models;
88+
}
4689
}

tests/Feature/Mcp/Tools/ApplicationInfoTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
expect($content['packages'][0]['version'])->toBe('11.0.0');
3333
expect($content['packages'][1]['name'])->toBe('PEST');
3434
expect($content['packages'][1]['version'])->toBe('2.0.0');
35+
expect($content['models'])->toBeArray();
3536
});
3637

3738
test('it returns application info with no packages', function () {
@@ -52,4 +53,5 @@
5253
expect($content['laravel_version'])->toBe(app()->version());
5354
expect($content['database_engine'])->toBe(config('database.default'));
5455
expect($content['packages'])->toHaveCount(0);
56+
expect($content['models'])->toBeArray();
5557
});

0 commit comments

Comments
 (0)