Skip to main content
Glama
internalCapabilitiesProvider.ts10.8 kB
/** * Internal capabilities provider for internal management tools * * This module provides internal MCP tools for managing the agent itself. * It acts as a special internal capabilities provider that exposes management capabilities. */ import { EventEmitter } from 'events'; import { Prompt, Resource, Tool } from '@modelcontextprotocol/sdk/types.js'; import { createInfoTool, createRegistryInfoTool, createRegistryListTool, createRegistryStatusTool, createSearchTool, } from '@src/core/capabilities/internal/discoveryTools.js'; import { createInstallTool, createUninstallTool, createUpdateTool, } from '@src/core/capabilities/internal/installationTools.js'; import { createDisableTool, createEditTool, createEnableTool, createListTool, createReloadTool, createStatusTool, } from '@src/core/capabilities/internal/managementTools.js'; import { FlagManager } from '@src/core/flags/flagManager.js'; import { AgentConfigManager } from '@src/core/server/agentConfig.js'; import { cleanupInternalToolHandlers, handleMcpDisable, handleMcpEdit, handleMcpEnable, handleMcpInfo, handleMcpInstall, handleMcpList, handleMcpRegistryInfo, handleMcpRegistryList, handleMcpRegistryStatus, handleMcpReload, handleMcpSearch, handleMcpStatus, handleMcpUninstall, handleMcpUpdate, } from '@src/core/tools/internal/index.js'; import { McpDisableToolSchema, McpEditToolSchema, McpEnableToolSchema, McpInfoToolSchema, McpInstallToolSchema, McpListToolSchema, McpRegistryInfoSchema, McpRegistryListSchema, McpRegistryStatusSchema, McpReloadToolSchema, McpSearchToolSchema, McpStatusToolSchema, McpUninstallToolSchema, McpUpdateToolSchema, } from '@src/core/tools/internal/schemas/index.js'; import logger from '@src/logger/logger.js'; import { z } from 'zod'; /** * Validate tool arguments using a Zod schema * * @param schema The Zod schema to validate against * @param args The raw arguments to validate * @param toolName The name of the tool for error reporting * @returns Validated and typed arguments * @throws Error if validation fails */ function validateToolArgs<T extends z.ZodType>(schema: T, args: unknown, toolName: string): z.infer<T> { try { return schema.parse(args); } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join(', '); logger.error(`Tool argument validation failed for ${toolName}`, { toolName, errors: error.issues, receivedArgs: args, }); throw new Error( `Invalid arguments for ${toolName}: ${errorMessages}. ` + `Expected format: ${JSON.stringify(schema._def, null, 2)}`, ); } logger.error(`Unexpected validation error for ${toolName}`, { toolName, error: error instanceof Error ? error.message : String(error), receivedArgs: args, }); throw new Error(`Validation failed for ${toolName}: ${error}`); } } /** * Internal capabilities provider that serves internal management tools */ export class InternalCapabilitiesProvider extends EventEmitter { private static instance: InternalCapabilitiesProvider | undefined; private configManager: AgentConfigManager; private flagManager: FlagManager; private isInitialized = false; private constructor() { super(); this.configManager = AgentConfigManager.getInstance(); this.flagManager = FlagManager.getInstance(); } /** * Get singleton instance */ public static getInstance(): InternalCapabilitiesProvider { if (!InternalCapabilitiesProvider.instance) { InternalCapabilitiesProvider.instance = new InternalCapabilitiesProvider(); } return InternalCapabilitiesProvider.instance; } /** * Initialize the internal provider */ public async initialize(): Promise<void> { if (this.isInitialized) { return; } this.isInitialized = true; // Emit ready event this.emit('ready'); } /** * Get all available internal tools based on current feature flags */ public getAvailableTools(): Tool[] { if (!this.isInitialized) { logger.warn('Internal capabilities provider not initialized'); return []; } const tools: Tool[] = []; // Check if internal tools are enabled in any way const internalToolsEnabled = this.flagManager.isToolEnabled('internalTools'); const internalToolsList = this.configManager.getInternalToolsList(); // Only proceed if internal tools are enabled (either by flag or custom list) if (internalToolsEnabled || internalToolsList.length > 0) { // Determine which tools to expose let enabledTools: string[] = []; if (internalToolsList.length > 0) { // Use custom tools list enabledTools = this.flagManager.getEnabledToolsFromList('internalTools', internalToolsList); } else { // Use all tools (existing behavior when --enable-internal-tools is used) enabledTools = this.flagManager.getEnabledTools('internalTools'); } // Add only the enabled tools for (const toolName of enabledTools) { switch (toolName) { // Discovery tools case 'search': tools.push(createSearchTool()); break; // registry case removed - mcp_registry tool has been deprecated and split into separate tools case 'registry_status': tools.push(createRegistryStatusTool()); break; case 'registry_info': tools.push(createRegistryInfoTool()); break; case 'registry_list': tools.push(createRegistryListTool()); break; case 'info': tools.push(createInfoTool()); break; // Installation tools case 'install': tools.push(createInstallTool()); break; case 'uninstall': tools.push(createUninstallTool()); break; case 'update': tools.push(createUpdateTool()); break; // Edit tools case 'edit': tools.push(createEditTool()); break; // Management tools case 'enable': tools.push(createEnableTool()); break; case 'disable': tools.push(createDisableTool()); break; case 'list': tools.push(createListTool()); break; case 'status': tools.push(createStatusTool()); break; case 'reload': tools.push(createReloadTool()); break; default: logger.warn(`Unknown internal tool: ${toolName}`); break; } } } return tools; } /** * Execute an internal tool */ public async executeTool(toolName: string, args: unknown): Promise<unknown> { if (!this.isInitialized) { throw new Error('Internal capabilities provider not initialized'); } let result: unknown; switch (toolName) { case 'mcp_search': { const validatedArgs = validateToolArgs(McpSearchToolSchema, args, toolName); result = await handleMcpSearch(validatedArgs); break; } // mcp_registry case removed - tool has been deprecated and split into separate tools case 'mcp_registry_status': { const validatedArgs = validateToolArgs(McpRegistryStatusSchema, args, toolName); result = await handleMcpRegistryStatus(validatedArgs); break; } case 'mcp_registry_info': { const validatedArgs = validateToolArgs(McpRegistryInfoSchema, args, toolName); result = await handleMcpRegistryInfo(validatedArgs); break; } case 'mcp_registry_list': { const validatedArgs = validateToolArgs(McpRegistryListSchema, args, toolName); result = await handleMcpRegistryList(validatedArgs); break; } case 'mcp_info': { const validatedArgs = validateToolArgs(McpInfoToolSchema, args, toolName); result = await handleMcpInfo(validatedArgs); break; } case 'mcp_install': { const validatedArgs = validateToolArgs(McpInstallToolSchema, args, toolName); result = await handleMcpInstall(validatedArgs); break; } case 'mcp_uninstall': { const validatedArgs = validateToolArgs(McpUninstallToolSchema, args, toolName); result = await handleMcpUninstall(validatedArgs); break; } case 'mcp_update': { const validatedArgs = validateToolArgs(McpUpdateToolSchema, args, toolName); result = await handleMcpUpdate(validatedArgs); break; } case 'mcp_edit': { const validatedArgs = validateToolArgs(McpEditToolSchema, args, toolName); result = await handleMcpEdit(validatedArgs); break; } case 'mcp_enable': { const validatedArgs = validateToolArgs(McpEnableToolSchema, args, toolName); result = await handleMcpEnable(validatedArgs); break; } case 'mcp_disable': { const validatedArgs = validateToolArgs(McpDisableToolSchema, args, toolName); result = await handleMcpDisable(validatedArgs); break; } case 'mcp_list': { const validatedArgs = validateToolArgs(McpListToolSchema, args, toolName); result = await handleMcpList(validatedArgs); break; } case 'mcp_status': { const validatedArgs = validateToolArgs(McpStatusToolSchema, args, toolName); result = await handleMcpStatus(validatedArgs); break; } case 'mcp_reload': { const validatedArgs = validateToolArgs(McpReloadToolSchema, args, toolName); result = await handleMcpReload(validatedArgs); break; } default: throw new Error(`Unknown internal tool: ${toolName}`); } // Return the structured result directly - let the MCP SDK handle wrapping return result; } /** * Cleanup resources */ public cleanup(): void { cleanupInternalToolHandlers(); this.removeAllListeners(); this.isInitialized = false; } public getAvailableResources(): Resource[] { if (!this.isInitialized) { logger.warn('Internal capabilities provider not initialized'); return []; } // Internal provider doesn't expose resources return []; } public getAvailablePrompts(): Prompt[] { if (!this.isInitialized) { logger.warn('Internal capabilities provider not initialized'); return []; } // Internal provider doesn't expose prompts return []; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1mcp-app/agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server