mcp: preserve transport errors in Write error chain (#888)

mcp: preserve transport errors in Write error chain

Custom RoundTrippers that return typed errors (e.g. for auth failures)
have those errors flattened to strings by `%v`, making `errors.As`
unusable for callers inspecting transport-level errors.

This is inconsistent with the OAuth handler path (line 1807) which
already uses `%w` to preserve errors for client inspection.

Relates to #579

Co-authored-by: Maciej Kisiel <mkisiel@google.com>
This commit is contained in:
John Pugliesi 2026-04-24 04:20:45 -07:00 • committed by GitHub
commit 5f2cd8fd14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1795,14 +1795,14 @@ func (c *streamableClientConn) Write(ctx context.Context, msg jsonrpc.Message) e
// Failure to set headers means that the request was not sent.
// Wrap with ErrRejected so the jsonrpc2 connection doesn't set writeErr
// and permanently break the connection.
return nil, nil, fmt.Errorf("%s: %w: %v", requestSummary, jsonrpc2.ErrRejected, err)
return nil, nil, fmt.Errorf("%s: %w: %w", requestSummary, jsonrpc2.ErrRejected, err)
}
resp, err := c.client.Do(req)
if err != nil {
// Any error from client.Do means the request didn't reach the server.
// Wrap with ErrRejected so the jsonrpc2 connection doesn't set writeErr
// and permanently break the connection.
err = fmt.Errorf("%s: %w: %v", requestSummary, jsonrpc2.ErrRejected, err)
err = fmt.Errorf("%s: %w: %w", requestSummary, jsonrpc2.ErrRejected, err)
}
return req, resp, err
}