Skip to main content
Glama
buildwithgrove

Grove's MCP Server for Pocket Network

enhanced-safety-checks.ts7.13 kB
/** * Enhanced Safety Checks for Pocket Network MCP * Prevents context overflow and session crashes from large responses */ export interface SafetyCheckResult { safe: boolean; reason?: string; suggestion?: string; } export interface SafetyConfig { maxTransactionsPerBlock: number; maxBlockRange: number; maxResponseSizeEstimate: number; // in KB allowBlocksWithTransactions: boolean; } export const DEFAULT_SAFETY_CONFIG: SafetyConfig = { maxTransactionsPerBlock: 10, maxBlockRange: 10, maxResponseSizeEstimate: 500, // 500 KB max response allowBlocksWithTransactions: false, // CRITICAL: Block by default }; /** * Dangerous RPC methods that can cause context overflow */ const DANGEROUS_METHODS = new Set([ 'eth_getBlockByNumber', 'eth_getBlockByHash', 'eth_getLogs', 'eth_getTransactionReceipt', // Can be large with many logs 'debug_traceTransaction', // Extremely large responses 'trace_block', // Traces entire block 'trace_transaction', ]); /** * Methods that require special handling for address transaction history */ const TRANSACTION_HISTORY_PATTERNS = [ /get.*transaction.*for.*address/i, /transaction.*history/i, /recent.*transactions/i, /last.*transaction/i, /latest.*transaction.*on.*address/i, /address.*transactions/i, ]; /** * Check if a natural language query is asking for transaction history */ export function isTransactionHistoryQuery(query: string): boolean { return TRANSACTION_HISTORY_PATTERNS.some(pattern => pattern.test(query)); } /** * Check if an RPC method is dangerous */ export function isDangerousMethod(method: string): boolean { return DANGEROUS_METHODS.has(method); } /** * Validate block query safety */ export function checkBlockQuery( method: string, params: any[], config: SafetyConfig = DEFAULT_SAFETY_CONFIG ): SafetyCheckResult { // Check if requesting full transactions if (method === 'eth_getBlockByNumber' || method === 'eth_getBlockByHash') { const includeTransactions = params[1] === true; if (includeTransactions && !config.allowBlocksWithTransactions) { return { safe: false, reason: 'Requesting blocks with full transactions is disabled to prevent context overflow', suggestion: 'Use eth_getBlockByNumber with false parameter to get block without transactions, or query specific transactions by hash' }; } if (includeTransactions) { return { safe: false, reason: 'Blocks can contain 100+ transactions, causing session crashes', suggestion: 'Query specific transactions by hash instead, or use a block explorer API' }; } } return { safe: true }; } /** * Validate log query safety */ export function checkLogQuery( params: any[], config: SafetyConfig = DEFAULT_SAFETY_CONFIG ): SafetyCheckResult { if (!params[0]) { return { safe: true }; } const filter = params[0]; const fromBlock = filter.fromBlock; const toBlock = filter.toBlock || 'latest'; // Check block range if (fromBlock && toBlock && toBlock !== 'latest') { try { const from = typeof fromBlock === 'string' ? parseInt(fromBlock, 16) : fromBlock; const to = typeof toBlock === 'string' ? parseInt(toBlock, 16) : toBlock; const range = to - from; if (range > config.maxBlockRange) { return { safe: false, reason: `Block range ${range} exceeds maximum ${config.maxBlockRange}`, suggestion: 'Reduce the block range or use pagination' }; } } catch (e) { // If we can't parse, be conservative return { safe: false, reason: 'Unable to validate block range safety', suggestion: 'Specify explicit numeric block ranges' }; } } // Warn about unrestricted queries if (!filter.address && !filter.topics) { return { safe: false, reason: 'Unrestricted log queries can return massive amounts of data', suggestion: 'Add address or topic filters to limit results' }; } return { safe: true }; } /** * Main safety check for RPC calls */ export function validateRPCCall( blockchain: string, method: string, params: any[], config: SafetyConfig = DEFAULT_SAFETY_CONFIG ): SafetyCheckResult { // Check for dangerous methods if (isDangerousMethod(method)) { if (method.startsWith('eth_getBlock')) { return checkBlockQuery(method, params, config); } if (method === 'eth_getLogs') { return checkLogQuery(params, config); } // Other dangerous methods - block by default return { safe: false, reason: `Method ${method} can return extremely large responses`, suggestion: 'Use safer alternatives or fetch data from a block explorer API' }; } return { safe: true }; } /** * Check natural language query safety */ export function validateNaturalLanguageQuery( query: string, config: SafetyConfig = DEFAULT_SAFETY_CONFIG ): SafetyCheckResult { // Check for transaction history queries if (isTransactionHistoryQuery(query)) { return { safe: false, reason: 'Transaction history queries require fetching multiple blocks with full transaction data, which causes context overflow', suggestion: 'Instead:\n' + ' • Query a specific transaction by hash if you know it\n' + ' • Use a block explorer API (Etherscan, etc.) for transaction history\n' + ' • Ask for current balance or state instead of history' }; } // Check for patterns that might lead to large responses const dangerousPatterns = [ /get all transactions/i, /list all/i, /fetch all/i, /every transaction/i, /all.*logs/i, ]; for (const pattern of dangerousPatterns) { if (pattern.test(query)) { return { safe: false, reason: 'Query requests potentially unbounded data', suggestion: 'Add specific limits, filters, or time ranges to your query' }; } } return { safe: true }; } /** * Estimate response size for a query (conservative) */ export function estimateResponseSize( method: string, params: any[] ): number { // Size estimates in KB const estimates: Record<string, number> = { 'eth_getBlockByNumber': params[1] === true ? 500 : 5, 'eth_getBlockByHash': params[1] === true ? 500 : 5, 'eth_getLogs': 200, // Very conservative 'eth_getTransactionReceipt': 10, 'debug_traceTransaction': 1000, 'trace_block': 2000, }; return estimates[method] || 5; // Default to 5KB for unknown methods } /** * Safe alternatives for common dangerous queries */ export const SAFE_ALTERNATIVES = { 'get_last_transaction': 'Use a block explorer API like Etherscan to fetch recent transactions for an address', 'get_transaction_history': 'Use etherscan.io API or similar indexing service', 'get_all_logs': 'Add specific address and topic filters, limit block range to < 10 blocks', 'get_block_with_transactions': 'Get block metadata only, then query specific transactions by hash', };

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/buildwithgrove/mcp-pocket'

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