Skip to main content
Glama
AgentWong

IAC Memory MCP Server

by AgentWong

get_module_version_compatibility

Check if a specific Ansible module works with a target collection version to prevent compatibility issues in IaC deployments.

Instructions

Check module compatibility across collection versions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
collection_nameYesName of the Ansible collection
module_nameYesName of the module to check
versionYesTarget collection version to check compatibility against

Implementation Reference

  • Main handler function executing the tool: logs input, fetches compatibility data from DB helper, formats detailed output including issues, breaking changes, and version history as TextContent.
    async def handle_get_module_version_compatibility(
        db: Any, arguments: Dict[str, Any], operation_id: str
    ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
        """Handle get_module_version_compatibility tool."""
        try:
            logger.info(
                "Getting module version compatibility",
                extra={
                    "collection_name": arguments["collection_name"],
                    "module_name": arguments["module_name"],
                    "version": arguments["version"],
                    "operation_id": operation_id,
                },
            )
    
            try:
                # Get compatibility info
                result = get_module_compatibility(
                    db,
                    arguments["collection_name"],
                    arguments["module_name"],
                    arguments["version"],
                )
            except Exception as db_error:
                error_msg = str(db_error)
                logger.error(error_msg, extra={"operation_id": operation_id})
                return [TextContent(type="text", text=error_msg)]
    
            # Format output
            output = [
                "Module Compatibility Check:",
                f"Module: {result['module_name']}",
                f"Collection: {result['collection_name']}",
                f"Target Version: {result['target_version']}",
                f"Current Version: {result['current_version']}",
                f"Is Compatible: {'Yes' if result['is_compatible'] else 'No'}",
                "\nCompatibility Issues:",
            ]
    
            if not result["compatibility_issues"]:
                output.append("- No issues found")
            else:
                for issue in result["compatibility_issues"]:
                    output.append(f"- {issue}")
    
            if result["breaking_changes"]:
                output.extend(
                    [
                        "\nBreaking Changes:",
                        *[f"- {change}" for change in result["breaking_changes"]],
                    ]
                )
    
            output.extend(
                [
                    "\nVersion History:",
                    *[
                        f"- {v['collection_version']} (Module v{v['module_version']}) - {v['released']}"
                        for v in result["version_history"]
                    ],
                ]
            )
    
            return [TextContent(type="text", text="\n".join(output))]
    
        except Exception as e:
            error_msg = f"Failed to check module version compatibility: {str(e)}"
            logger.error(error_msg, extra={"operation_id": operation_id})
            raise McpError(
                types.ErrorData(
                    code=types.INTERNAL_ERROR,
                    message=error_msg,
                    data={
                        "tool": "get_module_version_compatibility",
                        "operation_id": operation_id,
                    },
                )
            )
  • JSON schema defining input parameters: collection_name, module_name, version (all required strings). Used for validation.
    "get_module_version_compatibility": {
        "type": "object",
        "description": "Check module compatibility across collection versions",
        "required": ["collection_name", "module_name", "version"],
        "properties": {
            "collection_name": {
                "type": "string",
                "description": "Name of the Ansible collection",
            },
            "module_name": {
                "type": "string",
                "description": "Name of the module to check",
            },
            "version": {
                "type": "string",
                "description": "Target collection version to check compatibility against",
            },
        },
    },
  • Registration dictionary mapping tool name 'get_module_version_compatibility' to its handler function, alongside other Ansible tools.
    ansible_tool_handlers = {
        "get_ansible_collection_info": handle_get_ansible_collection_info,
        "list_ansible_collections": handle_list_ansible_collections,
        "get_collection_version_history": handle_get_collection_version_history,
        "get_ansible_module_info": handle_get_ansible_module_info,
        "list_collection_modules": handle_list_collection_modules,
        "get_module_version_compatibility": handle_get_module_version_compatibility,
        "add_ansible_collection": handle_add_ansible_collection,
        "add_ansible_module": handle_add_ansible_module,
        "update_collection_version": handle_update_collection_version,
        "update_module_version": handle_update_module_version,
    }
  • Database helper function that performs SQL queries to retrieve module data and history, compares schemas for compatibility (e.g., new required fields, removed properties), and computes results used by the handler.
    def get_module_compatibility(
        db: DatabaseManager, collection_name: str, module_name: str, version: str
    ) -> Dict:
        """Check module compatibility across collection versions.
    
        Args:
            db: Database manager instance
            collection_name: Name of the collection
            module_name: Name of the module
            version: Target version to check compatibility against
    
        Returns:
            Dict containing compatibility status and any potential issues
        """
        logger.info(
            "Getting module compatibility info",
            extra={
                "collection_name": collection_name,
                "module_name": module_name,
                "version": version,
                "operation": "get_module_compatibility",
            },
        )
    
        try:
            with db.get_connection() as conn:
                conn.execute("PRAGMA busy_timeout = 5000")  # 5 second timeout
    
                # Get latest version of the module
                current = conn.execute(
                    """
                    SELECT m.*, c.name as collection_name, c.version as collection_version
                    FROM ansible_modules m
                    JOIN ansible_collections c ON m.collection_id = c.id
                    WHERE c.name = ? AND m.name = ?
                    ORDER BY m.version DESC
                    LIMIT 1
                    """,
                    (collection_name, module_name),
                ).fetchone()
    
                if not current:
                    raise DatabaseError(
                        f"Module '{module_name}' not found in collection '{collection_name}'"
                    )
    
                # Get version history
                history = conn.execute(
                    """
                    SELECT m.version as module_version,
                           c.version as collection_version,
                           m.schema,
                           c.updated_at as released
                    FROM ansible_modules m
                    JOIN ansible_collections c ON m.collection_id = c.id
                    WHERE c.name = ? AND m.name = ?
                    ORDER BY c.updated_at DESC
                    """,
                    (collection_name, module_name),
                ).fetchall()
    
                # Check compatibility
                result = {
                    "module_name": module_name,
                    "collection_name": collection_name,
                    "target_version": version,
                    "current_version": current["version"],
                    "is_compatible": True,
                    "compatibility_issues": [],
                    "breaking_changes": [],
                    "version_history": [],
                }
    
                # Add version history
                for h in history:
                    result["version_history"].append(
                        {
                            "module_version": h["module_version"],
                            "collection_version": h["collection_version"],
                            "released": h["released"],
                        }
                    )
    
                # Compare schemas to detect breaking changes
                target = None
                for h in history:
                    if h["collection_version"] == version:
                        target = h
                        break
    
                if not target:
                    result["is_compatible"] = False
                    result["compatibility_issues"].append(
                        f"Target version {version} not found in module history"
                    )
                    return result
    
                # Basic schema comparison
                try:
                    import json
    
                    current_schema = json.loads(current["schema"])
                    target_schema = json.loads(target["schema"])
    
                    # Check for required fields in current that weren't required in target
                    if "required" in target_schema or "required" in current_schema:
                        current_required = set(current_schema.get("required", []))
                        target_required = set(target_schema.get("required", []))
                        
                        new_required = current_required - target_required
                        if new_required:
                            result["is_compatible"] = False
                            result["breaking_changes"].append(
                                f"Required fields added: {', '.join(new_required)}"
                            )
    
                    # Check for removed properties
                    if "properties" in current_schema and "properties" in target_schema:
                        removed_props = set(current_schema["properties"].keys()) - set(
                            target_schema["properties"].keys()
                        )
                        if removed_props:
                            result["breaking_changes"].append(
                                f"Properties removed: {', '.join(removed_props)}"
                            )
    
                    # Add compatibility notes
                    if result["breaking_changes"]:
                        result["compatibility_issues"].extend(result["breaking_changes"])
                    else:
                        result["compatibility_issues"].append(
                            "No breaking changes detected"
                        )
    
                except json.JSONDecodeError:
                    result["compatibility_issues"].append(
                        "Unable to compare schemas - invalid JSON format"
                    )
    
                return result

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/AgentWong/iac-memory-mcp-server'

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