1010 * - Admin authentication required
1111 * - Origin validation for security
1212 * - Automatic admin route to tool conversion
13+ * - Module-based tool organization with lazy loading
1314 */
1415
1516import { NextFunction , Request , Response } from 'express' ;
@@ -18,11 +19,12 @@ import { ConduitGrpcSdk } from '@conduitplatform/grpc-sdk';
1819import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' ;
1920import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js' ;
2021import { MCPConfig , MCPToolDefinition } from './types.js' ;
21- import { ToolRegistry } from './ToolRegistry.js' ;
22+ import { CORE_MODULE , ToolRegistry } from './ToolRegistry.js' ;
2223import { MCP_ERROR_CODES } from './MCPErrors.js' ;
2324import { convertConduitRouteToMCPTool } from './RouteToTool.js' ;
2425import { ConduitRoute } from '../classes/index.js' ;
2526import { isNil } from 'lodash-es' ;
27+ import { registerMetaTools } from './MetaTools.js' ;
2628
2729export class MCPController extends ConduitRouter {
2830 private _mcpServer : McpServer ;
@@ -54,6 +56,9 @@ export class MCPController extends ConduitRouter {
5456 this . _toolRegistry = new ToolRegistry ( grpcSdk ) ;
5557 this . _toolRegistry . setMcpServer ( this . _mcpServer ) ;
5658
59+ // Register meta-tools for module discovery (always enabled)
60+ registerMetaTools ( this . _toolRegistry ) ;
61+
5762 this . initializeRouter ( ) ;
5863 }
5964
@@ -137,16 +142,52 @@ export class MCPController extends ConduitRouter {
137142 * Health check endpoint
138143 */
139144 private handleHealthCheck ( req : Request , res : Response ) {
145+ const modules = this . _toolRegistry . getModules ( ) ;
140146 res . json ( {
141147 status : 'healthy' ,
142148 protocol : 'mcp' ,
143149 version : this . _config . protocolVersion ,
144150 serverInfo : this . _config . serverInfo ,
145- tools : this . _toolRegistry . getToolCount ( ) ,
151+ tools : {
152+ total : this . _toolRegistry . getToolCount ( ) ,
153+ enabled : this . _toolRegistry . getEnabledToolCount ( ) ,
154+ } ,
155+ modules : {
156+ total : modules . length ,
157+ loaded : this . _toolRegistry . getLoadedModules ( ) . length ,
158+ list : modules ,
159+ } ,
146160 uptime : process . uptime ( ) ,
147161 } ) ;
148162 }
149163
164+ /**
165+ * Extract module name from route path
166+ * e.g., "/authentication/local/login" -> "authentication"
167+ * e.g., "/storage/file/:id" -> "storage"
168+ * e.g., "/config" -> "core"
169+ */
170+ private extractModuleFromPath ( path : string ) : string {
171+ // Remove leading slash and split by /
172+ const segments = path . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
173+
174+ // First segment is the module name
175+ const firstSegment = segments [ 0 ] ;
176+
177+ // If path is just a single segment or empty, use core module
178+ if ( ! firstSegment || segments . length === 1 ) {
179+ return CORE_MODULE ;
180+ }
181+
182+ // Skip common prefixes that aren't module names
183+ if ( firstSegment === 'admin' || firstSegment === 'hook' ) {
184+ // Use second segment as module
185+ return segments [ 1 ] || CORE_MODULE ;
186+ }
187+
188+ return firstSegment ;
189+ }
190+
150191 /**
151192 * Register a tool with the MCP server
152193 */
@@ -182,22 +223,26 @@ export class MCPController extends ConduitRouter {
182223 * Register a Conduit admin route as an MCP tool
183224 */
184225 registerRouteAsTool ( route : ConduitRoute ) : void {
185- const tool = convertConduitRouteToMCPTool ( route , this ) ;
226+ // Extract module from route path
227+ const moduleName = this . extractModuleFromPath ( route . input . path ) ;
228+
229+ // Convert route to tool with module info
230+ const tool = convertConduitRouteToMCPTool ( route , this , { module : moduleName } ) ;
186231 this . registerTool ( tool ) ;
187232 }
188233
189234 // Override ConduitRouter methods
190235 protected _refreshRouter ( ) {
191- // Don't recreate server, just unregister and re-register tools
192- this . _toolRegistry . clearAllTools ( ) ; // This now properly removes via handles
236+ // Clear module tools but preserve meta- tools
237+ this . _toolRegistry . clearModuleTools ( ) ;
193238
194239 // Re-register all tools from registered routes
195240 this . _registeredRoutes . forEach ( route => {
196241 this . registerRouteAsTool ( route ) ;
197242 } ) ;
198243
199244 ConduitGrpcSdk . Logger . log (
200- `MCP tools refreshed: ${ this . _registeredRoutes . size } tools` ,
245+ `MCP tools refreshed: ${ this . _registeredRoutes . size } module tools + meta- tools` ,
201246 ) ;
202247 }
203248
@@ -221,6 +266,13 @@ export class MCPController extends ConduitRouter {
221266 this . refreshRouter ( ) ; // Triggers _refreshRouter after delay
222267 }
223268
269+ /**
270+ * Get the tool registry (for testing/debugging)
271+ */
272+ getToolRegistry ( ) : ToolRegistry {
273+ return this . _toolRegistry ;
274+ }
275+
224276 shutDown ( ) {
225277 ConduitGrpcSdk . Logger . log ( 'Shutting down MCP controller' ) ;
226278 super . shutDown ( ) ;
0 commit comments