Skip to content

Empty {} / omitted parameters still fail in v0.5.0 for abilities WITH input schemas (follow-up to #116) #229

Description

@pkhaninejad

Description

#116 was closed as fixed in v0.5.0 via AbilityArgumentNormalizer, but the fix only covers abilities without an input schema. Abilities with an input schema (the exact case in #116's reproduction steps) still fail on v0.5.0 when called with empty {} parameters:

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

We reproduced this today in production on mcp-adapter v0.5.0 across two independent WordPress sites, for every registered ability that defines an input_schema (type object, all-optional or required properties alike).

Steps to Reproduce

  1. Register an ability with an input_schema of type object (optional properties, no default key).
  2. Call mcp-adapter-execute-ability with:
{
    "ability_name": "example/get-info",
    "parameters": {}
}
  1. Expected: ability executes (no required properties).
  2. Actual: Ability "example/get-info" has invalid input. Reason: input is not of type object.

Any non-empty parameters object (e.g. {"anything": true}) succeeds.

Evidence that the ability receives null, not []

AbilityArgumentNormalizer::normalize() only converts []null when the ability has no schema, and never converts null[] when it has one. On v0.5.0 the inner ability demonstrably receives null:

We patched our plugin to add 'default' => array() to every ability's input_schema — and the failure disappeared on the same v0.5.0 install, with no other change. WP_Ability::normalize_input() only applies the schema default when input is null, and rest_validate_value_from_schema( array(), … ) passes — so the pre-patch failure must be rest_validate_value_from_schema( null, {type: object} ) → "input is not of type object".

So somewhere in the v0.5.0 execution chain, "parameters": {} (or an omitted parameters key — $input['parameters'] ?? null in ExecuteAbilityAbility::execute()) reaches WP_Ability::execute() as null for schema-defining abilities, and validation rejects it with the misleading type error.

Suggested fix

In AbilityArgumentNormalizer::normalize() (or ExecuteAbilityAbility::execute() / the tools handler), handle the inverse case as well: when the ability has an input schema and the arguments are null or an empty array, pass array() so it validates as an empty object. Roughly:

if ( ! empty( $input_schema ) && ( null === $parameters || array() === $parameters ) ) {
    return array();
}

This keeps strict rejection for abilities without schemas (current behavior) while letting zero-argument calls through for schema-defining abilities — which is what every MCP client sends for tools it believes take no arguments.

Workarounds

  • 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).

Environment

  • MCP Adapter: v0.5.0 (reproduced on two independent production sites)
  • WordPress: 6.9 (core Abilities API — no standalone abilities-api plugin installed)
  • Client: Claude (Desktop/Code) via MCP integration, calling the mcp-adapter-execute-ability tool

Related: #116 (same symptom, closed for v0.5.0), #75 (the no-schema half, fixed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions