44
55namespace Laravel \Boost \Mcp ;
66
7- use DirectoryIterator ;
87use Laravel \Boost \Install \GuidelineAssist ;
98use Laravel \Boost \Mcp \Methods \CallToolWithExecutor ;
109use Laravel \Boost \Mcp \Prompts \BladePrompt ;
11- use Laravel \Boost \Mcp \Resources \ApplicationInfo ;
10+ use Laravel \Boost \Mcp \Tools \ApplicationInfo ;
11+ use Laravel \Boost \Mcp \Tools \BrowserLogs ;
12+ use Laravel \Boost \Mcp \Tools \DatabaseConnections ;
13+ use Laravel \Boost \Mcp \Tools \DatabaseQuery ;
14+ use Laravel \Boost \Mcp \Tools \DatabaseSchema ;
15+ use Laravel \Boost \Mcp \Tools \GetAbsoluteUrl ;
16+ use Laravel \Boost \Mcp \Tools \GetConfig ;
17+ use Laravel \Boost \Mcp \Tools \LastError ;
18+ use Laravel \Boost \Mcp \Tools \ListArtisanCommands ;
19+ use Laravel \Boost \Mcp \Tools \ListAvailableConfigKeys ;
20+ use Laravel \Boost \Mcp \Tools \ListAvailableEnvVars ;
21+ use Laravel \Boost \Mcp \Tools \ListRoutes ;
22+ use Laravel \Boost \Mcp \Tools \ReadLogEntries ;
23+ use Laravel \Boost \Mcp \Tools \ReportFeedback ;
24+ use Laravel \Boost \Mcp \Tools \SearchDocs ;
25+ use Laravel \Boost \Mcp \Tools \Tinker ;
1226use Laravel \Boost \Support \Composer ;
1327use Laravel \Mcp \Server ;
28+ use Laravel \Mcp \Server \Prompt ;
29+ use Laravel \Mcp \Server \Resource ;
30+ use Laravel \Mcp \Server \Tool ;
1431
1532class Boost extends Server
1633{
@@ -37,111 +54,109 @@ class Boost extends Server
3754 /**
3855 * The tools registered with this MCP server.
3956 *
40- * @var array<int, class-string<\Laravel\Mcp\Server\ Tool>>
57+ * @var array<int, class-string<Tool>>
4158 */
4259 protected array $ tools = [];
4360
4461 /**
4562 * The resources registered with this MCP server.
4663 *
47- * @var array<int, class-string<\Laravel\Mcp\Server\ Resource>>
64+ * @var array<int, class-string<Resource>>
4865 */
49- protected array $ resources = [
50- ApplicationInfo::class,
51- ];
66+ protected array $ resources = [];
5267
5368 /**
5469 * The prompts registered with this MCP server.
5570 *
56- * @var array<int, class-string<\Laravel\Mcp\Server\ Prompt>>
71+ * @var array<int, class-string<Prompt>>
5772 */
5873 protected array $ prompts = [];
5974
6075 protected function boot (): void
6176 {
62- collect ($ this ->discoverTools ())->each (fn (string $ tool ): string => $ this ->tools [] = $ tool );
63- collect ($ this ->discoverResources ())->each (fn (string $ resource ): string => $ this ->resources [] = $ resource );
64-
65- $ this ->discoverThirdPartyPrompts ();
77+ $ this ->tools = $ this ->discoverTools ();
78+ $ this ->resources = $ this ->discoverResources ();
79+ $ this ->prompts = $ this ->discoverPrompts ();
6680
6781 // Override the tools/call method to use our ToolExecutor
6882 $ this ->methods ['tools/call ' ] = CallToolWithExecutor::class;
6983 }
7084
7185 /**
72- * @return array<int, class-string<\Laravel\Mcp\Server\ Tool>>
86+ * @return array<int, class-string<Tool>>
7387 */
7488 protected function discoverTools (): array
7589 {
76- $ tools = [];
77-
78- $ excludedTools = config ('boost.mcp.tools.exclude ' , []);
79- $ toolDir = new DirectoryIterator (__DIR__ .DIRECTORY_SEPARATOR .'Tools ' );
80-
81- foreach ($ toolDir as $ toolFile ) {
82- if ($ toolFile ->isFile () && $ toolFile ->getExtension () === 'php ' ) {
83- $ fqdn = 'Laravel \\Boost \\Mcp \\Tools \\' .$ toolFile ->getBasename ('.php ' );
84- if (class_exists ($ fqdn ) && ! in_array ($ fqdn , $ excludedTools , true )) {
85- $ tools [] = $ fqdn ;
86- }
87- }
88- }
89-
90- $ extraTools = config ('boost.mcp.tools.include ' , []);
91- foreach ($ extraTools as $ toolClass ) {
92- if (class_exists ($ toolClass )) {
93- $ tools [] = $ toolClass ;
94- }
95- }
96-
97- return $ tools ;
90+ return $ this ->filterPrimitives ([
91+ ApplicationInfo::class,
92+ BrowserLogs::class,
93+ DatabaseConnections::class,
94+ DatabaseQuery::class,
95+ DatabaseSchema::class,
96+ GetAbsoluteUrl::class,
97+ GetConfig::class,
98+ LastError::class,
99+ ListArtisanCommands::class,
100+ ListAvailableConfigKeys::class,
101+ ListAvailableEnvVars::class,
102+ ListRoutes::class,
103+ ReadLogEntries::class,
104+ ReportFeedback::class,
105+ SearchDocs::class,
106+ Tinker::class,
107+ ], 'tools ' );
98108 }
99109
100110 /**
101- * @return array<int, class-string<\Laravel\Mcp\Server\ Resource>>
111+ * @return array<int, class-string<Resource>>
102112 */
103113 protected function discoverResources (): array
104114 {
105- $ resources = [];
106-
107- $ excludedResources = config ('boost.mcp.resources.exclude ' , []);
108- $ resourceDir = new DirectoryIterator (__DIR__ .DIRECTORY_SEPARATOR .'Resources ' );
109-
110- foreach ($ resourceDir as $ resourceFile ) {
111- if ($ resourceFile ->isFile () && $ resourceFile ->getExtension () === 'php ' ) {
112- $ fqdn = 'Laravel \\Boost \\Mcp \\Resources \\' .$ resourceFile ->getBasename ('.php ' );
113- if (class_exists ($ fqdn ) && ! in_array ($ fqdn , $ excludedResources , true ) && $ fqdn !== ApplicationInfo::class) {
114- $ resources [] = $ fqdn ;
115- }
116- }
117- }
118-
119- $ extraResources = config ('boost.mcp.resources.include ' , []);
120- foreach ($ extraResources as $ resourceClass ) {
121- if (class_exists ($ resourceClass )) {
122- $ resources [] = $ resourceClass ;
123- }
124- }
115+ return $ this ->filterPrimitives ([
116+ Resources \ApplicationInfo::class,
117+ ], 'resources ' );
118+ }
125119
126- return $ resources ;
120+ /**
121+ * @return array<int, class-string<Prompt>>
122+ */
123+ protected function discoverPrompts (): array
124+ {
125+ return $ this ->filterPrimitives (
126+ $ this ->discoverThirdPartyPrompts (),
127+ 'prompts '
128+ );
127129 }
128130
129- protected function discoverThirdPartyPrompts (): void
131+ protected function discoverThirdPartyPrompts (): array
130132 {
133+ $ thirdPartyPrompts = [];
131134 $ guidelineAssist = app (GuidelineAssist::class);
132135
133136 foreach (Composer::packagesDirectoriesWithBoostGuidelines () as $ package => $ path ) {
134- $ corePath = $ path .DIRECTORY_SEPARATOR .'core.blade.php ' ;
137+ $ guidelinePath = $ path .DIRECTORY_SEPARATOR .'core.blade.php ' ;
135138
136- if (file_exists ($ corePath )) {
137- $ this -> registerThirdPartyPrompt ( $ package , $ corePath , $ guidelineAssist );
139+ if (file_exists ($ guidelinePath )) {
140+ $ thirdPartyPrompts [] = new BladePrompt ( $ guidelineAssist , $ package , $ guidelinePath );
138141 }
139142 }
143+
144+ return $ thirdPartyPrompts ;
140145 }
141146
142- protected function registerThirdPartyPrompt (string $ package , string $ bladePath , GuidelineAssist $ guidelineAssist ): void
147+ /**
148+ * @param array<int, class-string> $availablePrimitives
149+ * @return array<int, class-string>
150+ */
151+ private function filterPrimitives (array $ availablePrimitives , string $ type ): array
143152 {
144- $ prompt = new BladePrompt ($ guidelineAssist , $ package , $ bladePath );
145- $ this ->prompts [] = $ prompt ;
153+ return collect ($ availablePrimitives )
154+ ->diff (config ("boost.mcp. {$ type }.exclude " , []))
155+ ->merge (
156+ collect (config ("boost.mcp. {$ type }.include " , []))
157+ ->filter (fn (string $ class ): bool => class_exists ($ class ))
158+ )
159+ ->values ()
160+ ->all ();
146161 }
147162}
0 commit comments