diff --git bp-core/admin/bp-core-functions.php bp-core/admin/bp-core-functions.php
index e47e7da..ef11105 100644
--- bp-core/admin/bp-core-functions.php
+++ bp-core/admin/bp-core-functions.php
@@ -74,11 +74,16 @@ add_action( bp_core_admin_hook(), 'bp_core_admin_backpat_menu', 999 );
  * @since BuddyPress (1.6)
  */
 function bp_core_modify_admin_menu_highlight() {
-	global $plugin_page, $submenu_file;
+	global $pagenow, $plugin_page, $submenu_file;
 
 	// This tweaks the Settings subnav menu to show only one BuddyPress menu item
 	if ( ! in_array( $plugin_page, array( 'bp-activity', 'bp-general-settings', ) ) )
 		$submenu_file = 'bp-components';
+
+	// Network Admin > Tools
+	if ( in_array( $plugin_page, array( 'bp-tools', 'available-tools' ) ) ) {
+		$submenu_file = $plugin_page;
+	}
 }
 
 /**
@@ -388,7 +393,7 @@ function bp_core_admin_tabs( $active_tab = '' ) {
 		'2' => array(
 			'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ),
 			'name' => __( 'Settings', 'buddypress' )
-		)
+		),
 	);
 
 	// If forums component is active, add additional tab
diff --git bp-core/admin/bp-core-tools.php bp-core/admin/bp-core-tools.php
new file mode 100644
index 0000000..ecaac64
--- /dev/null
+++ bp-core/admin/bp-core-tools.php
@@ -0,0 +1,313 @@
+<?php
+
+/**
+ * BuddyPress Tools panel
+ *
+ * @since BuddyPress (2.0.0)
+ */
+
+/**
+ * Render the BuddyPress Tools page.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_core_admin_tools() {
+	?>
+	<div class="wrap">
+		<?php screen_icon( 'buddypress'); ?>
+
+		<h2><?php esc_html_e( 'BuddyPress Tools', 'buddypress' ) ?></h2>
+
+		<p><?php esc_html_e( 'BuddyPress keeps track of various relationships between users, groups, and activity items. Occasionally these relationships become out of sync, most often after an import, update, or migration. Use the tools below to manually recalculate these relationships.', 'buddypress' ); ?></p>
+		<p class="description"><?php esc_html_e( 'Some of these tools create substantial database overhead. Avoid running more than one repair job at a time.', 'buddypress' ); ?></p>
+
+		<form class="settings" method="post" action="">
+			<table class="form-table">
+				<tbody>
+					<tr valign="top">
+						<th scope="row"><?php esc_html_e( 'Data to Repair:', 'buddypress' ) ?></th>
+						<td>
+							<fieldset>
+								<legend class="screen-reader-text"><span><?php esc_html_e( 'Repair', 'buddypress' ) ?></span></legend>
+
+								<?php foreach ( bp_admin_repair_list() as $item ) : ?>
+
+									<label><input type="checkbox" class="checkbox" name="<?php echo esc_attr( $item[0] ) . '" id="' . esc_attr( str_replace( '_', '-', $item[0] ) ); ?>" value="1" /> <?php echo esc_html( $item[1] ); ?></label><br />
+
+								<?php endforeach; ?>
+
+							</fieldset>
+						</td>
+					</tr>
+				</tbody>
+			</table>
+
+			<fieldset class="submit">
+				<input class="button-primary" type="submit" name="bp-tools-submit" value="<?php esc_attr_e( 'Repair Items', 'buddypress' ); ?>" />
+				<?php wp_nonce_field( 'bp-do-counts' ); ?>
+			</fieldset>
+		</form>
+	</div>
+	<?php
+}
+
+/**
+ * Handle the processing and feedback of the admin tools page.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_admin_repair_handler() {
+	if ( ! bp_is_post_request() ) {
+		return;
+	}
+
+	if ( empty( $_POST['bp-tools-submit'] ) ) {
+		return;
+	}
+
+	check_admin_referer( 'bp-do-counts' );
+
+	// Stores messages
+	$messages = array();
+
+	wp_cache_flush();
+
+	foreach ( (array) bp_admin_repair_list() as $item ) {
+		if ( isset( $item[2] ) && isset( $_POST[$item[0]] ) && 1 === absint( $_POST[$item[0]] ) && is_callable( $item[2] ) ) {
+			$messages[] = call_user_func( $item[2] );
+		}
+	}
+
+	if ( count( $messages ) ) {
+		foreach ( $messages as $message ) {
+			bp_admin_tools_feedback( $message[1] );
+		}
+	}
+}
+add_action( bp_core_admin_hook(), 'bp_admin_repair_handler' );
+
+/**
+ * Get the array of the repair list.
+ *
+ * @return array
+ */
+function bp_admin_repair_list() {
+	// Members:
+	// - member count
+	$repair_list = array(
+		20 => array(
+			'bp-total-member-count',
+			__( 'Count total members', 'buddypress' ),
+			'bp_admin_repair_count_members',
+		),
+	);
+
+	// Friends:
+	// - user friend count
+	if ( bp_is_active( 'friends' ) ) {
+		$repair_list[0] = array(
+			'bp-user-friends',
+			__( 'Count friends for each user', 'buddypress' ),
+			'bp_admin_repair_friend_count',
+		);
+	}
+
+	// Groups:
+	// - user group count
+	if ( bp_is_active( 'groups' ) ) {
+		$repair_list[10] = array(
+			'bp-group-count',
+			__( 'Count groups for each user', 'buddypress' ),
+			'bp_admin_repair_group_count',
+		);
+	}
+
+	ksort( $repair_list );
+
+	return (array) apply_filters( 'bp_repair_list', $repair_list );
+}
+
+/**
+ * Recalculate friend counts for each user.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @return array
+ */
+function bp_admin_repair_friend_count() {
+	global $wpdb, $bp;
+
+	if ( ! bp_is_active( 'friends' ) ) {
+		return;
+	}
+
+	$statement = __( 'Counting the number of friends for each user&hellip; %s', 'buddypress' );
+	$result    = __( 'Failed!', 'buddypress' );
+
+	$sql_delete = "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ( 'total_friend_count' );";
+	if ( is_wp_error( $wpdb->query( $sql_delete ) ) ) {
+		return array( 1, sprintf( $statement, $result ) );
+	}
+
+	// Walk through all users on the site
+	$total_users = $wpdb->get_row( "SELECT count(ID) as c FROM {$wpdb->users}" )->c;
+
+	$updated = array();
+	if ( $total_users > 0 ) {
+		$per_query = 500;
+		$offset = 0;
+		while ( $offset < $total_users ) {
+			// Only bother updating counts for users who actually have friendships
+			$friendships = $wpdb->get_results( $wpdb->prepare( "SELECT initiator_user_id, friend_user_id FROM {$bp->friends->table_name} WHERE is_confirmed = 1 AND ( ( initiator_user_id > %d AND initiator_user_id <= %d ) OR ( friend_user_id > %d AND friend_user_id <= %d ) )", $offset, $offset + $per_query, $offset, $offset + $per_query ) );
+
+			// The previous query will turn up duplicates, so we
+			// filter them here
+			foreach ( $friendships as $friendship ) {
+				if ( ! isset( $updated[ $friendship->initiator_user_id ] ) ) {
+					BP_Friends_Friendship::total_friend_count( $friendship->initiator_user_id );
+					$updated[ $friendship->initiator_user_id ] = 1;
+				}
+
+				if ( ! isset( $updated[ $friendship->friend_user_id ] ) ) {
+					BP_Friends_Friendship::total_friend_count( $friendship->friend_user_id );
+					$updated[ $friendship->friend_user_id ] = 1;
+				}
+			}
+
+			$offset += $per_query;
+		}
+	} else {
+		return array( 2, sprintf( $statement, $result ) );
+	}
+
+	return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Recalculate group counts for each user.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @return array
+ */
+function bp_admin_repair_group_count() {
+	global $wpdb, $bp;
+
+	if ( ! bp_is_active( 'groups' ) ) {
+		return;
+	}
+
+	$statement = __( 'Counting the number of groups for each user&hellip; %s', 'buddypress' );
+	$result    = __( 'Failed!', 'buddypress' );
+
+	$sql_delete = "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ( 'total_group_count' );";
+	if ( is_wp_error( $wpdb->query( $sql_delete ) ) ) {
+		return array( 1, sprintf( $statement, $result ) );
+	}
+
+	// Walk through all users on the site
+	$total_users = $wpdb->get_row( "SELECT count(ID) as c FROM {$wpdb->users}" )->c;
+
+	if ( $total_users > 0 ) {
+		$per_query = 500;
+		$offset = 0;
+		while ( $offset < $total_users ) {
+			// But only bother to update counts for users that have groups
+			$users = $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE is_confirmed = 1 AND is_banned = 0 AND user_id > %d AND user_id <= %d", $offset, $offset + $per_query ) );
+
+			foreach ( $users as $user ) {
+				BP_Groups_Member::refresh_total_group_count_for_user( $user );
+			}
+
+			$offset += $per_query;
+		}
+	} else {
+		return array( 2, sprintf( $statement, $result ) );
+	}
+
+	return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Recalculate the total number of active site members.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_admin_repair_count_members() {
+	$statement = __( 'Counting the number of active members on the site&hellip; %s', 'buddypress' );
+	delete_transient( 'bp_active_member_count' );
+	bp_core_get_active_member_count();
+	return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Assemble admin notices relating success/failure of repair processes.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @param string $message Feedback message.
+ * @param unknown $class Unused.
+ */
+function bp_admin_tools_feedback( $message, $class = false ) {
+	if ( is_string( $message ) ) {
+		$message = '<p>' . $message . '</p>';
+		$class = $class ? $class : 'updated';
+	} elseif ( is_wp_error( $message ) ) {
+		$errors = $message->get_error_messages();
+
+		switch ( count( $errors ) ) {
+			case 0:
+				return false;
+				break;
+
+			case 1:
+				$message = '<p>' . $errors[0] . '</p>';
+				break;
+
+			default:
+				$message = '<ul>' . "\n\t" . '<li>' . implode( '</li>' . "\n\t" . '<li>', $errors ) . '</li>' . "\n" . '</ul>';
+				break;
+		}
+
+		$class = $class ? $class : 'error';
+	} else {
+		return false;
+	}
+
+	$message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
+	$message = str_replace( "'", "\'", $message );
+	$lambda  = create_function( '', "echo '$message';" );
+
+	add_action( 'admin_notices', $lambda );
+
+	return $lambda;
+}
+
+/**
+ * Render the Available Tools page.
+ *
+ * We register this page on Network Admin as a top-level home for our
+ * BuddyPress tools. This displays the default content.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_core_admin_available_tools_page() {
+	global $submenu;
+
+	// Stupid trick: grab all the submenu items and make a list
+	$tools = isset( $submenu['network-tools'] ) ? $submenu['network-tools'] : array();
+
+	?>
+	<div class="wrap">
+		<h2><?php esc_attr_e( 'Tools', 'buddypress' ) ?></h2>
+
+		<ul>
+		<?php foreach ( $tools as $tool ) : ?>
+			<?php /* Skip "Available Tools" */ ?>
+			<?php if ( 'available-tools' === $tool[2] ) continue; ?>
+			<li><a href="<?php echo esc_url( add_query_arg( 'page', $tool[2], network_admin_url( 'admin.php' ) ) ) ?>"><?php echo esc_html( $tool[3] ) ?></a></li>
+		<?php endforeach; ?>
+		</ul>
+	</div>
+	<?php
+}
diff --git bp-core/admin/css/common.css bp-core/admin/css/common.css
index 17548ec..e476679 100644
--- bp-core/admin/css/common.css
+++ bp-core/admin/css/common.css
@@ -90,6 +90,12 @@ body.branch-3-7 ul#adminmenu li.toplevel_page_bp-groups_network.current .wp-menu
 body.branch-3-7 ul#adminmenu li.toplevel_page_bp-groups_network.wp-has-current-submenu .wp-menu-image {
 	background-position: -61px -2px;
 }
+
+/* Tools */
+#adminmenu .toplevel_page_network-tools div.wp-menu-image:before {
+    content: "";
+}
+
 th.column-gid {
 	width: 60px;
 }
diff --git bp-core/bp-core-admin.php bp-core/bp-core-admin.php
index 4020355..bf541ac 100644
--- bp-core/bp-core-admin.php
+++ bp-core/bp-core-admin.php
@@ -118,6 +118,7 @@ class BP_Admin {
 		require( $this->admin_dir . 'bp-core-functions.php'  );
 		require( $this->admin_dir . 'bp-core-components.php' );
 		require( $this->admin_dir . 'bp-core-slugs.php'      );
+		require( $this->admin_dir . 'bp-core-tools.php'      );
 	}
 
 	/**
@@ -242,6 +243,42 @@ class BP_Admin {
 			'bp_core_admin_settings'
 		);
 
+		// For consistency with non-Multisite, we add a Tools menu in
+		// the Network Admin as a home for our Tools panel
+		if ( is_multisite() && bp_core_do_network_admin() ) {
+			$tools_parent = 'network-tools';
+
+			$hooks[] = add_menu_page(
+				__( 'Tools', 'buddypress' ),
+				__( 'Tools', 'buddypress' ),
+				'manage_network_options',
+				$tools_parent,
+				'bp_core_tools_top_level_item',
+				'',
+				24 // just above Settings
+			);
+
+			$hooks[] = add_submenu_page(
+				$tools_parent,
+				__( 'Available Tools', 'buddypress' ),
+				__( 'Available Tools', 'buddypress' ),
+				'manage_network_options',
+				'available-tools',
+				'bp_core_admin_available_tools_page'
+			);
+		} else {
+			$tools_parent = 'tools.php';
+		}
+
+		$hooks[] = add_submenu_page(
+			$tools_parent,
+			__( 'BuddyPress Tools', 'buddypress' ),
+			__( 'BuddyPress', 'buddypress' ),
+			'manage_options',
+			'bp-tools',
+			'bp_core_admin_tools'
+		);
+
 		// Fudge the highlighted subnav item when on a BuddyPress admin page
 		foreach( $hooks as $hook ) {
 			add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
@@ -401,6 +438,9 @@ class BP_Admin {
 		remove_submenu_page( $this->settings_page, 'bp-page-settings' );
 		remove_submenu_page( $this->settings_page, 'bp-settings'      );
 
+		// Network Admin Tools
+		remove_submenu_page( 'network-tools', 'network-tools' );
+
 		// About and Credits pages
 		remove_submenu_page( 'index.php', 'bp-about'   );
 		remove_submenu_page( 'index.php', 'bp-credits' );
