creates and attaches all the components
Why can't the client run the same code?
Or, to put a little more structure into my suggestion:
- There are two ways that configured objects can be created in most game engines.
- One is through a specific code path, where everything is hard coded.
- The other is through a generic code path, that loads some "data description" of entities/components/parameters.
Now, make sure that the client and server both have copies of the same code, and the same data.
To create an entity from a data configuration blob, you just need the instruction "create object given data blob 2873." This is trivial to send through the network, too, and it allows designers to edit data blobs separate from the code, so this is generally preferred.
To create an entity procedurally, you have some code that does that. This code needs to be available on both client and server, and some reference to the code needs to be sent from server to client. You can, for example, use some kind of look-up table from some identifier to an actual function to run, and send the identifier across in the message.