It is just a way to implement communication between your business logic components.
Imagine that you have:
FirstRequest // which handled by FirstRequestHandler(FirstRequest)
SecondRequest // which handled by SecondRequestHandler(SecondRequest)
ThirdRequest // which handled by ThirdRequestHandler(ThirdRequest)
... there are hundreds of them ...
And then comes ComplexRequest, when ComplexResponse have to be a combination of FirstResponse and ThirdResponse.
How should we solve this?
Well, ComplexRequestHandler would have to inject FirstHandler and ThirdHandler, get their results, and combine them.
But why should ComplexRequestHandler should have access to FirstRequestHandler interface ?
Why we should bother to inject First, Third ... OneHundredAndTwentythHandler into our ComplexHandler ?
What MediatR gives us in such use case, is a third party that tells us:
"Give me a request, and I"ll get you the right response, Trust me!"
So ComplexHandler doesn't know anything about First and Third Handlers.
It knows only about the required requests and responses (which usually are only just wrapping DTOs).
Note: You don't have to necessarily use the MediatR library for that. You can read about the Mediator Pattern and implement one yourself.