Skip to main content
Glama
ToolCalls.tsx9.42 kB
import React from 'react' import { useQuery } from '@tanstack/react-query' import { Terminal, Clock, AlertCircle, CheckCircle, Image } from 'lucide-react' import { format } from 'date-fns' const fetchLogs = async () => { const response = await fetch('/logs?limit=50') if (!response.ok) throw new Error('Failed to fetch logs') return response.json() } export default function ToolCalls() { const { data: logsData, isLoading } = useQuery({ queryKey: ['logs'], queryFn: fetchLogs, refetchInterval: 2000 }) if (isLoading) { return ( <div className="px-4 sm:px-6 lg:px-8"> <div className="animate-pulse"> <div className="h-8 bg-gray-300 dark:bg-gray-700 rounded w-1/4 mb-4"></div> <div className="space-y-3"> {[...Array(5)].map((_, i) => ( <div key={i} className="h-24 bg-gray-300 dark:bg-gray-700 rounded"></div> ))} </div> </div> </div> ) } const logs = logsData?.logs || [] return ( <div className="px-4 sm:px-6 lg:px-8"> <div className="sm:flex sm:items-center"> <div className="sm:flex-auto"> <h1 className="text-2xl font-semibold text-gray-900 dark:text-white">Tool Calls</h1> <p className="mt-2 text-sm text-gray-700 dark:text-gray-300"> Monitor all tool calls made to the MCP server in real-time. </p> </div> </div> {/* Stats */} <div className="mt-8 grid grid-cols-1 gap-5 sm:grid-cols-3"> <div className="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg border dark:border-gray-700"> <div className="p-5"> <div className="flex items-center"> <div className="flex-shrink-0"> <CheckCircle className="w-6 h-6 text-green-600" /> </div> <div className="ml-5 w-0 flex-1"> <dl> <dt className="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"> Successful Calls </dt> <dd className="text-lg font-semibold text-gray-900 dark:text-white"> {logs.filter((log: any) => !log.error).length} </dd> </dl> </div> </div> </div> </div> <div className="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg border dark:border-gray-700"> <div className="p-5"> <div className="flex items-center"> <div className="flex-shrink-0"> <AlertCircle className="w-6 h-6 text-red-600" /> </div> <div className="ml-5 w-0 flex-1"> <dl> <dt className="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"> Failed Calls </dt> <dd className="text-lg font-semibold text-gray-900 dark:text-white"> {logs.filter((log: any) => log.error).length} </dd> </dl> </div> </div> </div> </div> <div className="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg border dark:border-gray-700"> <div className="p-5"> <div className="flex items-center"> <div className="flex-shrink-0"> <Clock className="w-6 h-6 text-blue-600" /> </div> <div className="ml-5 w-0 flex-1"> <dl> <dt className="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"> Avg Duration </dt> <dd className="text-lg font-semibold text-gray-900 dark:text-white"> {logs.length > 0 ? Math.round(logs.reduce((sum: number, log: any) => sum + log.duration_ms, 0) / logs.length) : 0}ms </dd> </dl> </div> </div> </div> </div> </div> {/* Tool Calls List */} <div className="mt-8"> {logs.length > 0 ? ( <div className="bg-white dark:bg-gray-800 shadow overflow-hidden sm:rounded-lg border dark:border-gray-700"> <div className="divide-y divide-gray-200 dark:divide-gray-700"> {logs.map((log: any, index: number) => ( <div key={log.id || index} className="px-6 py-4"> <div className="flex items-start justify-between"> <div className="flex items-start space-x-4 min-w-0 flex-1"> <div className="flex-shrink-0"> {log.error ? ( <div className="w-8 h-8 rounded-full bg-red-100 dark:bg-red-900/20 flex items-center justify-center"> <AlertCircle className="w-4 h-4 text-red-600" /> </div> ) : ( <div className="w-8 h-8 rounded-full bg-green-100 dark:bg-green-900/20 flex items-center justify-center"> <CheckCircle className="w-4 h-4 text-green-600" /> </div> )} </div> <div className="min-w-0 flex-1"> <div className="flex items-center space-x-2"> <p className="text-sm font-medium text-gray-900 dark:text-white truncate"> {log.tool_name} </p> {log.images?.length > 0 && ( <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-300"> <Image className="w-3 h-3 mr-1" /> {log.images.length} image{log.images.length > 1 ? 's' : ''} </span> )} </div> <div className="mt-1 flex items-center text-sm text-gray-500 dark:text-gray-400 space-x-4"> <span>{format(new Date(log.timestamp), 'MMM d, h:mm:ss a')}</span> <span>{log.duration_ms}ms</span> {log.session_id && ( <span className="font-mono text-xs"> Session: {log.session_id.slice(0, 8)}... </span> )} </div> {log.error && ( <div className="mt-2 text-sm text-red-600 dark:text-red-400"> <p className="font-medium">{log.error.code}: {log.error.message}</p> {log.error.details && ( <pre className="mt-1 text-xs bg-red-50 dark:bg-red-900/10 p-2 rounded overflow-x-auto"> {JSON.stringify(log.error.details, null, 2)} </pre> )} </div> )} {/* Parameters */} {log.params && Object.keys(log.params).length > 0 && ( <details className="mt-2"> <summary className="text-xs font-medium text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-300"> Parameters </summary> <pre className="mt-1 text-xs bg-gray-50 dark:bg-gray-900 p-2 rounded overflow-x-auto"> {JSON.stringify(log.params, null, 2)} </pre> </details> )} {/* Result */} {log.result && !log.error && ( <details className="mt-2"> <summary className="text-xs font-medium text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-300"> Result </summary> <pre className="mt-1 text-xs bg-gray-50 dark:bg-gray-900 p-2 rounded overflow-x-auto"> {JSON.stringify(log.result, null, 2)} </pre> </details> )} </div> </div> </div> </div> ))} </div> </div> ) : ( <div className="text-center py-12"> <div className="w-12 h-12 mx-auto bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center mb-4"> <Terminal className="w-6 h-6 text-gray-400" /> </div> <h3 className="text-sm font-medium text-gray-900 dark:text-white mb-1">No tool calls yet</h3> <p className="text-sm text-gray-500 dark:text-gray-400"> Tool call logs will appear here as they are made. </p> </div> )} </div> </div> ) }

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/JacobFV/mcp-fullstack'

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