Files
OllaHub/hooks/use-mcp-tools.ts
Evandro Fonseca Junior 8834ef2b4f feat: update dependencies and enhance chat functionality
- Added new Radix UI components including checkbox, label, popover, slider, switch, and tooltip to improve UI interactions.
- Integrated react-syntax-highlighter for better code rendering in chat messages.
- Updated package.json and pnpm-lock.yaml to include new dependencies and ensure compatibility.
- Enhanced chat input to support web search toggling, improving user experience during message composition.
- Implemented auto-saving of chat sessions and improved session management features.
- Refactored chat message rendering to clean up metadata and improve display quality.
2025-11-20 04:26:35 -03:00

134 lines
4.9 KiB
TypeScript

'use client';
import { useState, useEffect, useCallback } from 'react';
import { invoke } from '@tauri-apps/api/core';
export interface McpTool {
name: string;
description: string;
input_schema?: any;
}
export interface McpToolInfo {
server_name: string;
tool: McpTool;
}
export function useMcpTools() {
const [tools, setTools] = useState<McpToolInfo[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const loadTools = useCallback(async () => {
try {
setIsLoading(true);
setError(null);
const allTools = await invoke<McpToolInfo[]>('get_all_mcp_tools');
setTools(allTools);
} catch (err) {
console.error('Failed to load MCP tools:', err);
setError(err instanceof Error ? err.message : 'Failed to load MCP tools');
setTools([]);
} finally {
setIsLoading(false);
}
}, []);
useEffect(() => {
loadTools();
// Refresh tools every 30 seconds
const interval = setInterval(() => {
loadTools();
}, 30000);
return () => clearInterval(interval);
}, [loadTools]);
// Generate tools context for prompt injection
const generateToolsContext = useCallback((availableTools: McpToolInfo[], selectedServers?: string[]): string => {
// Filter tools by selected servers if provided
let filteredTools = availableTools;
if (selectedServers && selectedServers.length > 0) {
filteredTools = availableTools.filter(tool => selectedServers.includes(tool.server_name));
}
if (filteredTools.length === 0) {
return '';
}
let context = '\n\n## Ferramentas MCP Disponíveis\n\n';
const header = selectedServers && selectedServers.length > 0
? `Você está usando os servidores MCP selecionados: ${selectedServers.join(', ')}.\n`
: 'Você tem acesso aos servidores MCP listados abaixo.\n';
context += `${header}\n`;
context += '### REGRAS OBRIGATÓRIAS PARA MCP:\n\n';
context += '1. **PRIORIZE RESULTADOS DE MCP**: Se você vir mensagens anteriores marcadas com `[MCP servidor/ferramenta]`, USE-AS como base da sua resposta.\n';
context += '2. **IDENTIFIQUE FONTES**: Quando há dados de MCP disponíveis, cite-os explicitamente (ex: "De acordo com a busca realizada...").\n';
context += '3. **TRATE ERROS**: Se MCP retornou erro (mensagens com ⚠️), informe ao usuário sobre a limitação de forma clara.\n';
context += '4. **SOLICITE FERRAMENTAS**: Use o formato `<tool_name>(arg1=valor1, arg2=valor2)` para solicitar execução de ferramentas.\n';
context += '5. **PROIBIDO**: NUNCA gere blocos `<metadata>`, JSON oculto ou texto como "Metadados:". Apenas texto visível.\n\n';
context += '**Nota**: O sistema executa MCPs automaticamente antes de você receber a mensagem do usuário. Verifique sempre se há resultados MCP nas mensagens anteriores.\n\n';
// Group tools by server
const toolsByServer = new Map<string, McpTool[]>();
for (const toolInfo of filteredTools) {
if (!toolsByServer.has(toolInfo.server_name)) {
toolsByServer.set(toolInfo.server_name, []);
}
toolsByServer.get(toolInfo.server_name)!.push(toolInfo.tool);
}
// Format tools for each server
for (const [serverName, serverTools] of toolsByServer.entries()) {
context += `### Servidor: ${serverName}\n\n`;
for (const tool of serverTools) {
context += `- **${tool.name}**: ${tool.description}\n`;
// Add input schema info if available
if (tool.input_schema) {
const schema = tool.input_schema;
if (schema.properties) {
context += ` - Parâmetros: `;
const params: string[] = [];
for (const [key, value] of Object.entries(schema.properties)) {
const prop = value as any;
params.push(`${key} (${prop.type || 'any'})`);
}
context += params.join(', ') + '\n';
}
}
context += '\n';
}
}
context += '### Como responder quando há dados MCP:\n\n';
context += '1. Verifique se há mensagens com `[MCP ...]` no histórico recente\n';
context += '2. Analise os dados retornados (mesmo que sejam erros)\n';
context += '3. Baseie sua resposta PRINCIPALMENTE nos dados MCP\n';
context += '4. Complemente com seu conhecimento apenas se necessário\n';
context += '5. Apresente tudo em texto limpo, sem metadados ou JSON oculto\n\n';
context += '**Lembre-se**: Resultados MCP são dados em tempo real e devem ter prioridade sobre seu conhecimento interno.\n';
return context;
}, []);
// Get tools context string for prompt injection
const getToolsContext = useCallback((selectedServers?: string[]): string => {
return generateToolsContext(tools, selectedServers);
}, [tools, generateToolsContext]);
return {
tools,
isLoading,
error,
loadTools,
generateToolsContext,
getToolsContext,
};
}