Code for I2C seem to be generally low priority in Microchip.
Once upon a time, there was a set of primitives and example code for simple I2C blocking operations, available as part of compiler / Plib installation.
With introduction of MCC, these have not been reproduced,
instead, the driver in MCC PIC device libraries, is a non-blocking interrupt driver with task queue, that is more complicated to use on the application level.
It did work for me, the first time I tried, but I have found several bugs and vulnerabilities,
and made a lot of modifications. You may see this thread:https://www.microchip.com/forums/FindPost/985254
For simpler purposes, threads in these forum, indicate that many users struggle with implementing their own code to control the MSSP I2C hardware. There is a lot of code examples around, but most have shortcuts and mistakes.
This is unfortunate, but not unexpected.
I2C is a communication protocol that require quite some careful software support, in order to function reliably and robust. But most I2C code provided by Microchip, or contributed in these fora, is weak on error checking and recovery from disturbances that may and will happen.
I2C communication concepts seem simple when presented and explained for simple purposes.
It is however a 'Listen before you talk' communication protocol, where hardware check that signaling procees correctly. If there is some disturbance, hardware will set a status flag or interrupt flag, and refuse any further transmission, until the mess is cleared up.
This require software support and quite a lot of testing.
Some conditions may be recovered, should be retried in driver level code,
but some conditions must be reported to Application code, and handled there.
I2C specification also hold several advanced features and alternatives, that require even more software support.
I did try the Foundation Library code for I2C about a year ago, and was not impressed.
It seem nothing have happened since then.
The first time I tried, I knowingly called a slave that was not connected. This is a case that should be expected, and handled and reported.
But example code went into a infinite loop, jammed the bus with continous transmission,
and never returned to application example.
When running on a small microcontroller with only one interrupt priority level,
a non-blocking interrupt driver, like in my link above, may not be the most suitable.
Code that wait for each transfer to complete, and do proper error cheching and recovery, may be suitable in many cases.
There are some code examples in: www.embeddedcodesource.com
If you provide a complete problem example, I may be able to try it on PIC16F1825 or PIC16F1829.