Sorry, didn’t even read the whole thing. Living on three hours of sleep, apologies
The mouse only exists on the client. It can’t be passed to the server.
Rather than passing the mouse object, you can instead pass the property that you want to the server. For example, send mouse.Target through the remote as that is an object that can be passed.
To explain this bit: the mouse is a client-created instance, meaning that it doesn’t have existence on the server. When you pass things through remotes, they are passed by reference. The server can’t hold a reference to an object it can’t see (not replicated), thus it’s nil.
The same will go with mouse.Target. If the Target (a BasePart) is created on the client, passing it as an argument to a remote will make it nil if the server doesn’t know it exists. Any object that exists immediately in the Workspace or is created by the server is replicated to the client as well, so both environments will be able to grab a reference to the object.
When it comes to passing a property (such as Hit), IIRC the behaviour here is that the data passed is essentially “cloned” and then passed as a reference, which is why the server can see a Vector3 that is a property of a client-side object and hence why passing mouse.Hit wouldn’t return nil.
There’s some information about the behaviour of sending arguments through remotes on the page or around the DevForum, since it’s been discussed at some lengths before. I’m going off of what I remember from those discussions, but that was a while ago when I saw them.