Files
mcphub/src/controllers/toolController.ts

108 lines
2.8 KiB
TypeScript

import { Request, Response } from 'express';
import { ApiResponse } from '../types/index.js';
import { handleCallToolRequest, getServerByName } from '../services/mcpService.js';
import { convertParametersToTypes } from '../utils/parameterConversion.js';
import { getNameSeparator } from '../config/index.js';
/**
* Interface for tool call request
*/
export interface ToolCallRequest {
toolName: string;
arguments?: Record<string, any>;
}
/**
* Interface for tool search request
*/
export interface ToolSearchRequest {
query: string;
limit?: number;
}
/**
* Interface for tool call result
*/
interface ToolCallResult {
content?: Array<{
type: string;
text?: string;
[key: string]: any;
}>;
isError?: boolean;
[key: string]: any;
}
/**
* Call a specific tool with given arguments
*/
export const callTool = async (req: Request, res: Response): Promise<void> => {
try {
const { server } = req.params;
const { toolName, arguments: toolArgs = {} } = req.body as ToolCallRequest;
if (!toolName) {
res.status(400).json({
success: false,
message: 'toolName is required',
});
return;
}
// Get the server info to access the tool's input schema
const serverInfo = getServerByName(server);
let inputSchema: Record<string, any> = {};
if (serverInfo) {
// Find the tool in the server's tools list
const fullToolName = `${server}${getNameSeparator()}${toolName}`;
const tool = serverInfo.tools.find(
(t: any) => t.name === fullToolName || t.name === toolName,
);
if (tool && tool.inputSchema) {
inputSchema = tool.inputSchema as Record<string, any>;
}
}
// Convert parameters to proper types based on the tool's input schema
const convertedArgs = convertParametersToTypes(toolArgs, inputSchema);
// Create a mock request structure for handleCallToolRequest
const mockRequest = {
params: {
name: 'call_tool',
arguments: {
toolName,
arguments: convertedArgs,
},
},
};
const extra = {
sessionId: req.headers['x-session-id'] || 'api-session',
server: server || undefined,
headers: req.headers, // Include request headers for passthrough
};
const result = (await handleCallToolRequest(mockRequest, extra)) as ToolCallResult;
const response: ApiResponse = {
success: true,
data: {
content: result.content || [],
toolName,
arguments: convertedArgs,
},
};
res.json(response);
} catch (error) {
console.error('Error calling tool:', error);
res.status(500).json({
success: false,
message: 'Failed to call tool',
error: error instanceof Error ? error.message : 'Unknown error occurred',
});
}
};