UNPKG

@mcp-shark/mcp-shark

Version:

Aggregate multiple Model Context Protocol (MCP) servers into a single unified interface with a powerful monitoring UI. Prov deep visibility into every request and response.

84 lines (73 loc) 3.11 kB
import { serializeBigInt } from '../utils/serialization.js'; import { queryRequests } from 'mcp-shark-common/db/query.js'; export function createStatisticsRoutes(db) { const router = {}; router.getStatistics = (req, res) => { try { // Sanitize search parameter - convert empty strings to null let search = req.query.search; if (search !== undefined && search !== null) { search = String(search).trim(); search = search.length > 0 ? search : null; } else { search = null; } // Build filters object matching the requests route const filters = { sessionId: (req.query.sessionId && String(req.query.sessionId).trim()) || null, direction: (req.query.direction && String(req.query.direction).trim()) || null, method: (req.query.method && String(req.query.method).trim()) || null, jsonrpcMethod: (req.query.jsonrpcMethod && String(req.query.jsonrpcMethod).trim()) || null, statusCode: req.query.statusCode ? parseInt(req.query.statusCode) : null, jsonrpcId: (req.query.jsonrpcId && String(req.query.jsonrpcId).trim()) || null, search: search, serverName: (req.query.serverName && String(req.query.serverName).trim()) || null, startTime: req.query.startTime ? BigInt(req.query.startTime) : null, endTime: req.query.endTime ? BigInt(req.query.endTime) : null, limit: 1000000, // Large limit for accurate statistics offset: 0, }; // Remove undefined values to avoid issues Object.keys(filters).forEach((key) => { if (filters[key] === undefined) { filters[key] = null; } }); // Get all filtered requests (no limit for accurate statistics) const allRequests = queryRequests(db, filters); // Calculate statistics from filtered requests const totalPackets = allRequests.length; const totalRequests = allRequests.filter((r) => r.direction === 'request').length; const totalResponses = allRequests.filter((r) => r.direction === 'response').length; const totalErrors = allRequests.filter((r) => { if (r.direction === 'response') { const statusCode = r.status_code || r.status; return ( statusCode >= 400 || (r.body_json && typeof r.body_json === 'object' && r.body_json.error) ); } return false; }).length; // Get unique sessions const uniqueSessions = new Set(); allRequests.forEach((r) => { if (r.session_id) { uniqueSessions.add(r.session_id); } }); const stats = { total_packets: totalPackets, total_requests: totalRequests, total_responses: totalResponses, total_errors: totalErrors, unique_sessions: uniqueSessions.size, }; res.json(serializeBigInt(stats)); } catch (error) { console.error('Error in getStatistics:', error); res.status(500).json({ error: 'Failed to get statistics', details: error.message }); } }; return router; }