From b6379efac5f56f6f0987451f48d2d50804813c43 Mon Sep 17 00:00:00 2001 From: Madhav Kandukuri Date: Wed, 8 Oct 2025 18:27:24 +0530 Subject: [PATCH 1/3] Fix field_validator for federation_peers Signed-off-by: Madhav Kandukuri --- mcpgateway/config.py | 60 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/mcpgateway/config.py b/mcpgateway/config.py index b5546edb7..d61ca410d 100644 --- a/mcpgateway/config.py +++ b/mcpgateway/config.py @@ -719,13 +719,63 @@ def _parse_federation_peers(cls, v): if isinstance(v, str): v = v.strip() - if len(v) > 1 and v[0] in "\"'" and v[-1] == v[0]: - v = v[1:-1] + + # Handle empty string cases + if not v or v in ('""', "''"): + return [] + + # Try JSON parsing first without quote stripping try: - peers = json.loads(v) + parsed = json.loads(v) + # Ensure we always return a list for federation peers + if isinstance(parsed, list): + return parsed + elif isinstance(parsed, str): + # Check if the string looks like JSON (starts with [ or {) + # and try to parse it again + parsed_str = parsed.strip() + if parsed_str.startswith(('[', '{')): + try: + nested_parsed = json.loads(parsed_str) + if isinstance(nested_parsed, list): + return nested_parsed + else: + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(nested_parsed).__name__}") + return [] + except json.JSONDecodeError: + pass + # Single quoted string, treat as single URL + return [parsed] + else: + # Objects or other types don't make sense for federation peers + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") + return [] except json.JSONDecodeError: - peers = [s.strip() for s in v.split(",") if s.strip()] - return peers + pass + + # If JSON parsing failed, try removing outer quotes and retry + if len(v) > 1 and v[0] in "\"'" and v[-1] == v[0]: + inner_v = v[1:-1] + try: + parsed = json.loads(inner_v) + if isinstance(parsed, list): + return parsed + elif isinstance(parsed, str): + return [parsed] + else: + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") + return [] + except json.JSONDecodeError: + pass + + # Fallback to CSV parsing with improved quote handling + csv_v = v + # Remove outer quotes if they wrap the entire string + if csv_v.startswith(("'", '"')) and csv_v.endswith(("'", '"')) and csv_v[0] == csv_v[-1]: + csv_v = csv_v[1:-1] + + # Split by comma and clean each item + return [s.strip().strip("'\"") for s in csv_v.split(",") if s.strip()] # Convert other iterables to list return list(v) From 5bc5919bae81920b4ae7ba5591c22393963869ac Mon Sep 17 00:00:00 2001 From: Madhav Kandukuri Date: Wed, 8 Oct 2025 18:50:06 +0530 Subject: [PATCH 2/3] Linting fixes Signed-off-by: Madhav Kandukuri --- mcpgateway/config.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/mcpgateway/config.py b/mcpgateway/config.py index d61ca410d..aacb9958d 100644 --- a/mcpgateway/config.py +++ b/mcpgateway/config.py @@ -719,40 +719,41 @@ def _parse_federation_peers(cls, v): if isinstance(v, str): v = v.strip() - + # Handle empty string cases if not v or v in ('""', "''"): return [] - + # Try JSON parsing first without quote stripping try: parsed = json.loads(v) # Ensure we always return a list for federation peers if isinstance(parsed, list): return parsed - elif isinstance(parsed, str): + + if isinstance(parsed, str): # Check if the string looks like JSON (starts with [ or {) # and try to parse it again parsed_str = parsed.strip() - if parsed_str.startswith(('[', '{')): + if parsed_str.startswith(("[", "{")): try: nested_parsed = json.loads(parsed_str) if isinstance(nested_parsed, list): return nested_parsed - else: - logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(nested_parsed).__name__}") - return [] + + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(nested_parsed).__name__}") + return [] except json.JSONDecodeError: pass # Single quoted string, treat as single URL return [parsed] - else: - # Objects or other types don't make sense for federation peers - logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") - return [] + + # Objects or other types don't make sense for federation peers + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") + return [] except json.JSONDecodeError: pass - + # If JSON parsing failed, try removing outer quotes and retry if len(v) > 1 and v[0] in "\"'" and v[-1] == v[0]: inner_v = v[1:-1] @@ -760,20 +761,21 @@ def _parse_federation_peers(cls, v): parsed = json.loads(inner_v) if isinstance(parsed, list): return parsed - elif isinstance(parsed, str): + + if isinstance(parsed, str): return [parsed] - else: - logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") - return [] + + logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") + return [] except json.JSONDecodeError: pass - + # Fallback to CSV parsing with improved quote handling csv_v = v # Remove outer quotes if they wrap the entire string if csv_v.startswith(("'", '"')) and csv_v.endswith(("'", '"')) and csv_v[0] == csv_v[-1]: csv_v = csv_v[1:-1] - + # Split by comma and clean each item return [s.strip().strip("'\"") for s in csv_v.split(",") if s.strip()] From bcc2f5ded197a90c4952a83ebdf8f42695db1444 Mon Sep 17 00:00:00 2001 From: Madhav Kandukuri Date: Wed, 8 Oct 2025 19:26:12 +0530 Subject: [PATCH 3/3] Minor changes Signed-off-by: Madhav Kandukuri --- mcpgateway/config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mcpgateway/config.py b/mcpgateway/config.py index aacb9958d..abd9bc3ed 100644 --- a/mcpgateway/config.py +++ b/mcpgateway/config.py @@ -735,6 +735,7 @@ def _parse_federation_peers(cls, v): # Check if the string looks like JSON (starts with [ or {) # and try to parse it again parsed_str = parsed.strip() + if parsed_str.startswith(("[", "{")): try: nested_parsed = json.loads(parsed_str) @@ -752,7 +753,12 @@ def _parse_federation_peers(cls, v): logger.warning(f"Invalid federation_peers format: expected list or CSV, got {type(parsed).__name__}") return [] except json.JSONDecodeError: - pass + if len(v) > 1 and v[0] in "\"'" and v[-1] == v[0]: + v = v[1:-1] + + parsed = json.loads(v) + + return parsed # If JSON parsing failed, try removing outer quotes and retry if len(v) > 1 and v[0] in "\"'" and v[-1] == v[0]: