| 687 | |
| 688 | |
| 689 | class MCPConfig(BaseModel): |
| 690 | servers: list[MCPServer] = Field(default_factory=list) |
| 691 | disconnected_servers: list[dict[str, Any]] = Field(default_factory=list) |
| 692 | config_scope: str = Field(default="global") |
| 693 | __lock: ClassVar[threading.Lock] = PrivateAttr(default=threading.Lock()) |
| 694 | __instance: ClassVar[Any] = PrivateAttr(default=None) |
| 695 | __initialized: ClassVar[bool] = PrivateAttr(default=False) |
| 696 | __project_instances: ClassVar[dict[str, tuple[str, "MCPConfig"]]] = {} |
| 697 | |
| 698 | @classmethod |
| 699 | def get_instance(cls) -> "MCPConfig": |
| 700 | with cls.__lock: |
| 701 | if cls.__instance is None: |
| 702 | cls.__instance = cls(servers_list=[], config_scope="global") |
| 703 | return cls.__instance |
| 704 | |
| 705 | @classmethod |
| 706 | def clear_project_instances(cls): |
| 707 | with cls.__lock: |
| 708 | cls.__project_instances = {} |
| 709 | |
| 710 | @classmethod |
| 711 | def parse_config_string(cls, config_str: str) -> List[Dict[str, Any]]: |
| 712 | servers_data: List[Dict[str, Any]] = [] |
| 713 | |
| 714 | if not (config_str and config_str.strip()): |
| 715 | return servers_data |
| 716 | |
| 717 | try: |
| 718 | parsed_value = dirty_json.try_parse(config_str) |
| 719 | normalized = cls.normalize_config(parsed_value) |
| 720 | |
| 721 | if isinstance(normalized, list): |
| 722 | for item in normalized: |
| 723 | if isinstance(item, dict): |
| 724 | servers_data.append(dict(item)) |
| 725 | else: |
| 726 | PrintStyle( |
| 727 | background_color="yellow", |
| 728 | font_color="black", |
| 729 | padding=True, |
| 730 | ).print( |
| 731 | f"Warning: MCP config item was not a dictionary and was ignored: {item}" |
| 732 | ) |
| 733 | else: |
| 734 | PrintStyle( |
| 735 | background_color="red", font_color="white", padding=True |
| 736 | ).print( |
| 737 | f"Error: Parsed MCP config top-level structure is not a list. Config string was: '{config_str}'" |
| 738 | ) |
| 739 | except Exception as e_json: |
| 740 | PrintStyle.error( |
| 741 | f"Error parsing MCP config string: {e_json}. Config string was: '{config_str}'" |
| 742 | ) |
| 743 | |
| 744 | return servers_data |
| 745 | |
| 746 | @classmethod |