Skip to content

feat(mcp): detail limit, param auto-resolve, and known behavior docs#327

Merged
erraggy merged 2 commits intomainfrom
feat/detail-limit
Feb 16, 2026
Merged

feat(mcp): detail limit, param auto-resolve, and known behavior docs#327
erraggy merged 2 commits intomainfrom
feat/detail-limit

Conversation

@erraggy
Copy link
Owner

@erraggy erraggy commented Feb 16, 2026

Summary

Follow-up to #324 — addresses remaining UX findings from corpus stress-testing the MCP plugin against 10 real-world OpenAPI specs.

  • 📏 Detail mode default limit (25): Walk tools in detail=true mode now default to 25 results instead of 100 via shared detailLimit() helper, keeping output manageable for LLM context windows
  • 🔍 Parameter filter auto-resolution: walk_parameters automatically resolves $ref parameters when in or name filter is specified, so users don't need to know about resolve_refs=true
  • 🏷️ Response group key fix: walk_responses group_by=method now labels component responses as (component) instead of ""
  • 📖 Known behavior docs: Filter behaviors, cross-tool limitations, and detail defaults documented in mcp-server.md and plugin/CLAUDE.md
  • 📊 Corpus analysis: Added docs/corpus-analysis.md with real-world spec analysis results

Limitation

Parameter auto-resolution doesn't take effect on specs with circular $refs due to a parser limitation where resolve_refs discards all resolution when circularity is detected. Tracked in #326.

Test plan

  • detailLimit() unit tests (zero, negative, explicit, boundary, max int)
  • walk_operations detail default limit integration test
  • walk_parameters in and name filter auto-resolution tests
  • walk_responses group_by=method (component) label test
  • make check passes (8176 tests, 0 lint issues)
  • gopls diagnostics clean
  • Manual MCP verification against NWS and GitHub corpus specs

🤖 Generated with Claude Code

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Warning

Rate limit exceeded

@erraggy has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Adds a 25-item default limit for detail-mode pagination, applies it across MCP walk handlers, enables parameter auto-resolution for in/name filters, labels component-level responses as "(component)", updates docs and lint globs, and adds tests covering these behaviors.

Changes

Cohort / File(s) Summary
Config / Lint
\.markdownlint-cli2.yaml
Added negative glob !.release/**, excluding .release from linting (i.e., updates lint glob behavior).
New Docs
docs/corpus-analysis.md
Adds a new corpus analysis document covering 10 OpenAPI specs with aggregated tables and observations.
MCP Docs & UX
docs/mcp-server.md, docs/mcp-ux-findings.md, plugin/CLAUDE.md
Documents detail-mode default limit, filter behaviors (param auto-resolve), component-response labeling, cross-tool limitations, and UX findings.
Core limit helper
internal/mcpserver/server.go
Introduces detailLimit(limit int) int and centralizes the 25-item default for detail mode.
Walk handlers — pagination
internal/mcpserver/tools_walk_*.go
internal/mcpserver/tools_walk_operations.go, internal/mcpserver/tools_walk_parameters.go, internal/mcpserver/tools_walk_paths.go, internal/mcpserver/tools_walk_refs.go, internal/mcpserver/tools_walk_responses.go, internal/mcpserver/tools_walk_schemas.go, internal/mcpserver/tools_walk_headers.go
When input.Detail is true, apply detailLimit(limit) before paginating; updated Limit jsonschema/docs to note "25 in detail mode".
Walk handlers — behavior tweaks
internal/mcpserver/tools_walk_parameters.go, internal/mcpserver/tools_walk_responses.go
Parameter filters by in/name auto-resolve $ref parameters; grouping by method uses "(component)" when method is empty.
Tests
internal/mcpserver/server_test.go, internal/mcpserver/tools_walk_operations_test.go, internal/mcpserver/tools_walk_parameters_test.go, internal/mcpserver/tools_walk_responses_test.go
Adds tests for detailLimit, default detail pagination (25), parameter auto-resolution (in/name filters), and (component) response grouping; adjusts paginate-related expectations.
Minor
plugin/CLAUDE.md
Documentation best-practices updated to note auto-resolve behavior and detail-mode default.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the three main changes: detail limit reduction to 25, parameter auto-resolution for filters, and documentation of known behaviors.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering all major changes, test plan, and known limitations.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/detail-limit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov
Copy link

codecov bot commented Feb 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.60%. Comparing base (217ece8) to head (741b366).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #327      +/-   ##
==========================================
+ Coverage   84.57%   84.60%   +0.02%     
==========================================
  Files         184      184              
  Lines       26820    26845      +25     
==========================================
+ Hits        22684    22711      +27     
+ Misses       2814     2813       -1     
+ Partials     1322     1321       -1     
Files with missing lines Coverage Δ
internal/mcpserver/server.go 94.40% <100.00%> (+0.18%) ⬆️
internal/mcpserver/tools_walk_headers.go 92.38% <100.00%> (+0.22%) ⬆️
internal/mcpserver/tools_walk_operations.go 91.33% <100.00%> (+0.20%) ⬆️
internal/mcpserver/tools_walk_parameters.go 80.58% <100.00%> (+2.58%) ⬆️
internal/mcpserver/tools_walk_paths.go 82.52% <100.00%> (+0.52%) ⬆️
internal/mcpserver/tools_walk_refs.go 95.23% <100.00%> (+0.05%) ⬆️
internal/mcpserver/tools_walk_responses.go 81.31% <100.00%> (+1.08%) ⬆️
internal/mcpserver/tools_walk_schemas.go 85.60% <100.00%> (+0.33%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@internal/mcpserver/tools_walk_operations.go`:
- Around line 55-57: Move the constant defaultDetailLimit from
tools_walk_operations.go into server.go and place it next to the detailLimit()
helper so the consumer and constant are co-located; update any references to
defaultDetailLimit to use the relocated symbol (no renaming needed), and ensure
the constant remains in the same package and visible to detailLimit() so
compilation and behavior are unchanged.

In `@internal/mcpserver/tools_walk_parameters_test.go`:
- Around line 357-436: Add a negative test (e.g.,
TestWalkParameters_BrokenRefAutoResolves) that uses a spec where a parameter is
a dangling $ref such as $ref: "#/components/parameters/DoesNotExist", call
callWalkParameters with a filter that forces auto-resolution (use
walkParametersInput + specInput and Path/In/Name as appropriate), and assert
that the call returns an error (use require.Error) and that the error message
mentions the unresolved ref (or at least that no parameters were matched).
Reference callWalkParameters, walkParametersInput, specInput, and the
output.Matched/output.Summaries to locate where to add the assertions.
- Around line 360-386: Extract the duplicated inline OpenAPI YAML used by
TestWalkParameters_InFilterAutoResolves and
TestWalkParameters_GroupByLocation_RefLabel into a package-level constant (e.g.,
walkParametersRefTestSpec) and replace the inline spec strings in both tests
with that const; ensure the const contains the superset spec (includes
TokenHeader) so both tests can reuse it and update any test helper calls that
reference the former inline variable names to use walkParametersRefTestSpec
instead.

@erraggy
Copy link
Owner Author

erraggy commented Feb 16, 2026

@claude please respond and resolve the review comments made by coderabbitai[bot] above. I agree with the first nitpick that calls out:

Consider moving defaultDetailLimit to server.go alongside detailLimit().

but I leave the other 2 for you to consider. I'm fine if you reason those away with words.

@oastools-claude
Copy link
Contributor

oastools-claude bot commented Feb 16, 2026

Claude finished @erraggy's task in 1m 58s —— View job


Resolving CodeRabbit Review Comments

  • Move defaultDetailLimit to server.go alongside detailLimit()
  • Respond to: missing edge-case test for broken $ref with auto-resolution
  • Respond to: extract shared spec YAML to package-level const

1. ✅ defaultDetailLimit moved to server.go — pushed in b6d0da6

Moved the defaultDetailLimit constant from tools_walk_operations.go to server.go, placing it directly above the detailLimit() helper that consumes it. This co-locates the constant with its primary consumer for better discoverability. All tests pass.


2. 🗣️ Missing edge-case test for broken $ref — respectfully declined

CodeRabbit suggests adding a TestWalkParameters_BrokenRefAutoResolves test for dangling $ref targets like #/components/parameters/DoesNotExist.

This is already covered at a different layer. The parser's resolve_refs logic is the component that handles $ref resolution — it either succeeds or returns an error — and that behavior has its own test coverage in the parser/ package. The auto-resolution feature in walk_parameters simply toggles the same parser.WithResolveRefs(true) option; it doesn't implement any new ref-resolution logic itself. A dangling $ref would produce a parser error before the walk tool's filter logic ever runs, so a test here would just be re-testing the parser's error path through an indirect integration point.

Adding it would also blur the boundary between what walk_parameters tests are responsible for (filtering/pagination UX) vs what the parser tests own (ref resolution correctness). The known limitation for circular refs (tracked in #326) is a different concern — that's about the parser silently discarding resolution rather than erroring.


3. 🗣️ Extract shared spec YAML to package-level const — respectfully declined

CodeRabbit notes the inline spec YAML in TestWalkParameters_InFilterAutoResolves and TestWalkParameters_NameFilterAutoResolves overlaps with TestWalkParameters_GroupByLocation_RefLabel.

Looking at the three tests:

  • GroupByLocation_RefLabel — uses a spec with one $ref parameter (LimitParam)
  • InFilterAutoResolves — uses a spec with two $ref parameters (LimitParam + TokenHeader) because it needs a second param to filter against
  • NameFilterAutoResolves — uses the one-param spec, same as GroupByLocation_RefLabel

The "superset" spec (with TokenHeader) could work for all three, but sharing it would obscure why each test uses the spec it does. Test specs should be self-documenting — when a test fails, you should be able to read the spec inline and immediately understand what's being exercised without chasing a shared constant defined elsewhere. The duplication is small (≈20 lines of YAML each), intentional, and serves readability over DRY. This is one of those cases where three similar lines of code is better than a premature abstraction.


|

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/mcpserver/tools_walk_operations.go (1)

25-25: ⚠️ Potential issue | 🟡 Minor

Update jsonschema descriptions for all walk input structs to clarify detail-mode limit override.

All seven walk input structs have stale Limit descriptions saying "default 100" without mentioning the detail-mode override. When detail=true, the effective default becomes 25 (via detailLimit() in server.go). This discrepancy is misleading to LLM clients consuming the schema.

Update the descriptions in:

  • internal/mcpserver/tools_walk_operations.go:25
  • internal/mcpserver/tools_walk_paths.go:19
  • internal/mcpserver/tools_walk_security.go:19
  • internal/mcpserver/tools_walk_refs.go:19
  • internal/mcpserver/tools_walk_parameters.go:23
  • internal/mcpserver/tools_walk_responses.go:21
  • internal/mcpserver/tools_walk_headers.go:23

Example fix for tools_walk_operations.go:

Proposed change
-	Limit       int       `json:"limit,omitempty"            jsonschema:"Maximum number of results to return (default 100)"`
+	Limit       int       `json:"limit,omitempty"            jsonschema:"Maximum number of results to return (default 100; 25 in detail mode)"`

…own behaviors

- Lower default limit for detail mode to 25 (vs 100 for summaries) across
  all 7 walk tools via shared detailLimit() helper
- Auto-resolve $ref parameters when `in` or `name` filter is specified in
  walk_parameters, so filters work without manual resolve_refs=true
- Add (component) label for walk_responses group_by=method empty keys
- Document filter behaviors, cross-tool limitations, and detail defaults
  in mcp-server.md
- Add best practice notes to plugin/CLAUDE.md (#9 auto-resolve, #10 detail limit)
- Update mcp-ux-findings.md status table with addressed/partial items
- Add corpus-analysis.md with real-world spec analysis results

Note: parameter auto-resolution is limited by a parser issue where
resolve_refs discards all resolution on specs with circular $refs (#326).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/mcp-server.md (1)

347-347: ⚠️ Potential issue | 🟡 Minor

Minor: Walk tools table limit description doesn't mention detail-mode default.

The shared walk tools table on this line describes limit as "Max results to return (default: 100)" without noting the 25-item detail-mode default. While the new "Detail Mode Defaults" section below covers this, the table is the first thing a reader encounters for walk tool parameters.

Consider updating for consistency with the per-tool jsonschema descriptions:

📝 Suggested update
-| `limit` | number | Max results to return (default: 100) |
+| `limit` | number | Max results to return (default: 100; 25 in detail mode) |

@erraggy erraggy merged commit cefdc5b into main Feb 16, 2026
8 checks passed
@erraggy erraggy deleted the feat/detail-limit branch February 16, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments