register ajax calls hook

Any action that fires before the AJAX call is made will work. Generally speaking, init is good choice.

You mention that the ajax call is made from a “front-end form”. If that form is available to end-users who are not logged in, then you need to use:

add_action ('wp_ajax_nopriv_my_plugin_etc', 'my_plugin_etc') ;

See wp_ajax_nopriv_{$_REQUEST[‘action’]}.

Edit

Must be my lack of sleep, because I should have seen this earlier.

is_admin() returns false during an invocation of admin-ajax.php. Thus, change your my_plugin_init() to be:

function my_plugin_init() {

    if ( ! is_admin() || wp_doing_ajax ()) {

        require( dirname( __FILE__ ) . '/inc/my-plugin-functions.php' );

    }

}
add_action( 'init', 'my_plugin_init' );

wp_doing_ajax() was introduced in WP 4.7.

If your plugin needs to work in version of WP before that, then change it to:

function my_plugin_init() {

    if ( ! is_admin() || (defined( 'DOING_AJAX' ) && DOING_AJAX)) {

        require( dirname( __FILE__ ) . '/inc/my-plugin-functions.php' );

    }

}
add_action( 'init', 'my_plugin_init' );

The advantage of wp_doing_ajax() over the pre-4.7 test (if you can get away with only supporting 4.7+) is that applies the wp_doing_ajax filter to the value of defined( 'DOING_AJAX' ) && DOING_AJAX which can give you finer control over whether you want to consider yourself within an ajax context. However, this extra control is probably not necessary in your case.

Finally, if inc/my-plugin-functions.php only contains code related to AJAX, then you remove ! is_admin() || from the if condition.