Skip to main content
Glama

migrate_mcp_config

Transfer configuration and rules between IDEs using this tool to maintain consistent AI assistance across development environments. Automatically uses current directory if project path is omitted or invalid.

Instructions

Migrate MCP configuration between different IDEs.

This tool helps migrate configuration and rules between different IDEs,
ensuring consistent AI assistance across different environments.

Note: If project_path is omitted, not a string, or invalid, the current working
directory will be used automatically.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
from_ideNoSource IDE to migrate from. Valid options: cursor, windsurf-next, windsurf, cline, roo, claude-desktopcursor
project_pathNoPath to the project. If not provided or invalid, the current working directory will be used
to_ideNoTarget IDE to migrate to. Valid options: cursor, windsurf-next, windsurf, cline, roo, claude-desktop

Implementation Reference

  • The primary handler for the 'migrate_mcp_config' tool. Decorated with @mcp.tool() for FastMCP registration. Validates parameters using Pydantic Fields (serving as schema), gets project path, performs migration via helper, handles errors, and returns structured JSON response.
    @mcp.tool()
    def migrate_mcp_config(
        project_path: Optional[str] = Field(
            description="Path to the project. If not provided or invalid, the current working directory will be used",
            default=None,
        ),
        from_ide: str = Field(
            description=f"Source IDE to migrate from. Valid options: {', '.join(MCP_IDE_PATHS.keys())}",
            default="cursor",
        ),
        to_ide: str = Field(
            description=f"Target IDE to migrate to. Valid options: {', '.join(MCP_IDE_PATHS.keys())}",
            default=None,
        ),
    ) -> str:
        """
        Migrate MCP configuration between different IDEs.
    
        This tool helps migrate configuration and rules between different IDEs,
        ensuring consistent AI assistance across different environments.
    
        Note: If project_path is omitted, not a string, or invalid, the current working
        directory will be used automatically.
        """
        # Extract actual values if they're Field objects
        if hasattr(project_path, "default"):
            project_path = project_path.default
        if hasattr(from_ide, "default"):
            from_ide = from_ide.default
        if hasattr(to_ide, "default"):
            to_ide = to_ide.default
    
        # Check if we have a target IDE
        if to_ide is None:
            return json.dumps(
                {
                    "success": False,
                    "error": "No target IDE specified",
                    "message": "Please specify a target IDE to migrate to",
                    "project_path": project_path,
                    "from_ide": from_ide,
                    "to_ide": None,
                },
                indent=2,
            )
    
        # Check if source IDE is valid
        if from_ide not in MCP_IDE_PATHS:
            return json.dumps(
                {
                    "success": False,
                    "error": f"Unknown source IDE: {from_ide}",
                    "message": f"Supported IDE types for MCP migration are: {', '.join(MCP_IDE_PATHS.keys())}",
                    "project_path": project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                },
                indent=2,
            )
    
        # Check if target IDE is valid
        if to_ide not in MCP_IDE_PATHS:
            return json.dumps(
                {
                    "success": False,
                    "error": f"Unknown target IDE: {to_ide}",
                    "message": f"Supported IDE types for MCP migration are: {', '.join(MCP_IDE_PATHS.keys())}",
                    "project_path": project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                },
                indent=2,
            )
    
        # Check if source and target are the same
        if from_ide == to_ide:
            return json.dumps(
                {
                    "success": False,
                    "error": "Source and target IDEs are the same",
                    "message": "Source and target IDEs must be different",
                    "project_path": project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                },
                indent=2,
            )
    
        # Get project settings
        settings_json = get_project_settings(proposed_path=project_path)
        settings = json.loads(settings_json)
    
        if not settings["success"]:
            return json.dumps(
                {
                    "success": False,
                    "error": settings.get("error", "Failed to get project settings"),
                    "message": "Please provide a valid project path. You can look up project path and try again.",
                    "project_path": project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                },
                indent=2,
            )
    
        actual_project_path = settings["project_path"]
    
        try:
            # Perform the migration
            success, error_message, conflicts, conflict_details = migrate_config(
                from_ide=from_ide, to_ide=to_ide
            )
    
            if not success:
                return json.dumps(
                    {
                        "success": False,
                        "error": error_message,
                        "message": f"Failed to migrate configuration: {error_message}",
                        "project_path": actual_project_path,
                        "from_ide": from_ide,
                        "to_ide": to_ide,
                    },
                    indent=2,
                )
    
            # Return success response
            return json.dumps(
                {
                    "success": True,
                    "project_path": actual_project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                    "migrated_rules": True,
                    "conflicts": conflicts,
                    "conflict_details": conflict_details,
                    "message": f"Migrated configuration from {from_ide} to {to_ide}",
                },
                indent=2,
            )
    
        except Exception as e:
            return json.dumps(
                {
                    "success": False,
                    "error": str(e),
                    "message": f"An error occurred during migration: {str(e)}",
                    "project_path": actual_project_path,
                    "from_ide": from_ide,
                    "to_ide": to_ide,
                },
                indent=2,
            )
  • Core helper function implementing the MCP config migration logic: resolves IDE config paths, reads source/target configs, detects and details conflicts in mcpServers, optionally backs up target, merges configurations, writes result.
    def migrate_config(
        from_ide: str, to_ide: str, backup: bool = True
    ) -> Tuple[bool, Optional[str], List[str], Dict]:
        """
        Migrate MCP configuration from one IDE to another.
    
        Args:
            from_ide: Source IDE name
            to_ide: Target IDE name
            backup: Whether to create backups before modifying files
    
        Returns:
            Tuple of (success, error_message, conflicts, conflict_details)
            - success: Whether the operation completed (may be True even with conflicts)
            - error_message: Error message if operation failed
            - conflicts: List of conflicting server names
            - conflict_details: Dictionary of detailed conflict information
        """
        try:
            # Get paths
            source_path = get_ide_path(from_ide)
            target_path = get_ide_path(to_ide)
    
            # Check if source exists
            if not os.path.exists(source_path):
                return False, f"Source configuration not found at {source_path}", [], {}
    
            # Read source configuration
            try:
                with open(source_path, "r") as f:
                    source_config = json.load(f)
            except json.JSONDecodeError:
                return (
                    False,
                    f"Invalid JSON in source configuration at {source_path}",
                    [],
                    {},
                )
    
            # Read target configuration if it exists
            target_config = {}
            if os.path.exists(target_path):
                try:
                    with open(target_path, "r") as f:
                        target_config = json.load(f)
                except json.JSONDecodeError:
                    return (
                        False,
                        f"Invalid JSON in target configuration at {target_path}",
                        [],
                        {},
                    )
    
            # Detect conflicts
            conflicts = detect_conflicts(source_config, target_config)
    
            # Generate conflict details if there are conflicts
            conflict_details = {}
            if conflicts:
                conflict_details = get_conflict_details(source_config, target_config, conflicts)
    
            # Create backup of target if it exists and backup is requested
            if backup and os.path.exists(target_path):
                backup_path = create_backup(target_path)
                if not backup_path:
                    return False, f"Failed to create backup of {target_path}", [], {}
    
            # Return if we found conflicts - user needs to resolve them
            if conflicts:
                return True, None, conflicts, conflict_details
    
            # No conflicts, perform basic merge
            merged_config = merge_configurations(source_config, target_config, {})
    
            # Create target directory if it doesn't exist
            os.makedirs(os.path.dirname(target_path), exist_ok=True)
    
            # Write merged configuration
            with open(target_path, "w") as f:
                json.dump(merged_config, f, indent=2)
    
            return True, None, [], {}
    
        except Exception as e:
            return False, str(e), [], {}
  • Dictionary defining platform-specific configuration file paths for each supported IDE. Imported as MCP_IDE_PATHS and used for path resolution (get_ide_path) and parameter validation in the handler.
    IDE_PATHS = {
        "cursor": {
            "darwin": "~/.cursor/mcp.json",
            "linux": "~/.cursor/mcp.json",
            "windows": "%APPDATA%\\Cursor\\mcp.json",
        },
        "windsurf-next": {
            "darwin": "~/.codeium/windsurf-next/mcp_config.json",
            "linux": "~/.codeium/windsurf-next/mcp_config.json",
            "windows": "%APPDATA%\\Codeium\\windsurf-next\\mcp_config.json",
        },
        "windsurf": {
            "darwin": "~/.codeium/windsurf/mcp_config.json",
            "linux": "~/.codeium/windsurf/mcp_config.json",
            "windows": "%APPDATA%\\Codeium\\windsurf\\mcp_config.json",
        },
        "cline": {
            "darwin": "~/Library/Application Support/Code - Insiders/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
            "linux": "~/.config/Code - Insiders/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
            "windows": "%APPDATA%\\Code - Insiders\\User\\globalStorage\\saoudrizwan.claude-dev\\settings\\cline_mcp_settings.json",
        },
        "roo": {
            "darwin": "~/Library/Application Support/Code - Insiders/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json",
            "linux": "~/.config/Code - Insiders/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json",
            "windows": "%APPDATA%\\Code - Insiders\\User\\globalStorage\\rooveterinaryinc.roo-cline\\settings\\cline_mcp_settings.json",
        },
        "claude-desktop": {
            "darwin": "~/Library/Application Support/Claude/claude_desktop_config.json",
            "linux": "~/.config/Claude/claude_desktop_config.json",
            "windows": "%APPDATA%\\Claude\\claude_desktop_config.json",
        },
    }
  • Lists 'migrate_mcp_config' in SUPPORTED_TOOLS array used by call_tool dispatcher.
    SUPPORTED_TOOLS = [
        "initialize_ide",
        "initialize_ide_rules",
        "get_project_settings",
        "prime_context",
        "migrate_mcp_config",
        "think",
        "get_thoughts",
        "clear_thoughts",
        "get_thought_stats",
        "process_natural_language",
    ]
  • Dispatcher in call_tool function maps 'migrate-mcp-config' to migrate_mcp_config handler call.
    elif fastmcp_tool_name == "migrate-mcp-config":
        result = migrate_mcp_config(**arguments)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/smian0/mcp-agile-flow'

If you have feedback or need assistance with the MCP directory API, please join our Discord server