# -*- coding: utf-8 -*-importtypingasTimportjsonimportenumimportdataclassesfrompathlibimportPathfrom.os_platformimportIS_WINDOWS,IS_MACOS,IS_LINUX@dataclasses.dataclassclassMcp:""" Represents a Model Context Protocol (MCP) server configuration. :param name: The name of the MCP server. :param settings: The settings for the MCP server, typically including command and arguments. """name:str=dataclasses.field()settings:dict[str,T.Any]=dataclasses.field()
[docs]defget_default_claude_desktop_config_path()->Path:# pragma: no cover""" See https://modelcontextprotocol.io/quickstart/user - macOS: ~/Library/Application Support/Claude/claude_desktop_config.json - Windows: %APPDATA%\Claude\claude_desktop_config.json """ifIS_MACOS:return(Path.home()/"Library"/"Application Support"/"Claude"/"claude_desktop_config.json")elifIS_WINDOWS:importosappdata=os.environ.get("APPDATA")ifappdata:returnPath(appdata)/"Claude"/"claude_desktop_config.json"else:# Fallback to typical Windows path if APPDATA is not setreturn(Path.home()/"AppData"/"Roaming"/"Claude"/"claude_desktop_config.json")elifIS_LINUX:# pragma: no coverreturnPath.home()/".config"/"Claude"/"claude_desktop_config.json"else:# pragma: no coverraiseOSError("Unsupported operating system")
[docs]defenable_mcp_server(config:dict[str,T.Any],name:str,settings:dict[str,T.Any],)->bool:""" Enable an MCP server by setting its configuration in the provided dictionary. This is an idempotent operation - no error if the server already exists with the same settings. :param config: The configuration dictionary to modify. :param name: The name of the MCP server. :param settings: The settings for the MCP server. :return: True if the configuration was changed, False if it was unchanged. """if"mcpServers"notinconfig:config["mcpServers"]={name:settings,}returnTrueifnameinconfig["mcpServers"]:existing_settings=config["mcpServers"][name]ifexisting_settings==settings:returnFalseelse:config["mcpServers"][name]=settingsreturnTrueelse:config["mcpServers"][name]=settingsreturnTrue
[docs]defdisable_mcp_server(config:dict[str,T.Any],name:str,)->bool:""" Remove an MCP server by deleting its entry from the provided configuration dictionary. This is an idempotent operation - no error if the server doesn't exist. :param config: The configuration dictionary to modify. :param name: The name of the MCP server to remove. :return: True if the configuration was changed, False if it was unchanged. """if"mcpServers"inconfigandnameinconfig["mcpServers"]:delconfig["mcpServers"][name]returnTruereturnFalse
[docs]defread(self)->dict[str,T.Any]:""" Read the configuration from the file. """returnjson.loads(self.path.read_text(encoding="utf-8"))
[docs]defwrite(self,config:dict[str,T.Any]):""" Write the configuration to the file. """self.path.write_text(json.dumps(config,indent=4),encoding="utf-8")
[docs]@classmethoddefapply(cls,wanted_mcps:T.Union[set["BaseMcpEnum"],list["BaseMcpEnum"]],cdc:ClaudeDesktopConfig,)->bool:""" Apply the MCP configuration to the Claude Desktop Config. This method should be overridden by subclasses to define Mcp Enumerations. :param wanted_mcps: A set of MCPs that should be enabled. :param cdc: An instance of ClaudeDesktopConfig to read and write the configuration. :return: True if the configuration was changed, False if it was unchanged. """config=cdc.read()flag_list=list()formcp_enumincls:ifmcp_enuminwanted_mcps:flag=enable_mcp_server(config,name=mcp_enum.value.name,settings=mcp_enum.value.settings,)else:flag=disable_mcp_server(config,name=mcp_enum.value.name,)flag_list.append(flag)ifany(flag_list):cdc.write(config)returnTruereturnFalse