A very large number. Most expander chips allow up to 8 to be connected on the bus. Some chips have a second variant part number which means a further 8 of the variant chips can also be added.
Then, there are i2c multiplexer chips which give up to an extra 8 i2c channels. Each channel can have many expander chips on it. Up to 8 of the multiplexer chips can be added to the main bus. It's probably also possible to cascade the multiplexers to further increase the number of channels. Think of a tree with a single trunk, 8 large branches, 8 smaller branches for each of the larger branches, 8 twigs off each of the smaller branches, and 8 or more leaves on each twig.
I've used the MCP23017 and was dissapointed at the speed when used to poll a bunch of switches for debouncing purposes. Also check the newest datasheet as it's been revised to say "Pins GPA7,
GPB7 are output only for MCP23017".
The MCP23017 has 3 adress lines so you can configure 8 different I2C adresses.
You can use a TCA9548A I2C Multiplexer Module to get 8 I2C ports out of one I2C port.
You can put 8 TCA9548A behind a TCA9548A I2C output.
And finally, the ESP32 has two I2C ports.
But when you are planing to "significantly increase the number of I/Os" I suggest you describe your real usecase what you plan to do in total. I assume there is an easier solution than a ton of multiplexers and port expanders.
May consider using I2C, SPI, or USART connection to an Arduino Mega2560, Due, or Giga board for 70 (54 digital + 16 analog pins) GPIO pins on one board. The Mega is 5V and the other two are 3.3V like the ESP.