Classify maps a transport-level error (stdio MCP, remote MCP, LSP) to one of the typed sentinels in this package, wrapping it so errors.Is matches both the sentinel and the original error. Already-classified errors (any wrapping a sentinel via errors.Is) are returned unchanged. Unknown errors are r
(err error)
| 21 | // Substring matching is used as a last resort because some upstream SDKs |
| 22 | // wrap their errors with %v (which drops the chain). |
| 23 | func Classify(err error) error { |
| 24 | if err == nil { |
| 25 | return nil |
| 26 | } |
| 27 | if isClassified(err) { |
| 28 | return err |
| 29 | } |
| 30 | |
| 31 | switch { |
| 32 | case errors.Is(err, exec.ErrNotFound), |
| 33 | errors.Is(err, os.ErrNotExist), |
| 34 | errors.Is(err, io.EOF): |
| 35 | return wrap(ErrServerUnavailable, err) |
| 36 | } |
| 37 | |
| 38 | var netErr net.Error |
| 39 | if errors.As(err, &netErr) { |
| 40 | return wrap(ErrTransport, err) |
| 41 | } |
| 42 | |
| 43 | return classifyByMessage(err) |
| 44 | } |
| 45 | |
| 46 | // isClassified reports whether err already wraps one of the package |
| 47 | // sentinels. Used to make Classify idempotent. |