toInt64 converts a value to int64, handling both float64 and string representations. Some MCP clients send numeric values as strings. It rejects NaN, ±Inf, fractional values, and values that lose precision in the float64→int64 conversion.
(val any)
| 73 | // Some MCP clients send numeric values as strings. It rejects NaN, ±Inf, |
| 74 | // fractional values, and values that lose precision in the float64→int64 conversion. |
| 75 | func toInt64(val any) (int64, error) { |
| 76 | var f float64 |
| 77 | switch v := val.(type) { |
| 78 | case float64: |
| 79 | f = v |
| 80 | case string: |
| 81 | var err error |
| 82 | f, err = strconv.ParseFloat(v, 64) |
| 83 | if err != nil { |
| 84 | return 0, fmt.Errorf("invalid numeric value: %s", v) |
| 85 | } |
| 86 | default: |
| 87 | return 0, fmt.Errorf("expected number, got %T", val) |
| 88 | } |
| 89 | if math.IsNaN(f) || math.IsInf(f, 0) { |
| 90 | return 0, fmt.Errorf("non-finite numeric value") |
| 91 | } |
| 92 | if f != math.Trunc(f) { |
| 93 | return 0, fmt.Errorf("non-integer numeric value: %v", f) |
| 94 | } |
| 95 | result := int64(f) |
| 96 | // Check round-trip to detect precision loss for large int64 values |
| 97 | if float64(result) != f { |
| 98 | return 0, fmt.Errorf("numeric value %v is too large to fit in int64", f) |
| 99 | } |
| 100 | return result, nil |
| 101 | } |
| 102 | |
| 103 | // RequiredParam is a helper function that can be used to fetch a requested parameter from the request. |
| 104 | // It does the following checks: |