Skip to content

MCP nested union schemas stringify valid list parameters #44321

Open

Description

@mikamikasuki

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

main (96202aa)

Cloud or Self Hosted

Self Hosted (Source)

Steps to reproduce

  1. On current main (96202aa544c4be59eae45ca9a9bf13f8deb03df6), configure an MCP tool with this inputSchema:
{
  "type": "object",
  "properties": {
    "domain": {
      "allOf": [
        {
          "anyOf": [
            {"type": "string"},
            {"type": "array", "items": {"type": "string"}}
          ]
        }
      ]
    }
  }
}
  1. Invoke it with domain: ["light", "cover"]. This schema is valid JSON Schema 2020-12 and uses MCP's supported composition keywords.
  2. Inspect the arguments passed to the MCP server.

Current main converts the parameter to Dify type string with no input_schema; MCPTool._transform_tool_parameters_type therefore sends the list as the string "['light', 'cover']". The same schema without the outer allOf is covered by #44181/#44182. The allOf wrapper is the missing case.

I reproduced this using the current-main converter and MCPTool transformation at the commit above. The #44182 review also identified nested-union handling as a separate follow-up: #44182 (review)

✔️ Expected Behavior

The valid list value should reach the MCP server unchanged as a JSON array. Dify should preserve the complete union schema for model input and skip scalar coercion for values governed by that mixed-type schema.

❌ Actual Behavior

The current converter loses the nested union metadata. The invoke path applies the string parameter cast and turns ["light", "cover"] into the Python representation "['light', 'cover']", so the MCP server receives the wrong JSON type.

Activity

  1. dosubot commented on Oct 19, 2026

    @dosubot

    The code at 96202aa confirms the mismatch: resolve_property_type() descends through allOf, but schema_accepts_multiple_types() examines only the property itself and its immediate anyOf/oneOf branches. Your wrapper therefore resolves to string without retaining input_schema. [1] [2] [3]

    Preserving input_schema in the converter alone would not fix this: the invocation bypass calls the same shallow detector again. The follow-up needs nested-schema detection shared by both paths, while respecting allOf intersection semantics rather than treating its branches as alternatives. [4]

    A useful regression is to extend the existing converter-to-MCPTool.invoke test with your wrapped schema, checking both "light" and ["light", "cover"], in both inner branch orders. That test already checks arguments passed to the remote invocation and verifies that ordinary single-type parameters still receive coercion, but its current cases contain no allOf wrapper. [5]

    To reply, just mention @dosu.


    Share context across your team and agents. Try Dosu.

    Leave Feedback Learn about dify with Dosu

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    review: highghfind author score; see https://ghfind.com🐞 bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions