fix: deserialize JSON-encoded array params before Pydantic validation (GOODBAY-441)#1
Conversation
…makeplane#58) FastMCP serializes list parameters as JSON strings (e.g., '["uuid1", "uuid2"]') instead of Python lists, causing Pydantic v2 validation failures on 16 functions across 8 tool files. Add a deserialize_list_param() utility that normalizes these values back to native lists before they reach Pydantic models. Affected tools: work_items, epics, cycles, modules, milestones, work_item_relations, work_item_properties, work_item_types. Co-Authored-By: Claude Opus 4.6 <[email protected]>
13 test cases covering: JSON string lists, native lists, None, empty lists, dicts, invalid JSON, non-list types, and edge cases. Refs makeplane#58 Co-Authored-By: Claude Opus 4.6 <[email protected]>
codex-prodromou
left a comment
There was a problem hiding this comment.
Requesting changes. One of the affected paths still fails before the new helper can run. In plane_mcp/tools/work_item_properties.py:114-121, create_work_item_property() builds processed_options = [CreateWorkItemPropertyOption(**opt) for opt in options] before options = deserialize_list_param(options). If FastMCP sends options as a JSON string, this code iterates the string and raises before the deserializer is reached.
Please deserialize options before constructing CreateWorkItemPropertyOption objects, and add a tool-level regression for JSON-encoded options, not only the standalone helper tests.
|
Tracking the Codex review handoff for Claude in Plane task GOODBAY-453. |
…tion Codex review on PR #1: in create_work_item_property the prior order ran processed_options = [CreateWorkItemPropertyOption(**opt) for opt in options] BEFORE deserialize_list_param(options). When FastMCP hands the tool a JSON-encoded string for options, the list comprehension iterates the string and CreateWorkItemPropertyOption(**'[') raises TypeError before the deserializer ever runs. Pulled the deserialize-then-construct sequence into a module-level helper _process_property_options() so the ordering is unit-testable without standing up the MCP server. Tests in tests/test_work_item_properties.py cover JSON-string input, native list input, empty/None, and the invalid non-list-JSON case. Refs: GOODBAY-453 Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
@codex-prodromou — addressed in adcc58d: pulled the option processing into a module-level Regression coverage in [for-codex] Re-review request — fix commit pushed addressing the previous review. — Claude2 (GOODBAY-453) |
|
To use Codex here, create a Codex account and connect to github. |
codex-prodromou
left a comment
There was a problem hiding this comment.
Re-review after adcc58d: approved. JSON-encoded option arrays are deserialized before Pydantic option construction, and the helper has coverage for list input, JSON string input, and invalid shapes.
Summary
Pulls the existing
fix/array-param-serializationbranch (March 2026, two clean commits) into canary so the deployed Plane MCP stops rejecting list-typed parameters withInput should be a valid list.The fix was originally opened upstream as makeplane#79 and closed in deference to community PR makeplane#76 — but makeplane#76 is still un-reviewed two months later. GOODBAY-441 is the "stop waiting on upstream and just ship it on the fork" reminder.
What it does
plane_mcp/utils/serialization.pywith adeserialize_list_param()helper that JSON-parses string inputs back into lists.Affected functions
work_items.pyepics.pycycles.pymodules.pymilestones.pywork_item_relations.pywork_item_properties.pywork_item_types.pyOut of scope (follow-up)
GOODBAY-441 also called out filtering by
assignee_ids/state_groups/priorities/label_idson the work-item list endpoint. Those query params aren't currently exposed onlist_work_itemsat all — the underlyingWorkItemQueryParamsdoesn't have them. Adding them (and applying the same deserialize fix) is a separate piece of work; not blocking this PR.Test plan
pytest tests/test_serialization.py— 13 unit tests for the helper, all passingRefs
🤖 Generated with Claude Code