Skip to main content
Glama

get_browser_tree

Retrieve a hierarchical tree of browser categories from Ableton Live to organize and navigate instruments, sounds, effects, and drum kits for music production workflows.

Instructions

Get a hierarchical tree of browser categories from Ableton.

Parameters:

  • category_type: Type of categories to get ('all', 'instruments', 'sounds', 'drums', 'audio_effects', 'midi_effects')

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
category_typeNoall

Implementation Reference

  • MCP tool handler for get_browser_tree. Proxies the command to Ableton remote script via socket, receives raw tree data, and formats it into a readable hierarchical string with indentation and paths.
    @mcp.tool()
    def get_browser_tree(ctx: Context, category_type: str = "all") -> str:
        """
        Get a hierarchical tree of browser categories from Ableton.
        
        Parameters:
        - category_type: Type of categories to get ('all', 'instruments', 'sounds', 'drums', 'audio_effects', 'midi_effects')
        """
        try:
            ableton = get_ableton_connection()
            result = ableton.send_command("get_browser_tree", {
                "category_type": category_type
            })
            
            # Check if we got any categories
            if "available_categories" in result and len(result.get("categories", [])) == 0:
                available_cats = result.get("available_categories", [])
                return (f"No categories found for '{category_type}'. "
                       f"Available browser categories: {', '.join(available_cats)}")
            
            # Format the tree in a more readable way
            total_folders = result.get("total_folders", 0)
            formatted_output = f"Browser tree for '{category_type}' (showing {total_folders} folders):\n\n"
            
            def format_tree(item, indent=0):
                output = ""
                if item:
                    prefix = "  " * indent
                    name = item.get("name", "Unknown")
                    path = item.get("path", "")
                    has_more = item.get("has_more", False)
                    
                    # Add this item
                    output += f"{prefix}• {name}"
                    if path:
                        output += f" (path: {path})"
                    if has_more:
                        output += " [...]"
                    output += "\n"
                    
                    # Add children
                    for child in item.get("children", []):
                        output += format_tree(child, indent + 1)
                return output
            
            # Format each category
            for category in result.get("categories", []):
                formatted_output += format_tree(category)
                formatted_output += "\n"
            
            return formatted_output
        except Exception as e:
            error_msg = str(e)
            if "Browser is not available" in error_msg:
                logger.error(f"Browser is not available in Ableton: {error_msg}")
                return f"Error: The Ableton browser is not available. Make sure Ableton Live is fully loaded and try again."
            elif "Could not access Live application" in error_msg:
                logger.error(f"Could not access Live application: {error_msg}")
                return f"Error: Could not access the Ableton Live application. Make sure Ableton Live is running and the Remote Script is loaded."
            else:
                logger.error(f"Error getting browser tree: {error_msg}")
                return f"Error getting browser tree: {error_msg}"
  • Helper implementation in Ableton remote script that interacts with Live's browser API to build the raw category tree dictionary for specified category_type, handling various browser roots like instruments, sounds, etc.
    def get_browser_tree(self, category_type="all"):
        """
        Get a simplified tree of browser categories.
        
        Args:
            category_type: Type of categories to get ('all', 'instruments', 'sounds', etc.)
            
        Returns:
            Dictionary with the browser tree structure
        """
        try:
            # Access the application's browser instance instead of creating a new one
            app = self.application()
            if not app:
                raise RuntimeError("Could not access Live application")
                
            # Check if browser is available
            if not hasattr(app, 'browser') or app.browser is None:
                raise RuntimeError("Browser is not available in the Live application")
            
            # Log available browser attributes to help diagnose issues
            browser_attrs = [attr for attr in dir(app.browser) if not attr.startswith('_')]
            self.log_message("Available browser attributes: {0}".format(browser_attrs))
            
            result = {
                "type": category_type,
                "categories": [],
                "available_categories": browser_attrs
            }
            
            # Helper function to process a browser item and its children
            def process_item(item, depth=0):
                if not item:
                    return None
                
                result = {
                    "name": item.name if hasattr(item, 'name') else "Unknown",
                    "is_folder": hasattr(item, 'children') and bool(item.children),
                    "is_device": hasattr(item, 'is_device') and item.is_device,
                    "is_loadable": hasattr(item, 'is_loadable') and item.is_loadable,
                    "uri": item.uri if hasattr(item, 'uri') else None,
                    "children": []
                }
                
                
                return result
            
            # Process based on category type and available attributes
            if (category_type == "all" or category_type == "instruments") and hasattr(app.browser, 'instruments'):
                try:
                    instruments = process_item(app.browser.instruments)
                    if instruments:
                        instruments["name"] = "Instruments"  # Ensure consistent naming
                        result["categories"].append(instruments)
                except Exception as e:
                    self.log_message("Error processing instruments: {0}".format(str(e)))
            
            if (category_type == "all" or category_type == "sounds") and hasattr(app.browser, 'sounds'):
                try:
                    sounds = process_item(app.browser.sounds)
                    if sounds:
                        sounds["name"] = "Sounds"  # Ensure consistent naming
                        result["categories"].append(sounds)
                except Exception as e:
                    self.log_message("Error processing sounds: {0}".format(str(e)))
            
            if (category_type == "all" or category_type == "drums") and hasattr(app.browser, 'drums'):
                try:
                    drums = process_item(app.browser.drums)
                    if drums:
                        drums["name"] = "Drums"  # Ensure consistent naming
                        result["categories"].append(drums)
                except Exception as e:
                    self.log_message("Error processing drums: {0}".format(str(e)))
            
            if (category_type == "all" or category_type == "audio_effects") and hasattr(app.browser, 'audio_effects'):
                try:
                    audio_effects = process_item(app.browser.audio_effects)
                    if audio_effects:
                        audio_effects["name"] = "Audio Effects"  # Ensure consistent naming
                        result["categories"].append(audio_effects)
                except Exception as e:
                    self.log_message("Error processing audio_effects: {0}".format(str(e)))
            
            if (category_type == "all" or category_type == "midi_effects") and hasattr(app.browser, 'midi_effects'):
                try:
                    midi_effects = process_item(app.browser.midi_effects)
                    if midi_effects:
                        midi_effects["name"] = "MIDI Effects"
                        result["categories"].append(midi_effects)
                except Exception as e:
                    self.log_message("Error processing midi_effects: {0}".format(str(e)))
            
            # Try to process other potentially available categories
            for attr in browser_attrs:
                if attr not in ['instruments', 'sounds', 'drums', 'audio_effects', 'midi_effects'] and \
                   (category_type == "all" or category_type == attr):
                    try:
                        item = getattr(app.browser, attr)
                        if hasattr(item, 'children') or hasattr(item, 'name'):
                            category = process_item(item)
                            if category:
                                category["name"] = attr.capitalize()
                                result["categories"].append(category)
                    except Exception as e:
                        self.log_message("Error processing {0}: {1}".format(attr, str(e)))
            
            self.log_message("Browser tree generated for {0} with {1} root categories".format(
                category_type, len(result['categories'])))
            return result
            
        except Exception as e:
            self.log_message("Error getting browser tree: {0}".format(str(e)))
            self.log_message(traceback.format_exc())
            raise

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/ahujasid/ableton-mcp'

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