moelove's picture
feat: init MCP server (#2)
24caae0 unverified
import { useState, useEffect, useCallback } from 'react';
// Custom hook for managing MCP servers and tools
function useMcp(mcpServers) {
const [serverTools, setServerTools] = useState({});
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
// Discover tools from all MCP servers
const discoverTools = useCallback(async () => {
console.log('Discovering MCP tools, servers:', mcpServers);
if (!mcpServers || mcpServers.length === 0) {
console.log('No MCP servers configured');
setServerTools({});
return;
}
setIsLoading(true);
setError(null);
const toolsMap = {};
try {
// Discover tools from each server in parallel
const discoveryPromises = mcpServers.map(async (server) => {
try {
const response = await fetch('/api/mcp/discover', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ server })
});
if (!response.ok) {
const errorText = await response.text();
console.error(`Error discovering tools for server ${server.name}:`, errorText);
return {
serverId: server.id,
tools: [],
error: `Failed to discover tools: ${response.status}`
};
}
return await response.json();
} catch (error) {
console.error(`Error discovering tools for server ${server.name}:`, error);
return {
serverId: server.id,
tools: [],
error: error.message
};
}
});
const results = await Promise.all(discoveryPromises);
// Organize tools by server
results.forEach(result => {
if (result && result.serverId) {
toolsMap[result.serverId] = {
tools: result.tools || [],
error: result.error || null
};
}
});
setServerTools(toolsMap);
} catch (error) {
console.error('Error discovering MCP tools:', error);
setError(error.message);
} finally {
setIsLoading(false);
}
}, [mcpServers]);
// Execute a tool on an MCP server
const executeTool = useCallback(async (serverId, toolName, parameters) => {
if (!mcpServers || !serverId || !toolName) {
throw new Error('Invalid tool execution parameters');
}
const server = mcpServers.find(s => s.id === serverId);
if (!server) {
throw new Error(`MCP server with ID ${serverId} not found`);
}
try {
const response = await fetch('/api/mcp/execute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
server,
tool: toolName,
parameters
})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Tool execution failed: ${response.status} - ${errorText}`);
}
return await response.json();
} catch (error) {
console.error(`Error executing tool ${toolName} on server ${server.name}:`, error);
throw error;
}
}, [mcpServers]);
// Discover tools when servers change
useEffect(() => {
console.log('MCP servers changed, discovering tools');
discoverTools();
}, [discoverTools]);
// Get all available tools across all servers
const getAllTools = useCallback(() => {
console.log('Getting all MCP tools, serverTools:', serverTools);
const allTools = [];
Object.entries(serverTools).forEach(([serverId, serverData]) => {
if (serverData.tools && serverData.tools.length > 0) {
const server = mcpServers.find(s => s.id === serverId);
if (server) {
serverData.tools.forEach(tool => {
allTools.push({
...tool,
serverId,
serverName: server.name
});
});
}
}
});
console.log('All MCP tools:', allTools);
return allTools;
}, [serverTools, mcpServers]);
return {
serverTools,
isLoading,
error,
discoverTools,
executeTool,
getAllTools
};
}
export default useMcp;