Skip to main content
Glama

SFCC Development MCP Server

by taurgis
log-tool-utils.ts4.18 kB
import { ToolArguments } from '../core/handlers/base-handler.js'; import { SFCCLogClient } from '../clients/log-client.js'; import { LogLevel, isValidLogLevel } from './log-tool-constants.js'; /** * Configuration interface for tool dispatch */ export interface ToolSpec<T = any> { validate?: (args: ToolArguments, toolName: string) => void; defaults?: (args: ToolArguments) => Record<string, any>; exec: (args: ToolArguments, client: SFCCLogClient) => Promise<T>; logMessage: (args: ToolArguments) => string; } /** * Validation utilities for log tools */ export class LogToolValidators { static validateLogLevel(level: string, toolName: string): void { if (!isValidLogLevel(level)) { throw new Error(`Invalid log level '${level}' for ${toolName}. Valid levels: ${Object.values(LogLevel).join(', ')}`); } } static validateLimit(limit: number | undefined, toolName: string): void { if (limit !== undefined) { // Validate type first if (typeof limit !== 'number' || isNaN(limit)) { throw new Error(`Invalid limit '${limit}' for ${toolName}. Must be a valid number`); } // Then validate range if (limit <= 0 || limit > 1000) { throw new Error(`Invalid limit '${limit}' for ${toolName}. Must be between 1 and 1000`); } } } static validateMaxBytes(maxBytes: number | undefined, toolName: string): void { if (maxBytes !== undefined) { // Validate type first if (typeof maxBytes !== 'number' || isNaN(maxBytes)) { throw new Error(`Invalid maxBytes '${maxBytes}' for ${toolName}. Must be a valid number`); } // Then validate range if (maxBytes <= 0 || maxBytes > 10_000_000) { // 10MB limit throw new Error(`Invalid maxBytes '${maxBytes}' for ${toolName}. Must be between 1 and 10,000,000`); } } } static validateFilename(filename: string, toolName: string): void { if (!filename || filename.trim().length === 0) { throw new Error(`Filename is required for ${toolName}`); } // Prevent path traversal if (filename.includes('..') || filename.includes('\\')) { throw new Error(`Invalid filename '${filename}' for ${toolName}. Path traversal not allowed`); } } } /** * Message formatting utilities for log tools */ export class LogMessageFormatter { static formatLatestLogs(level: string, limit: number, date?: string): string { return `Fetching latest ${level} logs limit=${limit} date=${date ?? 'today'}`; } static formatSummarizeLogs(date?: string): string { return `Summarizing logs for date ${date ?? 'today'}`; } static formatSearchLogs(pattern: string, logLevel?: string, limit?: number, _date?: string): string { // For backward compatibility with existing tests, don't include date in message return `Searching logs pattern="${pattern}" level=${logLevel ?? 'all'} limit=${limit ?? 20}`; } static formatListLogFiles(): string { return 'Listing log files'; } static formatGetLogFileContents(filename: string, maxBytes?: number, tailOnly?: boolean): string { return `Reading log file contents: ${filename} (maxBytes=${maxBytes ?? 'default'}, tailOnly=${tailOnly ?? false})`; } static formatJobLogMessage(operation: string, params: Record<string, any>): string { const paramStr = Object.entries(params) .filter(([_, value]) => value !== undefined) .map(([key, value]) => `${key}=${value}`) .join(' '); return paramStr ? `${operation} ${paramStr}` : operation; } } /** * Utility functions for argument processing */ export class LogToolUtils { static applyDefaults(spec: ToolSpec, args: ToolArguments): ToolArguments { if (!spec.defaults) { return args; } const defaults = spec.defaults(args); return { ...args, ...defaults }; } static createValidatedArgs(spec: ToolSpec, args: ToolArguments, toolName: string): ToolArguments { // Apply defaults first const processedArgs = LogToolUtils.applyDefaults(spec, args); // Validate if validator exists if (spec.validate) { spec.validate(processedArgs, toolName); } return processedArgs; } }

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/taurgis/sfcc-dev-mcp'

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