Skip to content

fix: normalize empty input to empty array for schema-defining abilities#230

Open
galatanovidiu wants to merge 2 commits into
trunkfrom
fix/229-normalize-empty-input-with-schema
Open

fix: normalize empty input to empty array for schema-defining abilities#230
galatanovidiu wants to merge 2 commits into
trunkfrom
fix/229-normalize-empty-input-with-schema

Conversation

@galatanovidiu

Copy link
Copy Markdown
Contributor

What

AbilityArgumentNormalizer::normalize() now converts null or an empty array to an empty array when the ability has an input_schema. Abilities without a schema keep the existing empty-to-null behavior.

Why

A zero-argument tool call sends {} (or omits arguments). For an ability that declares an input_schema, that value could reach WP_Ability::execute() as null, and validation rejected it:

Ability "example/get-info" has invalid input. Reason: input is not of type object.

An empty array is a valid empty object in WordPress (rest_is_object([]) is true), so passing [] instead of null lets a no-argument call through, while abilities with required properties still fail as they should.

Refs #229.

Testing

Verified live through the MCP Inspector over HTTP (default server, mcp-adapter-execute-ability and direct-tool paths), on WP 6.9 and 7.0:

Ability schema Empty {} before Empty {} after
object, all-optional passed already passes
array / non-object failed ("not of type array") passes
  • PHPCS: clean
  • PHPStan L8: clean
  • Normalizer unit test updated (test_null_parameters_normalized_to_empty_array_with_schema)
  • Full PHPUnit suite not run locally (tests wp-env would not start); please rely on CI.

Note on #229

I could not reproduce the reporter's exact case (an object schema failing on {}) on either v0.5.0 or trunk. This change fixes the real failure I did find (non-object schemas) and hardens the object path against null. It may not be the exact cause on their sites, so I'd keep #229 open until they share a failing ability's input_schema.

https://claude.ai/code/session_012RXWKvFkSm6LtNAYzPySHt

A zero-argument tool call sends {} (or omits arguments). For an ability
that declares an input_schema, that value reached WP_Ability::execute() as
null, and validation rejected it as "not of type object" (or "not of type
array" for non-object schemas the adapter unwraps). An empty array is a
valid empty object, so it passes.

AbilityArgumentNormalizer::normalize() now converts null or an empty array
to an empty array when the ability has a schema. Abilities without a schema
keep the existing empty-to-null behavior.

Refs #229

Claude-Session: https://claude.ai/code/session_012RXWKvFkSm6LtNAYzPySHt
Copilot AI review requested due to automatic review settings July 3, 2026 13:01
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: galatanovidiu <ovidiu-galatan@git.wordpress.org>
Co-authored-by: gziolo <gziolo@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.86%. Comparing base (90252e7) to head (05e0264).

Additional details and impacted files
@@            Coverage Diff            @@
##              trunk     #230   +/-   ##
=========================================
  Coverage     87.86%   87.86%           
- Complexity     1245     1247    +2     
=========================================
  Files            53       53           
  Lines          4037     4039    +2     
=========================================
+ Hits           3547     3549    +2     
  Misses          490      490           
Flag Coverage Δ
unit 87.86% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts how ability parameters are normalized when invoking WordPress Abilities through MCP, specifically ensuring schema-defining abilities receive an empty array ([]) instead of null for empty or omitted arguments to avoid schema validation failures (refs #229).

Changes:

  • Update AbilityArgumentNormalizer::normalize() to return [] (instead of null) when an ability has an input_schema and parameters are null or [].
  • Update the unit test to assert the new null[] behavior for schema-defining abilities.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
includes/Domain/Utils/AbilityArgumentNormalizer.php Changes normalization rules for empty inputs depending on whether an input_schema exists.
tests/phpunit/Unit/Domain/Utils/AbilityArgumentNormalizerTest.php Updates unit test expectations to match the new normalization behavior.
Comments suppressed due to low confidence (1)

tests/phpunit/Unit/Domain/Utils/AbilityArgumentNormalizerTest.php:106

  • This test covers the new null→[] behavior for an object schema, but the PR description also calls out non-object schemas (e.g. type=array) being fixed. Adding a second assertion for an array schema would lock in the intended behavior and prevent regressions.
	public function test_null_parameters_normalized_to_empty_array_with_schema(): void {
		$ability = $this->create_ability_mock(
			array(
				'type'       => 'object',
				'properties' => array(

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread includes/Domain/Utils/AbilityArgumentNormalizer.php
Comment thread includes/Domain/Utils/AbilityArgumentNormalizer.php Outdated
Comment thread includes/Domain/Utils/AbilityArgumentNormalizer.php
The class/method docblocks described validation as object-only ("not of
type object"), but normalize() applies to any non-empty input_schema,
including array schemas. Reworded to reference the schema type generically
so someone debugging an array-schema failure is not misled.

Docs only; no behavior change.

Claude-Session: https://claude.ai/code/session_01JsRf2jAiZLkqWyhGz92u1J
@gziolo

gziolo commented Jul 7, 2026

Copy link
Copy Markdown
Member

Client side: always send a non-empty parameters object, e.g. {"refresh": true}.
Ability side: add 'default' => array() to every registered input_schema (what we shipped).

Reading the problem statement described by @pkhaninejad in #229, I would expect that {} (empty object) gets properly converted to new stdClass() so it can get recognized as an object.

What if the author defines that the type of the input schema is either null or object? Would it be possible to still pass null as an argument?

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.

3 participants