From d712e58ff5a84e08b6596bead5b25548be08946e Mon Sep 17 00:00:00 2001 From: Caitlyn Byrne Date: Sat, 14 Feb 2026 07:44:30 -0500 Subject: [PATCH] fix: stricter field validation for human input requests (#184 feedback) Validate select option structure (value/label keys, non-empty strings) and reject options on non-select field types. Co-Authored-By: Claude Opus 4.6 --- mcp_server/feature_mcp.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mcp_server/feature_mcp.py b/mcp_server/feature_mcp.py index 4e0b08b9..71e217d4 100755 --- a/mcp_server/feature_mcp.py +++ b/mcp_server/feature_mcp.py @@ -1049,8 +1049,21 @@ def feature_request_human_input( ftype = field.get("type", "text") if ftype not in VALID_FIELD_TYPES: return json.dumps({"error": f"Field at index {i} has invalid type '{ftype}'. Must be one of: {', '.join(sorted(VALID_FIELD_TYPES))}"}) - if ftype == "select" and not field.get("options"): - return json.dumps({"error": f"Field at index {i} is type 'select' but missing 'options' array"}) + if ftype == "select": + options = field.get("options") + if not options or not isinstance(options, list): + return json.dumps({"error": f"Field at index {i} is type 'select' but missing or invalid 'options' array"}) + for j, opt in enumerate(options): + if not isinstance(opt, dict): + return json.dumps({"error": f"Field at index {i}, option {j} must be an object with 'value' and 'label'"}) + if "value" not in opt or "label" not in opt: + return json.dumps({"error": f"Field at index {i}, option {j} missing required 'value' or 'label'"}) + if not isinstance(opt["value"], str) or not opt["value"].strip(): + return json.dumps({"error": f"Field at index {i}, option {j} has empty or invalid 'value'"}) + if not isinstance(opt["label"], str) or not opt["label"].strip(): + return json.dumps({"error": f"Field at index {i}, option {j} has empty or invalid 'label'"}) + elif field.get("options"): + return json.dumps({"error": f"Field at index {i} has 'options' but type is '{ftype}' (only 'select' uses options)"}) request_data = { "prompt": prompt,