Uh oh!
There was an error while loading. Please reload this page.
improvement(microsoft-ad): add pagination support and fill BlockMeta gaps - #5442
Conversation
…gaps Full validate-integration pass against live Microsoft Graph API docs. No critical bugs found (endpoints, methods, params, and OAuth scopes were already correct). Fixed the real gaps: - List Users/Groups/Group Members had no way to page past the default Graph page size (100, max 999 via $top), which silently truncated results for the block's own audit/sweep templates. Added a nextLink input/output following the same convention as microsoft_dataverse. - Create Group's visibility dropdown was missing HiddenMembership, a valid Microsoft 365-only value that can only be set at creation time. - Rounded out BlockMeta skills (3 -> 5) with two more real, tool-grounded use cases: directory search and ad hoc group membership changes.
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Create Group adds Hidden Membership visibility (M365-only, creation-time). Create User requests selected profile fields on the POST so the created user payload is populated without a follow-up GET. List search queries now use Graph’s Block UI, tool params, and BlockMeta skills were updated for pagination and two new skills: directory user search and ad hoc group membership management. Reviewed by Cursor Bugbot for commit a4d76a6. Configure here. |
Greptile SummaryThis PR adds pagination support (
Confidence Score: 5/5Safe to merge — the pagination plumbing is correct, the continuation URL security guard is in place, and the block UI changes are coherent. The changes are well-scoped and consistent: pagination is added uniformly across all three list tools, assertGraphNextPageUrl prevents Bearer-token forwarding to untrusted hosts, the KQL search format is a net improvement over the old encoding, groupId is shown but made optional in the block with runtime validation preserving correctness for the initial call, and the HiddenMembership addition is a valid Microsoft Graph value. No data-correctness or auth-boundary issues were found. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant LLM
participant Tool as AD List Tool
participant Guard as assertGraphNextPageUrl
participant Graph as Microsoft Graph API
LLM->>Tool: call with filter/search/top params
Tool->>Graph: GET /v1.0/users with KQL search and select
Graph-->>Tool: value array plus odata.nextLink
Tool-->>LLM: users array plus nextLink string
LLM->>Tool: call with nextLink from previous response
Tool->>Guard: validate nextLink origin
Note over Guard: Throws if origin is not graph.microsoft.com
Guard-->>Tool: validated URL
Tool->>Graph: GET validated nextLink URL
Graph-->>Tool: next page of results
Tool-->>LLM: users array, nextLink null when exhausted
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant LLM
participant Tool as AD List Tool
participant Guard as assertGraphNextPageUrl
participant Graph as Microsoft Graph API
LLM->>Tool: call with filter/search/top params
Tool->>Graph: GET /v1.0/users with KQL search and select
Graph-->>Tool: value array plus odata.nextLink
Tool-->>LLM: users array plus nextLink string
LLM->>Tool: call with nextLink from previous response
Tool->>Guard: validate nextLink origin
Note over Guard: Throws if origin is not graph.microsoft.com
Guard-->>Tool: validated URL
Tool->>Graph: GET validated nextLink URL
Graph-->>Tool: next page of results
Tool-->>LLM: users array, nextLink null when exhausted
Reviews (4): Last reviewed commit: "fix(microsoft-ad): allow $search+$filter..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…elds Independent 4-agent re-audit against live Graph docs surfaced two real bugs predating this PR: - list_users/list_groups sent $search="<term>" with no property prefix. Graph requires the "property:value" form for directory-object search (e.g. "displayName:term" OR "mail:term") and 400s on a bare string. - create_user's POST had no $select, so Graph's default create response omits department/accountEnabled even when submitted, making transformResponse report them back as null. Added the same $select used by list/get so the response reflects what was actually set. Also tightened create_group's visibility description: only HiddenMembership is create-only: Private/Public can still be changed after creation via Update Group.
…nation Greptile and Cursor both flagged the same real issue: nextLink was passed straight to fetch() as the request URL with no origin check, while the OAuth bearer token was always attached. A crafted or prompt-injected nextLink pointing outside graph.microsoft.com would exfiltrate the token. Fix: reuse the existing assertGraphNextPageUrl/getGraphNextPageUrl helpers from tools/sharepoint/utils (already the shared pattern for SharePoint, OneDrive, Teams, Planner, Outlook, Excel Graph pagination) instead of a bespoke unvalidated pass-through. Cursor also caught that list_group_members required groupId even when only nextLink was supplied for a later page. Relaxed groupId to optional at the tool level, matching how sharepoint_get_list treats its analogous listId param — the URL builder still throws a clear error if neither groupId nor nextLink is given.
waleedlatif1
commented
Jul 6, 2026
@greptile review |
waleedlatif1
commented
Jul 6, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 9e00f2d. Configure here.
…ix pagination UX Second independent 4-agent re-audit of the final state (post security fix) surfaced 3 more real issues: - list_users/list_groups threw an error whenever $search and $filter were both supplied, claiming Graph doesn't support combining them. It does (AND semantics, documented) — the check was blocking valid, documented usage for no reason. Removed it. - The $search term escaping only handled embedded double quotes, not backslashes, which Graph's own escaping rule also requires. Fixed the replace order (backslashes first, then quotes). - list_group_members's Group ID field was still hard-required in the block UI for every operation including list_group_members, undermining the nextLink-only pagination path added earlier (the tool itself no longer requires it). Dropped list_group_members from the UI-required list, matching the tool's own conditional requirement — the runtime "Group ID is required" check still catches a genuinely empty call.
waleedlatif1
commented
Jul 6, 2026
@greptile review |
waleedlatif1
commented
Jul 6, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 6, 2026
@greptile review |
waleedlatif1
commented
Jul 6, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit a4d76a6. Configure here.
Summary
nextLinkinput/output to all three, following the same convention already used bymicrosoft_dataverseHiddenMembership, a valid Microsoft 365-only value that can only be set at creation timeType of Change
Testing
Tested manually (tsc + biome clean, verified query construction and Graph docs alignment)
Checklist