import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { ContainerManager } from '../managers/container.js';
import { ImageManager } from '../managers/image.js';
import { NetworkManager } from '../managers/network.js';
import { VolumeManager } from '../managers/volume.js';
import { SystemManager } from '../managers/system.js';
import { ExecManager } from '../managers/exec.js';
import { ComposeManager } from '../managers/compose.js';
import { DockerHubClient } from '../registries/dockerhub.js';
import { GHCRClient } from '../registries/ghcr.js';
import { getContainerTools, handleContainerTool } from './containers.js';
import { getImageTools, handleImageTool } from './images.js';
import { getNetworkTools, handleNetworkTool } from './networks.js';
import { getVolumeTools, handleVolumeTool } from './volumes.js';
import { getSystemTools, handleSystemTool } from './system.js';
import { getExecTools, handleExecTool } from './exec.js';
import { getComposeTools, handleComposeTool } from './compose.js';
import { getRegistryTools, handleRegistryTool } from './registries.js';
export function registerAllTools(
server: Server,
containerManager: ContainerManager,
imageManager: ImageManager,
networkManager: NetworkManager,
volumeManager: VolumeManager,
systemManager: SystemManager,
execManager: ExecManager,
composeManager: ComposeManager,
dockerHubClient: DockerHubClient,
ghcrClient: GHCRClient
) {
// Enable elicitation capability if client supports it
// The server will automatically negotiate capabilities with the client
// Collect ALL tools from all modules
const allTools = [
...getContainerTools(),
...getImageTools(),
...getNetworkTools(),
...getVolumeTools(),
...getSystemTools(),
...getExecTools(),
...getComposeTools(),
...getRegistryTools(),
];
// Set a single tools/list handler that returns ALL tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: allTools };
});
// Set a single tools/call handler that routes to the appropriate handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
// Try each handler in order
const handlers = [
() => handleContainerTool(name, args, containerManager),
() => handleImageTool(name, args, imageManager),
() => handleNetworkTool(name, args, networkManager),
() => handleVolumeTool(name, args, volumeManager, server),
() => handleSystemTool(name, args, systemManager),
() => handleExecTool(name, args, execManager),
() => handleComposeTool(name, args, composeManager),
() => handleRegistryTool(name, args, dockerHubClient, ghcrClient, imageManager),
];
for (const handler of handlers) {
try {
const result = await handler();
if (result !== null && result !== undefined) {
return result;
}
} catch (error: any) {
// If it's "Unknown tool", try next handler
if (error.message?.includes('Unknown tool')) {
continue;
}
// Otherwise, rethrow the error
throw error;
}
}
throw new Error(`Unknown tool: ${name}`);
});
}