Fix MCP get-items returning zero results due to empty filter values#349
Fix MCP get-items returning zero results due to empty filter values#349superdav42 merged 1 commit intomainfrom
Conversation
LLMs populate every schema field with default values ("" for strings,
false for booleans) even when no filter is intended. BerlinDB interprets
these literally as WHERE clauses (e.g. WHERE type = '' or WHERE
recurring = 0), which matches nothing or nearly nothing.
Strip empty strings and false booleans from args before passing them to
the query. This affects all models using the MCP_Abilities trait
(products, memberships, customers, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughModified MCP abilities trait to remove an early MCP-enabled check in the registration function, allowing processing when Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
🔨 Build Complete - Ready for Testing!📦 Download Build Artifact (Recommended)Download the zip build, upload to WordPress and test:
🌐 Test in WordPress Playground (Very Experimental)Click the link below to instantly test this PR in your browser - no installation needed! Login credentials: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@inc/apis/trait-mcp-abilities.php`:
- Around line 751-760: The current array_filter callback removes falsy false
values and so discards intentional boolean filters; update the callback used on
$args (the anonymous function passed to array_filter) to only remove empty
strings and nulls while preserving boolean false (e.g., return !($value === ''
|| $value === null)); ensure you do not use loose comparisons (==) so false
remains intact, and consider adjusting upstream schema defaults for boolean
filter properties to prevent LLMs from auto-populating false in the first place.
| // LLMs fill in every schema field with default-ish values like "" | ||
| // or false. BerlinDB interprets these literally (WHERE type = '' or | ||
| // WHERE recurring = 0), returning zero rows. Strip them out so only | ||
| // intentional filters reach the query. | ||
| $args = array_filter( | ||
| $args, | ||
| function ($value) { | ||
| return '' !== $value && false !== $value; | ||
| } | ||
| ); |
There was a problem hiding this comment.
Stripping false may silently discard intentional boolean filters.
The current filter removes all false values, but users may legitimately want to query for items where a boolean field is false (e.g., active = false to list inactive products, or recurring = false to find one-time purchases). This fix would make those queries impossible.
Consider one of these approaches:
- Track which fields were explicitly provided by the caller vs. auto-populated defaults
- Use a sentinel value (e.g.,
null) for "not specified" and only strip those - Require the LLM/caller to omit fields entirely rather than sending defaults (adjust schema to not have defaults for filter fields)
Additionally, null values pass through this filter (null !== false is true) and may also cause unexpected query behavior depending on how BerlinDB handles them.
Proposed fix to also filter null while preserving intentional false
One approach is to filter only truly "empty" values while keeping explicit booleans. However, this requires distinguishing intent, which may need upstream schema changes:
$args = array_filter(
$args,
function ($value) {
- return '' !== $value && false !== $value;
+ // Strip empty strings and null; keep false for intentional boolean filters
+ return '' !== $value && null !== $value;
}
);Note: This alone doesn't fully solve the LLM default problem for booleans. A more robust solution would be to remove default values from boolean filter properties in the schema (lines 648-705) so LLMs don't auto-fill them.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // LLMs fill in every schema field with default-ish values like "" | |
| // or false. BerlinDB interprets these literally (WHERE type = '' or | |
| // WHERE recurring = 0), returning zero rows. Strip them out so only | |
| // intentional filters reach the query. | |
| $args = array_filter( | |
| $args, | |
| function ($value) { | |
| return '' !== $value && false !== $value; | |
| } | |
| ); | |
| // LLMs fill in every schema field with default-ish values like "" | |
| // or false. BerlinDB interprets these literally (WHERE type = '' or | |
| // WHERE recurring = 0), returning zero rows. Strip them out so only | |
| // intentional filters reach the query. | |
| $args = array_filter( | |
| $args, | |
| function ($value) { | |
| // Strip empty strings and null; keep false for intentional boolean filters | |
| return '' !== $value && null !== $value; | |
| } | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@inc/apis/trait-mcp-abilities.php` around lines 751 - 760, The current
array_filter callback removes falsy false values and so discards intentional
boolean filters; update the callback used on $args (the anonymous function
passed to array_filter) to only remove empty strings and nulls while preserving
boolean false (e.g., return !($value === '' || $value === null)); ensure you do
not use loose comparisons (==) so false remains intact, and consider adjusting
upstream schema defaults for boolean filter properties to prevent LLMs from
auto-populating false in the first place.
Summary
""for strings,falsefor booleans) even when no filter is intendedWHERE type = ''orWHERE recurring = 0), returning zero rowsfalsebooleans from$argsinmcp_get_items()before passing them toquery()MCP_Abilitiestrait (products, memberships, customers, sites, payments, etc.)Test plan
type=plan)🤖 Generated with Claude Code
Summary by CodeRabbit