Skip to content

Commit 89850e0

Browse files
committed
Simplify tool, resource, and prompt discovery logic for MCP
Signed-off-by: Pushpak Chhajed <[email protected]>
1 parent a1553c6 commit 89850e0

File tree

2 files changed

+67
-82
lines changed

2 files changed

+67
-82
lines changed

rector.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
declare(strict_types=1);
44

55
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
6-
use Rector\CodingStyle\Rector\FunctionLike\FunctionLikeToFirstClassCallableRector;
76
use Rector\Config\RectorConfig;
87
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
98
use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector;
@@ -17,7 +16,6 @@
1716
ReadOnlyPropertyRector::class,
1817
EncapsedStringsToSprintfRector::class,
1918
DisallowedEmptyRuleFixerRector::class,
20-
FunctionLikeToFirstClassCallableRector::class,
2119
])
2220
->withPreparedSets(
2321
deadCode: true,

src/Mcp/Boost.php

Lines changed: 67 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,27 @@
44

55
namespace Laravel\Boost\Mcp;
66

7-
use DirectoryIterator;
87
use Laravel\Boost\Mcp\Methods\CallToolWithExecutor;
9-
use Laravel\Boost\Mcp\Resources\ApplicationInfo;
8+
use Laravel\Boost\Mcp\Tools\ApplicationInfo;
9+
use Laravel\Boost\Mcp\Tools\BrowserLogs;
10+
use Laravel\Boost\Mcp\Tools\DatabaseConnections;
11+
use Laravel\Boost\Mcp\Tools\DatabaseQuery;
12+
use Laravel\Boost\Mcp\Tools\DatabaseSchema;
13+
use Laravel\Boost\Mcp\Tools\GetAbsoluteUrl;
14+
use Laravel\Boost\Mcp\Tools\GetConfig;
15+
use Laravel\Boost\Mcp\Tools\LastError;
16+
use Laravel\Boost\Mcp\Tools\ListArtisanCommands;
17+
use Laravel\Boost\Mcp\Tools\ListAvailableConfigKeys;
18+
use Laravel\Boost\Mcp\Tools\ListAvailableEnvVars;
19+
use Laravel\Boost\Mcp\Tools\ListRoutes;
20+
use Laravel\Boost\Mcp\Tools\ReadLogEntries;
21+
use Laravel\Boost\Mcp\Tools\ReportFeedback;
22+
use Laravel\Boost\Mcp\Tools\SearchDocs;
23+
use Laravel\Boost\Mcp\Tools\Tinker;
1024
use Laravel\Mcp\Server;
25+
use Laravel\Mcp\Server\Prompt;
26+
use Laravel\Mcp\Server\Resource;
27+
use Laravel\Mcp\Server\Tool;
1128

1229
class Boost extends Server
1330
{
@@ -34,120 +51,90 @@ class Boost extends Server
3451
/**
3552
* The tools registered with this MCP server.
3653
*
37-
* @var array<int, class-string<\Laravel\Mcp\Server\Tool>>
54+
* @var array<int, class-string<Tool>>
3855
*/
3956
protected array $tools = [];
4057

4158
/**
4259
* The resources registered with this MCP server.
4360
*
44-
* @var array<int, class-string<\Laravel\Mcp\Server\Resource>>
61+
* @var array<int, class-string<Resource>>
4562
*/
46-
protected array $resources = [
47-
ApplicationInfo::class,
48-
];
63+
protected array $resources = [];
4964

5065
/**
5166
* The prompts registered with this MCP server.
5267
*
53-
* @var array<int, class-string<\Laravel\Mcp\Server\Prompt>>
68+
* @var array<int, class-string<Prompt>>
5469
*/
5570
protected array $prompts = [];
5671

5772
protected function boot(): void
5873
{
59-
collect($this->discoverTools())->each(fn (string $tool): string => $this->tools[] = $tool);
60-
collect($this->discoverResources())->each(fn (string $resource): string => $this->resources[] = $resource);
61-
collect($this->discoverPrompts())->each(fn (string $prompt): string => $this->prompts[] = $prompt);
74+
$this->tools = $this->discoverTools();
75+
$this->resources = $this->discoverResources();
76+
$this->prompts = $this->discoverPrompts();
6277

6378
// Override the tools/call method to use our ToolExecutor
6479
$this->methods['tools/call'] = CallToolWithExecutor::class;
6580
}
6681

6782
/**
68-
* @return array<int, class-string<\Laravel\Mcp\Server\Tool>>
83+
* @param array<int, class-string> $availablePrimitives
84+
* @return array<int, class-string>
85+
*/
86+
private function discoverPrimitives(array $availablePrimitives, string $type): array
87+
{
88+
return collect($availablePrimitives)
89+
->diff(config("boost.mcp.{$type}.exclude", []))
90+
->merge(
91+
collect(config("boost.mcp.{$type}.include", []))
92+
->filter(fn (string $class): bool => class_exists($class))
93+
)
94+
->values()
95+
->all();
96+
}
97+
98+
/**
99+
* @return array<int, class-string<Tool>>
69100
*/
70101
protected function discoverTools(): array
71102
{
72-
$tools = [];
73-
74-
$excludedTools = config('boost.mcp.tools.exclude', []);
75-
$toolDir = new DirectoryIterator(__DIR__.DIRECTORY_SEPARATOR.'Tools');
76-
77-
foreach ($toolDir as $toolFile) {
78-
if ($toolFile->isFile() && $toolFile->getExtension() === 'php') {
79-
$fqdn = 'Laravel\\Boost\\Mcp\\Tools\\'.$toolFile->getBasename('.php');
80-
if (class_exists($fqdn) && ! in_array($fqdn, $excludedTools, true)) {
81-
$tools[] = $fqdn;
82-
}
83-
}
84-
}
85-
86-
$extraTools = config('boost.mcp.tools.include', []);
87-
foreach ($extraTools as $toolClass) {
88-
if (class_exists($toolClass)) {
89-
$tools[] = $toolClass;
90-
}
91-
}
92-
93-
return $tools;
103+
return $this->discoverPrimitives([
104+
ApplicationInfo::class,
105+
BrowserLogs::class,
106+
DatabaseConnections::class,
107+
DatabaseQuery::class,
108+
DatabaseSchema::class,
109+
GetAbsoluteUrl::class,
110+
GetConfig::class,
111+
LastError::class,
112+
ListArtisanCommands::class,
113+
ListAvailableConfigKeys::class,
114+
ListAvailableEnvVars::class,
115+
ListRoutes::class,
116+
ReadLogEntries::class,
117+
ReportFeedback::class,
118+
SearchDocs::class,
119+
Tinker::class,
120+
], 'tools');
94121
}
95122

96123
/**
97-
* @return array<int, class-string<\Laravel\Mcp\Server\Resource>>
124+
* @return array<int, class-string<Resource>>
98125
*/
99126
protected function discoverResources(): array
100127
{
101-
$resources = [];
102-
103-
$excludedResources = config('boost.mcp.resources.exclude', []);
104-
$resourceDir = new DirectoryIterator(__DIR__.DIRECTORY_SEPARATOR.'Resources');
105-
106-
foreach ($resourceDir as $resourceFile) {
107-
if ($resourceFile->isFile() && $resourceFile->getExtension() === 'php') {
108-
$fqdn = 'Laravel\\Boost\\Mcp\\Resources\\'.$resourceFile->getBasename('.php');
109-
if (class_exists($fqdn) && ! in_array($fqdn, $excludedResources, true) && $fqdn !== ApplicationInfo::class) {
110-
$resources[] = $fqdn;
111-
}
112-
}
113-
}
114-
115-
$extraResources = config('boost.mcp.resources.include', []);
116-
foreach ($extraResources as $resourceClass) {
117-
if (class_exists($resourceClass)) {
118-
$resources[] = $resourceClass;
119-
}
120-
}
121-
122-
return $resources;
128+
return $this->discoverPrimitives([
129+
Resources\ApplicationInfo::class,
130+
], 'resources');
123131
}
124132

125133
/**
126-
* @return array<int, class-string<\Laravel\Mcp\Server\Prompt>>
134+
* @return array<int, class-string<Prompt>>
127135
*/
128136
protected function discoverPrompts(): array
129137
{
130-
$prompts = [];
131-
132-
$excludedPrompts = config('boost.mcp.prompts.exclude', []);
133-
$promptDir = new DirectoryIterator(__DIR__.DIRECTORY_SEPARATOR.'Prompts');
134-
135-
foreach ($promptDir as $promptFile) {
136-
if ($promptFile->isFile() && $promptFile->getExtension() === 'php') {
137-
$fqdn = 'Laravel\\Boost\\Mcp\\Prompts\\'.$promptFile->getBasename('.php');
138-
if (class_exists($fqdn) && ! in_array($fqdn, $excludedPrompts, true)) {
139-
$prompts[] = $fqdn;
140-
}
141-
}
142-
}
143-
144-
$extraPrompts = config('boost.mcp.prompts.include', []);
145-
foreach ($extraPrompts as $promptClass) {
146-
if (class_exists($promptClass)) {
147-
$prompts[] = $promptClass;
148-
}
149-
}
150-
151-
return $prompts;
138+
return $this->discoverPrimitives([], 'prompts');
152139
}
153140
}

0 commit comments

Comments
 (0)