Skip to main content
Glama

simple-mcp-runner

by mjmorales
errors.go4.95 kB
// Package errors provides enhanced error types for the MCP server package errors import ( "errors" "fmt" "runtime" "strings" ) // ErrorType represents the type of error. type ErrorType string const ( // ErrorTypeValidation indicates a validation error. ErrorTypeValidation ErrorType = "validation" // ErrorTypeConfiguration indicates a configuration error. ErrorTypeConfiguration ErrorType = "configuration" // ErrorTypeExecution indicates a command execution error. ErrorTypeExecution ErrorType = "execution" // ErrorTypeTimeout indicates a timeout error. ErrorTypeTimeout ErrorType = "timeout" // ErrorTypePermission indicates a permission error. ErrorTypePermission ErrorType = "permission" // ErrorTypeNotFound indicates a not found error. ErrorTypeNotFound ErrorType = "not_found" // ErrorTypeInternal indicates an internal server error. ErrorTypeInternal ErrorType = "internal" ) // Error represents an enhanced error with additional context. type Error struct { Type ErrorType Message string Err error Context map[string]any Stack []string } // New creates a new error. func New(errType ErrorType, message string) *Error { return &Error{ Type: errType, Message: message, Context: make(map[string]any), Stack: captureStack(), } } // Wrap wraps an existing error. func Wrap(err error, errType ErrorType, message string) *Error { if err == nil { return nil } // If it's already our error type, preserve the original e := &Error{} if errors.As(err, &e) { e.Message = fmt.Sprintf("%s: %s", message, e.Message) return e } return &Error{ Type: errType, Message: message, Err: err, Context: make(map[string]any), Stack: captureStack(), } } // WithContext adds context to the error. func (e *Error) WithContext(key string, value any) *Error { if e == nil { return nil } e.Context[key] = value return e } // WithContextMap adds multiple context values. func (e *Error) WithContextMap(ctx map[string]any) *Error { if e == nil { return nil } for k, v := range ctx { e.Context[k] = v } return e } // Error implements the error interface. func (e *Error) Error() string { if e.Err != nil { return fmt.Sprintf("%s: %s: %v", e.Type, e.Message, e.Err) } return fmt.Sprintf("%s: %s", e.Type, e.Message) } // Unwrap returns the wrapped error. func (e *Error) Unwrap() error { return e.Err } // Is checks if the error is of a specific type. func (e *Error) Is(target error) bool { if target == nil { return false } if err, ok := target.(*Error); ok { return e.Type == err.Type } return errors.Is(e.Err, target) } // GetContext returns a context value. func (e *Error) GetContext(key string) (any, bool) { if e == nil || e.Context == nil { return nil, false } val, ok := e.Context[key] return val, ok } // StackTrace returns the stack trace as a string. func (e *Error) StackTrace() string { if e == nil || len(e.Stack) == 0 { return "" } return strings.Join(e.Stack, "\n") } // captureStack captures the current stack trace. func captureStack() []string { var stack []string for i := 2; i < 10; i++ { // Skip this function and the caller pc, file, line, ok := runtime.Caller(i) if !ok { break } fn := runtime.FuncForPC(pc) if fn == nil { break } // Skip runtime functions fnName := fn.Name() if strings.Contains(fnName, "runtime.") { continue } stack = append(stack, fmt.Sprintf("%s:%d %s", trimPath(file), line, fnName)) } return stack } // trimPath removes the full path for readability. func trimPath(path string) string { parts := strings.Split(path, "/") if len(parts) > 2 { return strings.Join(parts[len(parts)-2:], "/") } return path } // Helper functions for common error types // ValidationError creates a validation error. func ValidationError(message string, field string) *Error { return New(ErrorTypeValidation, message).WithContext("field", field) } // ConfigurationError creates a configuration error. func ConfigurationError(message string) *Error { return New(ErrorTypeConfiguration, message) } // ExecutionError creates an execution error. func ExecutionError(message string, command string) *Error { return New(ErrorTypeExecution, message).WithContext("command", command) } // TimeoutError creates a timeout error. func TimeoutError(message string, duration string) *Error { return New(ErrorTypeTimeout, message).WithContext("duration", duration) } // PermissionError creates a permission error. func PermissionError(message string, resource string) *Error { return New(ErrorTypePermission, message).WithContext("resource", resource) } // NotFoundError creates a not found error. func NotFoundError(message string, resource string) *Error { return New(ErrorTypeNotFound, message).WithContext("resource", resource) } // InternalError creates an internal error. func InternalError(message string) *Error { return New(ErrorTypeInternal, message) }

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/mjmorales/simple-mcp-runner'

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