You could use crossContext. But I don't think that's app server agnostic.
I would share a custom class, behaving as a registry of running applications in the same tomcat instance through JNDI, as I explained here.
During startup, through a
ContextListener or through an Spring container event, I would obtain the registry through a JNDI lookup, add my web app instance with an url obtained from the servletcontext.contextpath, and finally register a listener to hear other applications registering themselves. That's the more server agnostic I can think of.
Obtaining the port won't be server agnostic, you should use a context parameter.
EDIT: I'm sorry, forgot to say that what I've described is to share objects among contexts, but no, you can't not know the port unless you use some server API (not agnostic at all).