Skip to main content
Glama

Install from Library

install_from_library

Install chatmodes or instructions from the Mode Manager MCP library to enhance VS Code functionality.

Instructions

Install a chatmode or instruction from the Mode Manager MCP Library.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesThe name of the item to install from the library
filenameNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • MCP tool handler for 'install_from_library', including schema annotations, registration, and thin wrapper logic that delegates to LibraryManager.install_from_library.
    @app.tool(
        name="install_from_library",
        description="Install a chatmode or instruction from the Mode Manager MCP Library.",
        tags={"public", "library"},
        annotations={
            "idempotentHint": False,
            "readOnlyHint": False,
            "title": "Install from Library",
            "parameters": {
                "name": "The name of the chatmode or instruction to install from the library. Use browse_mode_library() to see available items.",
                "filename": "Optional custom filename for the installed item. If not provided, the default filename from the library will be used.",
            },
            "returns": "Returns a success message with details about the installed item (filename, source URL, type), or an error message if the installation failed.",
        },
        meta={"category": "library"},
    )
    def install_from_library(
        name: Annotated[str, "The name of the item to install from the library"],
        filename: Annotated[Optional[str], "Optional custom filename for the installed item"] = None,
    ) -> str:
        """Install a chatmode or instruction from the Mode Manager MCP Library."""
        if read_only:
            return "Error: Server is running in read-only mode"
        try:
            result = library_manager.install_from_library(name, filename)
            if result["status"] == "success":
                return f"{result['message']}\n\nFilename: {result['filename']}\nSource: {result['source_url']}\nType: {result['type'].title()}\n\nThe {result['type']} is now available in VS Code!"
            else:
                return f"Installation failed: {result.get('message', 'Unknown error')}"
        except FileOperationError as e:
            return f"Error installing from library: {str(e)}"
        except Exception as e:
            return f"Unexpected error installing from library: {str(e)}"
  • Core helper method in LibraryManager that implements the installation logic: finds item, fetches content from URL, parses, creates/updates chatmode or instruction file with source tracking.
    def install_from_library(self, name: str, custom_filename: Optional[str] = None) -> Dict[str, Any]:
        """
        Install a chatmode or instruction from the library.
    
        Args:
            name: Name of the item to install
            custom_filename: Custom filename (optional)
    
        Returns:
            Installation result
        """
        try:
            # Find the item in the library
            item = self.get_library_item(name)
            if not item:
                raise FileOperationError(f"Item '{name}' not found in library")
    
            item_type = item["type"]
            item_data = item["data"]
            content_url = item_data.get("content_location")
    
            if not content_url:
                raise FileOperationError(f"No content location found for '{name}'")
    
            # Determine filename
            filename = custom_filename or item_data.get("install_name") or f"{name}.{item_type}.md"
    
            # Fetch the content from the URL
            logger.info(f"Fetching {item_type} content from: {content_url}")
    
            req = urllib.request.Request(content_url, headers={"User-Agent": "Mode-Manager-MCP/1.0"})
    
            with urllib.request.urlopen(req, timeout=30) as response:
                content = response.read()
    
            # Try different encodings
            for encoding in ["utf-8", "utf-8-sig", "cp1252", "latin1"]:
                try:
                    file_content = content.decode(encoding)
                    break
                except UnicodeDecodeError:
                    continue
            else:
                raise FileOperationError("Could not decode file content with any supported encoding")
    
            # Install based on type
            if item_type == "chatmode":
                # Parse the content to extract frontmatter and content
                import tempfile
                from pathlib import Path
    
                from .simple_file_ops import parse_frontmatter_file
    
                frontmatter, content_text = parse_frontmatter(file_content)
    
                # Create the chatmode
                success = self.chatmode_manager.create_chatmode(
                    filename,
                    frontmatter.get("description", item_data.get("description", "")),
                    content_text,
                    frontmatter.get("tools", []),
                )
    
                if success:
                    # Add source_url to track origin
                    updated_frontmatter = frontmatter.copy()
                    updated_frontmatter["source_url"] = content_url
                    updated_frontmatter["library_source"] = name
    
                    self.chatmode_manager.update_chatmode(
                        filename,
                        frontmatter=updated_frontmatter,
                        content=content_text,
                    )
    
                    return {
                        "status": "success",
                        "type": "chatmode",
                        "name": name,
                        "filename": filename,
                        "source_url": content_url,
                        "message": f"Successfully installed chatmode '{name}' as {filename}",
                    }
                else:
                    raise FileOperationError(f"Failed to create chatmode file: {filename}")
    
            elif item_type == "instruction":
                # Parse the content to extract frontmatter and content
                import tempfile
                from pathlib import Path
    
                from .simple_file_ops import parse_frontmatter_file
    
                frontmatter, content_text = parse_frontmatter(file_content)
    
                # Create the instruction
                success = self.instruction_manager.create_instruction(
                    filename,
                    frontmatter.get("description", item_data.get("description", "")),
                    content_text,
                )
    
                if success:
                    # Add source_url to track origin
                    updated_frontmatter = frontmatter.copy()
                    updated_frontmatter["source_url"] = content_url
                    updated_frontmatter["library_source"] = name
    
                    self.instruction_manager.update_instruction(
                        filename,
                        frontmatter=updated_frontmatter,
                        content=content_text,
                    )
    
                    return {
                        "status": "success",
                        "type": "instruction",
                        "name": name,
                        "filename": filename,
                        "source_url": content_url,
                        "message": f"Successfully installed instruction '{name}' as {filename}",
                    }
                else:
                    raise FileOperationError(f"Failed to create instruction file: {filename}")
    
            else:
                raise FileOperationError(f"Unknown item type: {item_type}")
    
        except urllib.error.URLError as e:
            raise FileOperationError(f"Could not fetch content from {content_url}: {str(e)}")
        except Exception as e:
            raise FileOperationError(f"Error installing '{name}' from library: {str(e)}")
  • Top-level tool registration function that calls register_library_tools(), which defines and registers the install_from_library tool.
    def register_all_tools() -> None:
        """Register all tools with the server."""
        register_instruction_tools()
        register_chatmode_tools()
        register_library_tools()
        register_memory_tools()
        register_remember_tools()
  • Helper method to retrieve specific library item by name, used by install_from_library.
    def get_library_item(self, name: str) -> Optional[Dict[str, Any]]:
        """
        Get a specific item from the library by name.
    
        Args:
            name: Name of the chatmode or instruction
    
        Returns:
            Item data if found, None otherwise
        """
        try:
            library = self._fetch_library()
    
            # Search in chatmodes
            for chatmode in library.get("chatmodes", []):
                if chatmode.get("name") == name:
                    return {"type": "chatmode", "data": chatmode}
    
            # Search in instructions
            for instruction in library.get("instructions", []):
                if instruction.get("name") == name:
                    return {"type": "instruction", "data": instruction}
    
            return None
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=false and idempotentHint=false, implying a non-read-only, non-idempotent operation, which aligns with 'Install' as a write action. The description adds value by specifying the source ('from the Mode Manager MCP Library'), but doesn't disclose behavioral traits like installation effects (e.g., overwriting existing items), authentication needs, or rate limits. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action and resource. It avoids redundancy and wastes no words, making it easy to parse quickly. This optimal structure supports agent decision-making without unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (a write operation with 2 parameters), annotations cover safety hints, and an output schema exists (so return values are documented elsewhere). However, the description lacks context on installation behavior (e.g., side effects) and parameter usage, leaving gaps. It's minimally adequate but incomplete for informed use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50%, with 'name' documented but 'filename' lacking a description. The description doesn't add meaning beyond the schema; it doesn't explain what 'name' refers to (e.g., library identifier) or when 'filename' is used (e.g., for custom naming). With partial coverage, the description fails to compensate, resulting in a baseline score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Install') and the resource ('a chatmode or instruction from the Mode Manager MCP Library'), which distinguishes it from siblings like 'create_chatmode' or 'get_chatmode'. However, it doesn't explicitly differentiate from 'update_chatmode_from_source' or 'refresh_library', which might involve similar library operations, leaving some ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing to browse the library first), exclusions (e.g., not for local files), or comparisons to siblings like 'create_chatmode' (for new items) or 'update_chatmode_from_source' (for updates). This lack of context could lead to misuse.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/NiclasOlofsson/mode-manager-mcp'

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