There is one real and one practical reason.
First, MPI was developed at a time when machines had exactly one processor core and when we wanted to couple different machines. It is today used on clusters of tens of thousands of machines, each of which happens to have many cores but the point is that it's still separate machines. Now, a processor core on machine A can't access memory on machine B, and so there needs to be a way to transfer information between these processes -- that's what the message passing interface (MPI) fundamentally does: transfer data from one machine to another.
You are entirely correct that, strictly speaking, you don't need MPI if you are working on one machine only. That of course limits how far you can scale your program (you will be able to use a few dozen threads, but not thousands since we don't have machines with that many cores). But more importantly, when you use threads, you now have a few dozen threads all accessing the same memory. It turns out to be conceptually very difficult to write codes that are efficient because historically we have been taught that the way to access shared data structures is to just use a mutex to access the information. That turns out to be efficient if you have 4 cores access the same memory, but not if you have 192: In that case, the ratio of time spent on computing information to time spent obtaining the mutex is just not very good any more. What one needs to do to address the issue is that every thread duplicates the read-write data structures during the main phase of the algorithm (so that they can be accessed without a mutex), followed by a reduction step. In other words, threads need to keep separate copies of data structures for efficiency. But that's not how we think when we program with threads, and so few implementations employ this strategy. On the other hand, that's what you need to do when you program with MPI because every process has its own memory space -- so MPI forces you to do what you should do with threads, and that's why using MPI often leads to quite efficient and scalable programs even when used in situations where threads could be used.