{"record":{"id":"ffa903b7dba284da","repo":"agentscope-ai/agentscope","slug":"disable-tools-should-be-a-list-of-strings-but-got","errorCode":null,"errorMessage":"Disable tools should be a list of strings, but got {self.disable_tools}.","messagePattern":"Disable tools should be a list of strings, but got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/mcp/_mcp_client.py","lineNumber":149,"sourceCode":"            raise ValueError(\n                \"STDIO MCP must be stateful (is_stateful=True).\",\n            )\n\n        # Check arguments for self.enable_tools and disable_tools\n        if self.enable_tools is not None:\n            if not isinstance(self.enable_tools, list) or any(\n                not isinstance(_, str) for _ in self.enable_tools\n            ):\n                raise ValueError(\n                    \"Enable tools should be a list of strings, but got \"\n                    f\"{self.enable_tools}.\",\n                )\n\n        if self.disable_tools is not None:\n            if not isinstance(self.disable_tools, list) or any(\n                not isinstance(_, str) for _ in self.disable_tools\n            ):\n                raise ValueError(\n                    \"Disable tools should be a list of strings, but got \"\n                    f\"{self.disable_tools}.\",\n                )\n\n        if self.enable_tools is not None and self.disable_tools is not None:\n            intersection = set(self.enable_tools).intersection(\n                set(self.disable_tools),\n            )\n            if len(intersection) != 0:\n                raise ValueError(\n                    f\"The tools in enable_tools and disable_tools \"\n                    f\"should not overlap, but got {intersection}.\",\n                )\n\n        # Initialize the underlying client\n        self._initialize_client()\n\n    def _initialize_client(self) -> None:","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/mcp/_mcp_client.py#L131-L167","documentation":"Same validation as enable_tools but for disable_tools: it must be None or a list of strings. Any other shape (bare string, set, list with non-string elements) raises this ValueError in model_post_init.","triggerScenarios":"MCPClient(..., disable_tools=\"dangerous_tool\") or disable_tools=[\"a\", None] or disable_tools=(\"a\",).","commonSituations":"Symmetric with enable_tools mistakes: scalar tool name passed directly, or filters loaded from user-supplied config without normalization.","solutions":["Use a list of strings: disable_tools=[\"dangerous_tool\"]","Normalize config values (list(map(str, ...))) before constructing the client"],"exampleFix":"// before\nclient = MCPClient(name=\"fs\", mcp_config=cfg, disable_tools=\"delete_file\")\n\n// after\nclient = MCPClient(name=\"fs\", mcp_config=cfg, disable_tools=[\"delete_file\"])","handlingStrategy":"validation","validationCode":"disable_tools = None if disable_tools is None else [str(t) for t in disable_tools]\nclient = MCPClient(name=n, mcp_config=cfg, disable_tools=disable_tools)","typeGuard":"def is_tool_name_list(v) -> bool:\n    return v is None or (isinstance(v, list) and all(isinstance(x, str) for x in v))","tryCatchPattern":"try:\n    MCPClient(name=n, mcp_config=cfg, disable_tools=disable_tools)\nexcept ValueError:\n    disable_tools = list(map(str, disable_tools or [])) or None","preventionTips":["Mirror the enable_tools rules for disable_tools","Validate both filters with one shared helper","Prefer tuples->list conversion when configs come from YAML"],"tags":["mcp","type-validation","tool-filtering"],"backgroundTag":"type-mismatch-validation","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}