@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix content: <http://purl.org/rss/1.0/modules/content/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<https://lhero.org/?post_type=lh-portfolio-doc&#038;p=147321>
  a sioc:Post ;
  dc:title "MCP abilities" ;
  dcterms:identifier 147321 ;
  dc:modified "2026-09-13T15:18:50Z"^^xsd:dateTime ;
  dc:created "2026-09-13T15:03:54Z"^^xsd:dateTime ;
  sioc:link <https://lhero.org/portfolio/lh-mcp-buddypress-queries/mcp-abilities/> ;
  sioc:has_creator <https://lhero.org/author/1/#account> ;
  sioc:has_container <https://lhero.org/#posts> ;
  content:encoded """<ul class="lh_portfolio-meta"><li><strong>Type:</strong> Doc-section</li><li><strong>Part of:</strong> <a href="https://lhero.org/portfolio/lh-mcp-buddypress-queries/">LH MCP BuddyPress Queries</a></li></ul>
<p class="wp-block-paragraph">Seven read-only MCP abilities, category <code>lh-mcp-buddypress-queries</code>. Abilities that never return an email address are gated to BuddyPress&#8217;s <code>bp_moderate</code> capability; abilities that return member email addresses (<code>get-group-members</code>, <code>search-members</code>) are gated to <code>edit_users</code> instead, matching the precedent set by <code>lh-membership/list-members</code>. Deliberately not exposed: private messages (<code>messages_get_threads</code>) and friend connections (<code>friends_get_friend_user_ids</code>) — a different risk category to group/activity/directory metadata, out of scope for this plugin.</p>



<h3 class="wp-block-heading">Group membership</h3>



<figure class="wp-block-table"><table>
<thead><tr><th>Ability</th><th>Capability</th><th>Notes</th></tr></thead>
<tbody>
<tr><td><code>get-group-members</code></td><td><code>edit_users</code></td><td>Members of a group: display name, email, roles (admin/mod/member/banned), join date. Optional <code>role</code> filter and <code>search</code>. Wraps <code>groups_get_group_members()</code>.</td></tr>
<tr><td><code>get-group-membership-status</code></td><td><code>bp_moderate</code></td><td>Whether a user is member/admin/mod/banned in a group, plus pending-invite status. No email returned.</td></tr>
</tbody>
</table></figure>



<h3 class="wp-block-heading">Group listing</h3>



<figure class="wp-block-table"><table>
<thead><tr><th>Ability</th><th>Capability</th><th>Notes</th></tr></thead>
<tbody>
<tr><td><code>list-groups</code></td><td><code>bp_moderate</code></td><td>Search/filter groups by name, status, user, include/exclude IDs — independent of any taxonomy. For taxonomy-based queries, use <a href="/portfolio/lh-buddypress-group-taxonomies/mcp-abilities/">lh-buddypress-group-taxonomies/get-groups-by-taxonomy</a> instead. Wraps <code>groups_get_groups()</code>; status filtering is applied client-side after fetching with <code>show_hidden: true</code>, the same pattern as the taxonomy plugin.</td></tr>
<tr><td><code>get-group</code></td><td><code>bp_moderate</code></td><td>Single group by ID or slug, including admin user IDs only (no email — use <code>get-group-members</code> filtered to <code>role: admin</code> for that).</td></tr>
</tbody>
</table></figure>



<h3 class="wp-block-heading">Activity</h3>



<figure class="wp-block-table"><table>
<thead><tr><th>Ability</th><th>Capability</th><th>Notes</th></tr></thead>
<tbody>
<tr><td><code>get-group-activity</code></td><td><code>bp_moderate</code></td><td>Recent activity stream for a group. Content stripped of markup and truncated to 300 chars. Wraps <code>bp_activity_get()</code> with <code>object: groups</code>.</td></tr>
<tr><td><code>get-user-activity</code></td><td><code>bp_moderate</code></td><td>Recent activity stream authored by a single user, across all components.</td></tr>
</tbody>
</table></figure>



<h3 class="wp-block-heading">Member directory</h3>



<figure class="wp-block-table"><table>
<thead><tr><th>Ability</th><th>Capability</th><th>Notes</th></tr></thead>
<tbody>
<tr><td><code>search-members</code></td><td><code>edit_users</code></td><td>BuddyPress member directory search (active/newest/alphabetical/online/random), distinct from <code>lh-membership/list-members</code> which is taxonomy-based rather than directory-based. Wraps <code>bp_core_get_users()</code>. Returns email.</td></tr>
</tbody>
</table></figure>



<h2 class="wp-block-heading">Worked example: admin contact lookup</h2>



<p class="wp-block-paragraph">Finding a group&#8217;s admin name and email is a two-call round trip, usable from any subsite connector:</p>



<pre class="wp-block-code"><code>// 1. Resolve the group and get admin user ID(s)
{ "tool": "lh-mcp-buddypress-queries/get-group", "params": { "slug": "sugar-gliders" } }
// -&gt; admin_ids: [7407]

// 2. Get that admin's name and email
{ "tool": "lh-mcp-buddypress-queries/get-group-members", "params": { "group_id": 21, "role": "admin" } }
// -&gt; name and email of the group admin</code></pre>



<h2 class="wp-block-heading">Architectural notes</h2>



<ul class="wp-block-list">

<li>Bootstraps entirely on <code>plugins_loaded</code> (no <code>bp_loaded</code> dependency, unlike <code>lh-buddypress-group-taxonomies</code>) since it has no BuddyPress-specific class loading order requirements — every execute callback guards with <code>function_exists()</code>/<code>class_exists()</code> checks instead, since BuddyPress itself may not be fully loaded at <code>plugins_loaded</code> time on every request path.</li>


<li>Requires WordPress 6.9+ since <code>wp_register_ability()</code>/<code>wp_register_ability_category()</code> require that version.</li>


<li><code>list-groups</code> and <code>get-groups-by-taxonomy</code> (in the taxonomy plugin) share the same status-filter-after-fetch pattern, since BuddyPress core doesn&#8217;t yet support filtering <code>groups_get_groups()</code> by a list of statuses directly.</li>


<li>Plugin folder, main file, class name, and ability namespace were all renamed from <code>lh-buddypress-queries</code> to <code>lh-mcp-buddypress-queries</code> in v2.0.0 — a breaking change for anything calling the old ability names directly.</li>

</ul>



<h2 class="wp-block-heading">Related plugins</h2>



<ul class="wp-block-list">

<li><a href="/portfolio/lh-buddypress-group-taxonomies/">lh-buddypress-group-taxonomies</a> — taxonomy-scoped group queries (<code>get-groups-by-taxonomy</code>, <code>list-terms</code>, <code>list-group-taxonomies</code>)</li>


<li><code>lh-membership</code> — taxonomy-based (not directory-based) member listing, same <code>edit_users</code> capability precedent for email-bearing abilities</li>

</ul>
"""^^rdf:XMLLiteral ;
  sioc:content """Type: Doc-sectionPart of: LH MCP BuddyPress Queries
Seven read-only MCP abilities, category lh-mcp-buddypress-queries. Abilities that never return an email address are gated to BuddyPress&#8217;s bp_moderate capability; abilities that return member email addresses (get-group-members, search-members) are gated to edit_users instead, matching the precedent set by lh-membership/list-members. Deliberately not exposed: private messages (messages_get_threads) and friend connections (friends_get_friend_user_ids) — a different risk category to group/activity/directory metadata, out of scope for this plugin.



Group membership




AbilityCapabilityNotes

get-group-membersedit_usersMembers of a group: display name, email, roles (admin/mod/member/banned), join date. Optional role filter and search. Wraps groups_get_group_members().
get-group-membership-statusbp_moderateWhether a user is member/admin/mod/banned in a group, plus pending-invite status. No email returned.





Group listing




AbilityCapabilityNotes

list-groupsbp_moderateSearch/filter groups by name, status, user, include/exclude IDs — independent of any taxonomy. For taxonomy-based queries, use lh-buddypress-group-taxonomies/get-groups-by-taxonomy instead. Wraps groups_get_groups(); status filtering is applied client-side after fetching with show_hidden: true, the same pattern as the taxonomy plugin.
get-groupbp_moderateSingle group by ID or slug, including admin user IDs only (no email — use get-group-members filtered to role: admin for that).





Activity




AbilityCapabilityNotes

get-group-activitybp_moderateRecent activity stream for a group. Content stripped of markup and truncated to 300 chars. Wraps bp_activity_get() with object: groups.
get-user-activitybp_moderateRecent activity stream authored by a single user, across all components.





Member directory




AbilityCapabilityNotes

search-membersedit_usersBuddyPress member directory search (active/newest/alphabetical/online/random), distinct from lh-membership/list-members which is taxonomy-based rather than directory-based. Wraps bp_core_get_users(). Returns email.





Worked example: admin contact lookup



Finding a group&#8217;s admin name and email is a two-call round trip, usable from any subsite connector:



// 1. Resolve the group and get admin user ID(s)
{ "tool": "lh-mcp-buddypress-queries/get-group", "params": { "slug": "sugar-gliders" } }
// -&gt; admin_ids: [7407]

// 2. Get that admin's name and email
{ "tool": "lh-mcp-buddypress-queries/get-group-members", "params": { "group_id": 21, "role": "admin" } }
// -&gt; name and email of the group admin



Architectural notes





Bootstraps entirely on plugins_loaded (no bp_loaded dependency, unlike lh-buddypress-group-taxonomies) since it has no BuddyPress-specific class loading order requirements — every execute callback guards with function_exists()/class_exists() checks instead, since BuddyPress itself may not be fully loaded at plugins_loaded time on every request path.


Requires WordPress 6.9+ since wp_register_ability()/wp_register_ability_category() require that version.


list-groups and get-groups-by-taxonomy (in the taxonomy plugin) share the same status-filter-after-fetch pattern, since BuddyPress core doesn&#8217;t yet support filtering groups_get_groups() by a list of statuses directly.


Plugin folder, main file, class name, and ability namespace were all renamed from lh-buddypress-queries to lh-mcp-buddypress-queries in v2.0.0 — a breaking change for anything calling the old ability names directly.





Related plugins





lh-buddypress-group-taxonomies — taxonomy-scoped group queries (get-groups-by-taxonomy, list-terms, list-group-taxonomies)


lh-membership — taxonomy-based (not directory-based) member listing, same edit_users capability precedent for email-bearing abilities


""" ;
  sioc:topic <https://lhero.org/?taxonomy=author&term=cap-1> .

<https://lhero.org/author/1/#account> rdfs:seeAlso <https://lhero.org/author/1/?feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=author&term=cap-1> rdfs:seeAlso <https://lhero.org/?taxonomy=author&term=cap-1&feed=lhrdf&format=turtle> .
