Skip to main content
Glama
index.ts7.73 kB
/** * @file Example Unified Tools * @description Sample tools demonstrating the unified tool system */ import { z } from 'zod'; import { UnifiedToolDefinition, ToolContext, ToolResult } from '../base.js'; import { routeRequest } from '../../../routing/index.js'; import { chatContextBuilder } from '../../../services/chat/ChatContextBuilder.js'; import { db } from '../../../db/postgres.js'; import { logger } from '../../../logging/logger.js'; /** * AI Chat Tool - Routes chat requests to appropriate LLM */ export const aiChatTool: UnifiedToolDefinition< { message: string; conversationId?: string; model?: string; temperature?: number; }, { response: string; model: string; tokensUsed: number; cost: number; } > = { name: 'ai.chat', description: 'Send a chat message to AI and get a response with automatic model routing', category: 'ai', inputSchema: z.object({ message: z.string().min(1).describe('The message to send to AI'), conversationId: z.string().optional().describe('Conversation ID for context'), model: z.string().optional().describe('Specific model to use (optional)'), temperature: z.number().min(0).max(2).optional().describe('Temperature for response generation'), }), handler: async (input, context): Promise<ToolResult> => { try { // Build context if conversation ID provided let messages = [{ role: 'user' as const, content: input.message }]; if (input.conversationId) { const contextResult = await chatContextBuilder.buildContext({ conversationId: input.conversationId, currentMessages: messages, maxTokens: 4096, }); messages = contextResult.messages; } // Route request const result = await routeRequest({ task: input.message, messages, model: input.model, temperature: input.temperature, }); return { success: true, data: { response: result.text, model: result.modelUsed, tokensUsed: result.tokensUsed || 0, cost: result.cost || 0, }, metadata: { tokensUsed: result.tokensUsed, cost: result.cost, }, }; } catch (error) { logger.error('AI chat tool error', { error }); return { success: false, error: { code: 'AI_CHAT_ERROR', message: error instanceof Error ? error.message : 'Failed to process chat', }, }; } }, metadata: { requiresAuth: false, rateLimit: 60, // 60 calls per minute estimatedDuration: 3000, tags: ['ai', 'chat', 'llm'], examples: [ { input: { message: 'Explain quantum computing in simple terms', }, description: 'Simple chat without context', }, ], }, }; /** * Database Query Tool */ export const dbQueryTool: UnifiedToolDefinition< { query: string; params?: any[]; }, { rows: any[]; rowCount: number; } > = { name: 'db.query', description: 'Execute a SQL query on the database', category: 'database', inputSchema: z.object({ query: z.string().min(1).describe('SQL query to execute'), params: z.array(z.any()).optional().describe('Query parameters'), }), handler: async (input, context): Promise<ToolResult> => { try { const result = await db.query(input.query, input.params); return { success: true, data: { rows: result?.rows || [], rowCount: result?.rows?.length || 0, }, }; } catch (error) { logger.error('Database query error', { error, query: input.query }); return { success: false, error: { code: 'DB_QUERY_ERROR', message: error instanceof Error ? error.message : 'Query failed', }, }; } }, metadata: { requiresAuth: true, rateLimit: 100, estimatedDuration: 500, tags: ['database', 'query'], }, }; /** * Context Stats Tool - Get conversation context statistics */ export const contextStatsTool: UnifiedToolDefinition< { conversationId: string; }, { totalMessages: number; totalTokens: number; summarizedMessages: number; messagesWithEmbeddings: number; hasSummary: boolean; } > = { name: 'chat.context_stats', description: 'Get statistics about a conversation context', category: 'chat', inputSchema: z.object({ conversationId: z.string().describe('Conversation ID to get stats for'), }), handler: async (input, context): Promise<ToolResult> => { try { const result = await db.query<{ total_messages: number; total_tokens: number; summarized_messages: number; messages_with_embeddings: number; has_summary: boolean; }>( `SELECT COUNT(m.id) as total_messages, COALESCE(SUM(m.token_estimate), 0) as total_tokens, COUNT(CASE WHEN m.is_summarized THEN 1 END) as summarized_messages, COUNT(CASE WHEN m.embedding IS NOT NULL THEN 1 END) as messages_with_embeddings, c.summary IS NOT NULL as has_summary FROM messages m LEFT JOIN conversations c ON c.id = m.conversation_id WHERE m.conversation_id = $1 GROUP BY c.summary`, [input.conversationId] ); if (!result || result.rows.length === 0) { return { success: false, error: { code: 'CONVERSATION_NOT_FOUND', message: 'Conversation not found', }, }; } const row = result.rows[0]; return { success: true, data: { totalMessages: Number(row.total_messages), totalTokens: Number(row.total_tokens), summarizedMessages: Number(row.summarized_messages), messagesWithEmbeddings: Number(row.messages_with_embeddings), hasSummary: Boolean(row.has_summary), }, }; } catch (error) { logger.error('Context stats error', { error, conversationId: input.conversationId }); return { success: false, error: { code: 'STATS_ERROR', message: error instanceof Error ? error.message : 'Failed to get stats', }, }; } }, metadata: { requiresAuth: false, rateLimit: 100, estimatedDuration: 200, tags: ['chat', 'context', 'stats'], }, }; /** * Export all example tools */ export const exampleTools = [ aiChatTool, dbQueryTool, contextStatsTool, ];

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/babasida246/ai-mcp-gateway'

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