2020use Mcp \Capability \Prompt \Completion \ListCompletionProvider ;
2121use Mcp \Capability \Prompt \Completion \ProviderInterface ;
2222use Mcp \Capability \Registry ;
23+ use Mcp \Capability \Registry \PromptReference ;
24+ use Mcp \Capability \Registry \ResourceReference ;
25+ use Mcp \Capability \Registry \ResourceTemplateReference ;
26+ use Mcp \Capability \Registry \ToolReference ;
2327use Mcp \Exception \ExceptionInterface ;
2428use Mcp \Schema \Prompt ;
2529use Mcp \Schema \PromptArgument ;
@@ -54,13 +58,13 @@ public function __construct(
5458 }
5559
5660 /**
57- * Discover MCP elements in the specified directories.
61+ * Discover MCP elements in the specified directories and return the discovery state .
5862 *
5963 * @param string $basePath the base path for resolving directories
6064 * @param array<string> $directories list of directories (relative to base path) to scan
6165 * @param array<string> $excludeDirs list of directories (relative to base path) to exclude from the scan
6266 */
63- public function discover (string $ basePath , array $ directories , array $ excludeDirs = []): void
67+ public function discover (string $ basePath , array $ directories , array $ excludeDirs = []): DiscoveryState
6468 {
6569 $ startTime = microtime (true );
6670 $ discoveredCount = [
@@ -70,6 +74,12 @@ public function discover(string $basePath, array $directories, array $excludeDir
7074 'resourceTemplates ' => 0 ,
7175 ];
7276
77+ // Collections to store discovered elements
78+ $ tools = [];
79+ $ resources = [];
80+ $ prompts = [];
81+ $ resourceTemplates = [];
82+
7383 try {
7484 $ finder = new Finder ();
7585 $ absolutePaths = [];
@@ -86,7 +96,7 @@ public function discover(string $basePath, array $directories, array $excludeDir
8696 'base_path ' => $ basePath ,
8797 ]);
8898
89- return ;
99+ return new DiscoveryState () ;
90100 }
91101
92102 $ finder ->files ()
@@ -95,7 +105,7 @@ public function discover(string $basePath, array $directories, array $excludeDir
95105 ->name ('*.php ' );
96106
97107 foreach ($ finder as $ file ) {
98- $ this ->processFile ($ file , $ discoveredCount );
108+ $ this ->processFile ($ file , $ discoveredCount, $ tools , $ resources , $ prompts , $ resourceTemplates );
99109 }
100110 } catch (\Throwable $ e ) {
101111 $ this ->logger ->error ('Error during file finding process for MCP discovery ' , [
@@ -112,14 +122,29 @@ public function discover(string $basePath, array $directories, array $excludeDir
112122 'prompts ' => $ discoveredCount ['prompts ' ],
113123 'resourceTemplates ' => $ discoveredCount ['resourceTemplates ' ],
114124 ]);
125+
126+ return new DiscoveryState ($ tools , $ resources , $ prompts , $ resourceTemplates );
127+ }
128+
129+ /**
130+ * Apply a discovery state to the registry.
131+ * This method imports the discovered elements into the registry.
132+ */
133+ public function applyDiscoveryState (DiscoveryState $ state ): void
134+ {
135+ $ this ->registry ->importDiscoveryState ($ state );
115136 }
116137
117138 /**
118139 * Process a single PHP file for MCP elements on classes or methods.
119140 *
120141 * @param DiscoveredCount $discoveredCount
142+ * @param array<string, ToolReference> $tools
143+ * @param array<string, ResourceReference> $resources
144+ * @param array<string, PromptReference> $prompts
145+ * @param array<string, ResourceTemplateReference> $resourceTemplates
121146 */
122- private function processFile (SplFileInfo $ file , array &$ discoveredCount ): void
147+ private function processFile (SplFileInfo $ file , array &$ discoveredCount, array & $ tools , array & $ resources , array & $ prompts , array & $ resourceTemplates ): void
123148 {
124149 $ filePath = $ file ->getRealPath ();
125150 if (false === $ filePath ) {
@@ -150,7 +175,7 @@ private function processFile(SplFileInfo $file, array &$discoveredCount): void
150175 foreach ($ attributeTypes as $ attributeType ) {
151176 $ classAttribute = $ reflectionClass ->getAttributes ($ attributeType , \ReflectionAttribute::IS_INSTANCEOF )[0 ] ?? null ;
152177 if ($ classAttribute ) {
153- $ this ->processMethod ($ invokeMethod , $ discoveredCount , $ classAttribute );
178+ $ this ->processMethod ($ invokeMethod , $ discoveredCount , $ classAttribute, $ tools , $ resources , $ prompts , $ resourceTemplates );
154179 $ processedViaClassAttribute = true ;
155180 break ;
156181 }
@@ -170,7 +195,7 @@ private function processFile(SplFileInfo $file, array &$discoveredCount): void
170195 foreach ($ attributeTypes as $ attributeType ) {
171196 $ methodAttribute = $ method ->getAttributes ($ attributeType , \ReflectionAttribute::IS_INSTANCEOF )[0 ] ?? null ;
172197 if ($ methodAttribute ) {
173- $ this ->processMethod ($ method , $ discoveredCount , $ methodAttribute );
198+ $ this ->processMethod ($ method , $ discoveredCount , $ methodAttribute, $ tools , $ resources , $ prompts , $ resourceTemplates );
174199 break ;
175200 }
176201 }
@@ -195,8 +220,12 @@ private function processFile(SplFileInfo $file, array &$discoveredCount): void
195220 * @param \ReflectionMethod $method The target method (e.g., regular method or __invoke).
196221 * @param DiscoveredCount $discoveredCount pass by reference to update counts
197222 * @param \ReflectionAttribute<McpTool|McpResource|McpPrompt|McpResourceTemplate> $attribute the ReflectionAttribute instance found (on method or class)
223+ * @param array<string, ToolReference> $tools
224+ * @param array<string, ResourceReference> $resources
225+ * @param array<string, PromptReference> $prompts
226+ * @param array<string, ResourceTemplateReference> $resourceTemplates
198227 */
199- private function processMethod (\ReflectionMethod $ method , array &$ discoveredCount , \ReflectionAttribute $ attribute ): void
228+ private function processMethod (\ReflectionMethod $ method , array &$ discoveredCount , \ReflectionAttribute $ attribute, array & $ tools , array & $ resources , array & $ prompts , array & $ resourceTemplates ): void
200229 {
201230 $ className = $ method ->getDeclaringClass ()->getName ();
202231 $ classShortName = $ method ->getDeclaringClass ()->getShortName ();
@@ -213,7 +242,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
213242 $ description = $ instance ->description ?? $ this ->docBlockParser ->getSummary ($ docBlock ) ?? null ;
214243 $ inputSchema = $ this ->schemaGenerator ->generate ($ method );
215244 $ tool = new Tool ($ name , $ inputSchema , $ description , $ instance ->annotations );
216- $ this -> registry -> registerTool ($ tool , [$ className , $ methodName ]);
245+ $ tools [ $ name ] = new ToolReference ($ tool , [$ className , $ methodName ], false );
217246 ++$ discoveredCount ['tools ' ];
218247 break ;
219248
@@ -225,7 +254,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
225254 $ size = $ instance ->size ;
226255 $ annotations = $ instance ->annotations ;
227256 $ resource = new Resource ($ instance ->uri , $ name , $ description , $ mimeType , $ annotations , $ size );
228- $ this -> registry -> registerResource ($ resource , [$ className , $ methodName ]);
257+ $ resources [ $ instance -> uri ] = new ResourceReference ($ resource , [$ className , $ methodName ], false );
229258 ++$ discoveredCount ['resources ' ];
230259 break ;
231260
@@ -245,7 +274,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
245274 }
246275 $ prompt = new Prompt ($ name , $ description , $ arguments );
247276 $ completionProviders = $ this ->getCompletionProviders ($ method );
248- $ this -> registry -> registerPrompt ($ prompt , [$ className , $ methodName ], $ completionProviders );
277+ $ prompts [ $ name ] = new PromptReference ($ prompt , [$ className , $ methodName ], false , $ completionProviders );
249278 ++$ discoveredCount ['prompts ' ];
250279 break ;
251280
@@ -257,7 +286,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
257286 $ annotations = $ instance ->annotations ;
258287 $ resourceTemplate = new ResourceTemplate ($ instance ->uriTemplate , $ name , $ description , $ mimeType , $ annotations );
259288 $ completionProviders = $ this ->getCompletionProviders ($ method );
260- $ this -> registry -> registerResourceTemplate ($ resourceTemplate , [$ className , $ methodName ], $ completionProviders );
289+ $ resourceTemplates [ $ instance -> uriTemplate ] = new ResourceTemplateReference ($ resourceTemplate , [$ className , $ methodName ], false , $ completionProviders );
261290 ++$ discoveredCount ['resourceTemplates ' ];
262291 break ;
263292 }
0 commit comments