package tools import ( "encoding/json" "fmt" "strings" "git.warky.dev/wdevs/amcs/internal/config" "git.warky.dev/wdevs/amcs/internal/mcperrors" "github.com/modelcontextprotocol/go-sdk/jsonrpc" ) func normalizeLimit(limit int, cfg config.SearchConfig) int { if limit <= 0 { return cfg.DefaultLimit } if limit > cfg.MaxLimit { return cfg.MaxLimit } return limit } func normalizeThreshold(value float64, fallback float64) float64 { if value <= 0 { return fallback } if value > 1 { return 1 } return value } const ( codeSessionRequired = mcperrors.CodeSessionRequired codeProjectRequired = mcperrors.CodeProjectRequired codeProjectNotFound = mcperrors.CodeProjectNotFound codeInvalidID = mcperrors.CodeInvalidID codeEntityNotFound = mcperrors.CodeEntityNotFound ) type mcpErrorData = mcperrors.Data func newMCPError(code int64, message string, data mcpErrorData) error { rpcErr := &jsonrpc.Error{ Code: code, Message: message, } payload, err := json.Marshal(data) if err != nil { return fmt.Errorf("marshal mcp error data: %w", err) } rpcErr.Data = payload return rpcErr } func errInvalidInput(message string) error { return newMCPError( jsonrpc.CodeInvalidParams, "invalid input: "+message, mcpErrorData{ Type: mcperrors.TypeInvalidInput, }, ) } func errRequiredField(field string) error { return newMCPError( jsonrpc.CodeInvalidParams, field+" is required", mcpErrorData{ Type: mcperrors.TypeInvalidInput, Field: field, Detail: "required", Hint: "provide " + field, }, ) } func errInvalidField(field string, message string, hint string) error { return newMCPError( jsonrpc.CodeInvalidParams, message, mcpErrorData{ Type: mcperrors.TypeInvalidInput, Field: field, Detail: "invalid", Hint: hint, }, ) } func errOneOfRequired(fields ...string) error { return newMCPError( jsonrpc.CodeInvalidParams, joinFields(fields)+" is required", mcpErrorData{ Type: mcperrors.TypeInvalidInput, Fields: fields, Detail: "one_of_required", Hint: "provide one of: " + strings.Join(fields, ", "), }, ) } func errMutuallyExclusiveFields(fields ...string) error { return newMCPError( jsonrpc.CodeInvalidParams, "provide "+joinFields(fields)+", not both", mcpErrorData{ Type: mcperrors.TypeInvalidInput, Fields: fields, Detail: "mutually_exclusive", Hint: "provide only one of: " + strings.Join(fields, ", "), }, ) } func errEntityNotFound(entity string, field string, value string) error { return newMCPError( codeEntityNotFound, entity+" not found", mcpErrorData{ Type: mcperrors.TypeEntityNotFound, Entity: entity, Field: field, Value: value, Detail: "not_found", }, ) } func joinFields(fields []string) string { switch len(fields) { case 0: return "field" case 1: return fields[0] case 2: return fields[0] + " or " + fields[1] default: return strings.Join(fields[:len(fields)-1], ", ") + ", or " + fields[len(fields)-1] } }