I have the same requirement. I believe it's a bug.
I have today raised a WordPress TRAC reporting my findings.
https://core.trac.wordpress.org/ticket/29714
Have a look and see if you've got the same problem.
Workaround
I have also developed a workaround that may allow you to make progress in the mean time.
Create a filter function for "user_has_cap".
In that filter function, when the capability being checked for is that which you have defined ( e.g. "edit_your_cpts"), add the following logic.
global $pagenow;
if ( $pagenow == "edit.php" && isset( $_REQUEST['post_type'] ) ) {
$pagenow .= '?post_type=' . $_REQUEST['post_type' ];
}
This will then allow the failing function ( user_can_access_admin_page() ) to return true.
Update 11th October. The first part of the workaround had some unwanted side effects. To overcome these you need some more code.
add_filter( "add_menu_classes", "oik_sites_add_menu_classes" );
/**
* Implement "add_menu_classes" filter for oik-sites
*
* Part 2 of the Workaround for TRAC #29714
*/
function oik_sites_add_menu_classes( $menu ) {
global $pagenow;
if ( false !== strpos( $pagenow, "edit.php" ) ) {
$pagenow = "edit.php";
}
return( $menu );
}