Skip to content

MM-69467: Add page/per_page pagination to read_channel and read_post agent tools#856

Open
cursor[bot] wants to merge 7 commits into
masterfrom
cursor/jira-bug-fixing-agent-5060
Open

MM-69467: Add page/per_page pagination to read_channel and read_post agent tools#856
cursor[bot] wants to merge 7 commits into
masterfrom
cursor/jira-bug-fixing-agent-5060

Conversation

@cursor

@cursor cursor Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

The read_channel and read_post agent (MCP) tools were limited to 100 posts per call with no way to paginate, so an agent asked for "the last 500 threads" could only report it can pull up 100 recent posts per call. This adds page and per_page parameters to both tools so callers can retrieve more than 100 results or page through larger result sets.

  • read_channel (mcpserver/tools/channels.go): now forwards page/per_page to GetPostsForChannel (server-side pagination), raises the per-page cap from 100 to 200 (consistent with the other paginated channel tools), keeps the old limit as a deprecated alias for per_page (backward compatible), and appends a "More posts available — call read_channel again with page=N" hint when a full page is returned.
  • read_post (mcpserver/tools/posts.go): paginates large threads via page/per_page (the whole thread is still returned when neither is provided, preserving existing behavior), continues post numbering across pages, and appends a "More posts in this thread" hint when more pages exist.
  • Updated the tool descriptions and mcpserver/README.md.

QA test steps

  1. Configure an agent with access to the read_channel/read_post tools and a channel with more than 100 posts.
  2. Ask the agent to retrieve more than 100 posts (e.g. "show me the last 200 posts in this channel"). It can now return up to 200 per call and page beyond that via page.
  3. Ask it to keep going / "show the next page" — it pages using page=1, page=2, … and surfaces the next-page hint until the channel is exhausted.

Testing / evidence

No LLM provider credentials are available in this environment, so the user-facing agent conversation could not be driven in a browser. The bug and fix live at the MCP tool layer, which is verified end-to-end against a real Mattermost server (Testcontainers) through the real MCP protocol:

  • TestMCPToolsIntegration/ReadChannelTool/PaginationBeyond100: seeds 130 posts; page 0 with per_page=120 returns Found 120 posts (page 0) (impossible under the old 100 cap) plus More posts available — call read_channel again with page=1 to retrieve the next 120.; page 1 returns the remainder with no hint, and the oldest post is reachable on the later page.
  • TestMCPToolsIntegration/ReadPostTool/ThreadPagination: pages through a 10-post thread (page 0, showing 4page 2, showing 2).
  • Unit tests (real httptest.Server + real Client4) cover param forwarding, the limit alias, the 200 cap on both tools, negative-page clamping, the empty later-page message, the next-page hint contract, and the since + pagination interaction.

Ticket Link

Jira https://mattermost.atlassian.net/browse/MM-69467

Release Note

Added page and per_page parameters to the read_channel and read_post agent tools, allowing agents to retrieve more than 100 posts per call and paginate through larger channels and threads.
Open in Web View Automation 

Summary by CodeRabbit

Release Notes

  • New Features

    • Added page + per_page pagination to read_channel and in-thread read_post when enabled, including next-page “more posts” hints.
    • Added a per_page cap of 200 and support for the deprecated limit alias.
  • Bug Fixes

    • Improved empty-state messaging and pagination labels (including since filtering behaviour) for page-based results.
    • Negative page values are now clamped to 0.
  • Tests

    • Added unit and integration coverage for channel and thread pagination.
  • Documentation

    • Updated tool documentation to reflect per_page and the deprecated limit.

cursoragent and others added 4 commits June 23, 2026 18:19
…tools

The read_channel and read_post agent tools were limited to 100 posts per
call with no way to paginate. Add page and per_page parameters so callers
can retrieve more than 100 results or page through larger result sets.

read_channel now forwards page/per_page to GetPostsForChannel (max 200,
keeping the deprecated limit as an alias) and surfaces a next-page hint.
read_post paginates large threads in memory and continues post numbering
across pages.

Co-authored-by: mattermost-code <[email protected]>
Seed >100 posts and a multi-post thread against the real Mattermost test
server and verify read_channel returns 120 posts in one call (beyond the
old 100 cap) with working page navigation, and read_post pages through a
thread.

Co-authored-by: mattermost-code <[email protected]>
Add coverage for the read_post per_page cap, negative page clamping in
both tools, the empty later-page branch in read_channel, and tighten the
next-page hint and post-count assertions.

Co-authored-by: mattermost-code <[email protected]>
Document that since filters within the fetched page (reducing the shown
count) while the next-page hint reflects the number of posts the server
returned, not the filtered count.

Co-authored-by: mattermost-code <[email protected]>
@mattermost-code
mattermost-code marked this pull request as ready for review June 23, 2026 18:42
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

🤖 LLM Evaluation Results

OpenAI

⚠️ Overall: 21/28 tests passed (75.0%)

Provider Total Passed Failed Pass Rate
⚠️ OPENAI 28 21 7 75.0%

❌ Failed Evaluations

Show 7 failures

OPENAI

1. TestReactEval/[openai]_react_cat_message

  • Score: 0.00
  • Rubric: The word/emoji is a cat emoji or a heart/love emoji
  • Reason: The output is the text string "heart_eyes_cat", not an actual cat emoji (e.g., 🐱) or a heart/love emoji (e.g., ❤️).

2. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: is a list of bugs
  • Reason: The output does not provide an actual list of bugs; it states it cannot enumerate bugs without links and instead offers a blank template and instructions.

3. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: includes a description of each bug
  • Reason: The output does not include descriptions of any specific bugs; it only asks the user to provide bug titles/links and offers a template. Therefore it does not include a description of each bug.

4. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes each bug to a user
  • Reason: The output does not list any bugs or attribute them to specific users; it only requests that the user provide bug titles/links and provides a blank template. Therefore it does not satisfy the rubric requirement to attribute each bug to a user.

5. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes the bug about trying to save without a color and the save button not doing anything to @maria.nunez
  • Reason: The output does not mention the specific bug (“trying to save without a color” and the save button not doing anything) nor does it attribute it to @maria.nunez; it only asks the user to provide bug titles/links and offers a template.

6. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: the bug about the end user being able to change channel banner is attributed to @maria.nunez
  • Reason: The output does not list any specific bugs or attribute any bug to @maria.nunez. It only states it cannot access the tracker and provides a blank template, so the required attribution is missing.

7. TestDirectMessageConversations/[openai]_bot_dm_tool_introspection

  • Score: 0.00
  • Rubric: mentions Github and refers to the documentation
  • Reason: The output refers to documentation (docs.mattermost.com) but does not mention GitHub anywhere, so it does not satisfy the requirement to mention GitHub and refer to the documentation.

Anthropic

⚠️ Overall: 21/28 tests passed (75.0%)

Provider Total Passed Failed Pass Rate
⚠️ ANTHROPIC 28 21 7 75.0%

❌ Failed Evaluations

Show 7 failures

ANTHROPIC

1. TestReactEval/[anthropic]_react_cat_message

  • Score: 0.00
  • Rubric: The word/emoji is a cat emoji or a heart/love emoji
  • Reason: The output is the literal text "heart_eyes_cat", not an actual cat emoji (e.g., 😺/🐱) or heart/love emoji (e.g., ❤️/😍).

2. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: is a list of bugs
  • Reason: The output states it cannot access bug reports and suggests ways to provide details, but it does not actually present a list of bugs.

3. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: includes a description of each bug
  • Reason: The output explicitly states it does not have access to bug reports and does not list or describe any bugs. Therefore, it does not include a description of each bug as required by the rubric.

4. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes each bug to a user
  • Reason: The output does not list any bugs, nor does it attribute bugs to any users. It only states lack of access and suggests ways to provide bug details.

5. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes the bug about trying to save without a color and the save button not doing anything to @maria.nunez
  • Reason: The output does not mention @maria.nunez and does not attribute any specific bug (saving without a color / save button not doing anything) to anyone; it only states lack of access and suggests how to provide details.

6. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: the bug about the end user being able to change channel banner is attributed to @maria.nunez
  • Reason: The output does not mention the bug about an end user being able to change the channel banner, nor does it attribute any bug to @maria.nunez. It only states lack of access and suggests how to provide bug details.

7. TestDirectMessageConversations/[anthropic]_bot_dm_tool_introspection

  • Score: 0.50
  • Rubric: mentions Github and refers to the documentation
  • Reason: The output refers to documentation at docs.mattermost.com, satisfying the documentation reference, but it does not mention GitHub.

This comment was automatically generated by the eval CI pipeline.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 57 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: c887b126-91b4-4610-83ec-6a2e04a739af

📥 Commits

Reviewing files that changed from the base of the PR and between 537d560 and 67fc44a.

📒 Files selected for processing (7)
  • mcpserver/tools/channels.go
  • mcpserver/tools/channels_test.go
  • mcpserver/tools/pagination.go
  • mcpserver/tools/pagination_test.go
  • mcpserver/tools/posts.go
  • mcpserver/tools/posts_test.go
  • mcpserver/tools/teams.go
📝 Walkthrough

Walkthrough

Adds page and per_page parameters to the read_channel and read_post MCP tools. read_channel fetches posts by page from the API; read_post slices thread replies in-memory. Both tools emit page-context response headers, next-page hints when more results exist, and deprecate the old limit alias. New unit and integration tests cover the pagination behaviour.

Changes

Pagination for read_channel and read_post

Layer / File(s) Summary
Pagination args, constants, tool descriptions, and README
mcpserver/tools/channels.go, mcpserver/tools/posts.go, mcpserver/README.md
ReadChannelArgs and ReadPostArgs gain Page/PerPage fields with readChannelMaxPerPage and readPostMaxPerPage cap constants. Both tool Description strings and the README document per_page/page and mark limit as a deprecated alias.
read_channel pagination logic and response formatting
mcpserver/tools/channels.go
toolReadChannel resolves effective perPage from PerPage or deprecated Limit, clamps to cap, normalises negative page to 0, calls GetPostsForChannel with computed page/perPage, produces page-aware "no posts" messages, and appends a next-page hint when hasMore is true.
read_post thread pagination logic and response formatting
mcpserver/tools/posts.go
toolReadPost clamps per_page to readPostMaxPerPage, computes in-memory slice boundaries from page, returns an out-of-range message when the page start exceeds thread length, renders the thread header with total/page/shown counts, adjusts per-post numbering by pageStart offset, and appends a next-page hint when replies remain.
Unit tests for channel and post pagination
mcpserver/tools/channels_test.go, mcpserver/tools/posts_test.go
Introduces readChannelTestServer and readPostThreadServer mocks. TestToolReadChannelPagination and TestToolReadChannelSinceWithPagination assert query param forwarding, defaults, capping, clamping, and hasMore hint logic. TestToolReadPostThreadPagination, TestToolReadPostThreadPerPageCap, and TestToolReadPostThreadPageOverflow cover thread slicing, out-of-range pages, negative clamping, overflow handling, and the 200-cap.
Integration tests for channel and post pagination
mcpserver/tools_integration_test.go
PaginationBeyond100 seeds 130 posts and verifies per_page=120 returns correct counts and hint across two pages. ThreadPagination builds a 10-post thread and verifies per_page=4 pagination via the live API. Adds a textContent helper that concatenates TextContent blocks from tool results.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main changes: adding page/per_page pagination to read_channel and read_post agent tools.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/jira-bug-fixing-agent-5060

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mcpserver/tools/posts.go`:
- Around line 178-202: The pagination logic multiplies `page * perPage` to
calculate `pageStart` without validating that `page` is within a reasonable
upper bound, which can cause integer overflow when `page` is very large (e.g.,
math.MaxInt64), resulting in a negative value that bypasses the bounds check and
causes a panic on slice indexing. Before computing `pageStart`, add validation
to ensure `page` is less than the total number of pages, calculated as
(totalThreadPosts + perPage - 1) / perPage, and return an appropriate
out-of-range error message if the page exceeds this limit. Additionally, add a
regression test case that verifies the pagination logic handles `page =
math.MaxInt64` with `per_page > 0` correctly by returning the out-of-range
message without panicking.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 95bc7985-01ec-4d52-8177-6aa3414fa40f

📥 Commits

Reviewing files that changed from the base of the PR and between eb1b736 and 28709e0.

📒 Files selected for processing (6)
  • mcpserver/README.md
  • mcpserver/tools/channels.go
  • mcpserver/tools/channels_test.go
  • mcpserver/tools/posts.go
  • mcpserver/tools/posts_test.go
  • mcpserver/tools_integration_test.go

Comment thread mcpserver/tools/posts.go
Validate page against total pages before multiplying by per_page to
avoid integer overflow panics on extreme page values.

Co-authored-by: mattermost-code <[email protected]>
@mm-cloud-bot

Copy link
Copy Markdown

Creating a Plugin SpinWick test server

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Babysit complete — ready for human review

CodeRabbit approved commit 537d5609 after the page-overflow guard fix.

CI note: flaky e2e-tool-calling-anthropic failure (unrelated)

The e2e-tool-calling-anthropic job failed on the post-fix CI run with a timeout in multiplayer-tool-calling.spec.ts ("Accept tool calls then Keep Private"). This is not related to the read_channel / read_post pagination changes — the same job passed on the initial CI run (28709e09), and the failure is a timing flake in the multiplayer tool-approval UI flow.

All other checks are green (lint, plugin-tests, build, e2e shards, other real-API e2e jobs).

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@mm-cloud-bot

Copy link
Copy Markdown

Plugin Spinwick PR #856 🎉

Test server created!

Access here: https://agents-pr-856-qow94.test.mattermost.cloud

Plugin Version Artifact
agents 537d560 Download

Installation ID: bhujgcfyqin8xbfrbx6fpqopnr
Logs: Click here

Credentials: Posted securely in this Mattermost channel - Look for PR #856

@nickmisasi

Copy link
Copy Markdown
Collaborator

Validated pagination on the spinwick myself
image

@nickmisasi nickmisasi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we extract some of the pagination logic (in particular things around <=0, setting the default limit per entity) etc - to a helper within the tools package? That way future tools that support pagination could use it too.

@mattermost-code

Copy link
Copy Markdown
Contributor

Looking! Follow along here: https://cursor.com/agents/bc-91fcec2e-f586-4ce5-bc74-ccc7b60c559a

@mattermost-code

Copy link
Copy Markdown
Contributor

PR Feedback Resolution Summary

Questions Answered (0 items):

Code Changes Applied (1 item):

  • FB-001 — Extracted shared pagination helpers in mcpserver/tools and updated read_channel, read_post, get_channel_members, get_user_channels, and get_team_members to use centralized page/per-page normalization and safe in-memory slice bounds.

Declined Changes (0 items):

Needs Human Review (0 items):

Verification:

  • Targeted tests: ✅ go test ./mcpserver/tools; go test ./mcpserver/...
  • /deslop: N/A (no repo command available in this environment)
  • /precommit: ✅ make check using Go 1.26.4 and Node 24.11.0
  • Visual proof captured for 0 items

@nickmisasi

Copy link
Copy Markdown
Collaborator

/smart-cherry-pick release-2.0

@cursor
cursor Bot requested a review from amyblais June 25, 2026 18:22
@nickmisasi
nickmisasi removed the request for review from amyblais June 25, 2026 18:24
@nickmisasi

Copy link
Copy Markdown
Collaborator

@amyblais please ignore you being added here - was testing smart cherry pick.

@amyblais

Copy link
Copy Markdown
Member

please ignore you being added here - was testing smart cherry pick.

Thanks!

@nickmisasi
nickmisasi requested a review from crspeller June 26, 2026 15:27
@nickmisasi nickmisasi added the 2: Dev Review Requires review by a developer label Jun 26, 2026
@mattermost-code

Copy link
Copy Markdown
Contributor

@crspeller — friendly nudge: this PR has been waiting on your review for a couple of days and CodeRabbit has already signed off. Could you take a look when you get a chance? 🙏

Reconcile read_channel/read_post pagination with master refactors
(typed resolvers, *bool include_thread, renderMembers helper) and fix
unit tests to call tool handlers with struct args.

Co-authored-by: mattermost-code <[email protected]>
@mm-cloud-bot

Copy link
Copy Markdown

New commit detected. SpinWick will update the plugin if a new artifact is available.

@mm-cloud-bot

Copy link
Copy Markdown

Plugin test server update attempted, but encountered an issue:

⚠️ Install Error: failed to install plugin via mmctl: failed with status code 409

The test server is still available. You can manually download and install the updated plugin using the artifact link below.

Updated with git commit 67fc44accac1ebe5899aa43eb19bc18c469e49ff

Plugin Version Artifact
agents 67fc44a Download

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysit complete — ready for human review

All acceptance criteria met on commit 67fc44ac.

Changes in this babysit run

  • Merge conflicts resolved with master (typed resolvers, *bool include_thread, renderMembers helper) while preserving read_channel / read_post pagination.
  • Unit tests fixed to call tool handlers with struct args instead of legacy argsGetter callbacks.

Review feedback

  • CodeRabbit (page overflow): already addressed in 537d5609; thread resolved. Latest CodeRabbit status check passed on 67fc44ac.
  • nickmisasi (extract pagination helpers): addressed in 9a352a56 via shared mcpserver/tools/pagination.go used by read_channel, read_post, get_channel_members, get_user_channels, and get_team_members.

CI

All checks green on 67fc44ac (lint, plugin-tests, build, e2e shards, evals, security analyzers).

Handing off for human review.

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor Bot removed the AI/Babysit label Jul 1, 2026
@mattermost-code

Copy link
Copy Markdown
Contributor

@crspeller — friendly nudge: this PR has been waiting on your review for a couple of days and CodeRabbit has already signed off. Could you take a look when you get a chance? 🙏

@mattermost-code

Copy link
Copy Markdown
Contributor

@crspeller — friendly nudge: this PR has been waiting on your review for a couple of days and CodeRabbit has already signed off. Could you take a look when you get a chance? 🙏

2 similar comments
@mattermost-code

Copy link
Copy Markdown
Contributor

@crspeller — friendly nudge: this PR has been waiting on your review for a couple of days and CodeRabbit has already signed off. Could you take a look when you get a chance? 🙏

@mattermost-code

Copy link
Copy Markdown
Contributor

@crspeller — friendly nudge: this PR has been waiting on your review for a couple of days and CodeRabbit has already signed off. Could you take a look when you get a chance? 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants