Internal Logic for Bulk Operations Filtering in MCP OpenStack Ops

The MCP OpenStack Ops toolkit implements a seven-step filtering pipeline that validates input parameters, queries OpenStack APIs for candidate resources, applies secondary local filters like flavor_contains, deduplicates results, and executes bulk actions with post-operation status verification.

The mcp-openstack-ops repository provides powerful bulk management capabilities for OpenStack resources through tools like set_instance and set_networks. Understanding the internal logic for bulk operations filtering reveals how parameters such as name_contains and status translate into efficient API queries and local processing. This analysis examines the source code implementation to show exactly how the toolkit discovers, filters, and acts upon large resource sets without requiring explicit name enumeration.

The Seven-Step Filtering Pipeline

Step 1: Targeting Mode Detection

The tools first determine whether the user provided direct target names or filter parameters. In src/mcp_openstack_ops/tools/set_instance.py and src/mcp_openstack_ops/tools/set_networks.py, the code checks has_direct_targets against has_filter_params. If both are present, the tool raises a mutually-exclusive error; if neither is present, it returns an error requesting explicit input.

Step 2: Building the Candidate Set

When operating in filter mode, the tools query OpenStack to build an initial candidate list. For instances, set_instance calls _search_instances from src/mcp_openstack_ops/services/compute.py with the name_contains parameter (lines L116-L130 in set_instance.py). If a status filter is provided, it additionally calls _get_instances_by_status, passing status.upper() to ensure case-insensitive matching.

Step 3: Applying Secondary Filters

After retrieving the initial candidate set, the code applies additional criteria locally. In set_instance.py, the implementation checks flavor_contains and image_contains by iterating through results and performing substring matches against instance.get('flavor', '') and instance.get('image', ''). This local filtering reduces API call overhead by refining results client-side.

Step 4: Deduplication and Name Extraction

To handle resources that match multiple filter criteria, the tools maintain a seen_ids set. As implemented in set_instance.py, the code tracks unique resource IDs before extracting the name field for each entry. This prevents duplicate operations when a resource matches both name_contains and status filters simultaneously.

Step 5: Aborting on Empty Results

If filtering yields no matches, the tools assemble descriptive error messages. The implementation in set_instance.py and set_networks.py constructs a "no resources found matching filters" response that includes the specific filter descriptors provided by the user, enabling rapid troubleshooting of overly restrictive criteria.

Step 6: Performing Bulk Operations

Once the final name_list is prepared, the tools iterate through each resource and execute the requested action. In set_instance.py and set_networks.py, the code calls _set_instance or _set_networks for each target, recording success or failure states in a results aggregator.

Step 7: Post-Action Status Verification

After completing all operations, the tools verify final states. The code in set_instance.py and set_networks.py sleeps briefly to allow OpenStack to process changes, then queries each resource using _get_instance_by_name or _get_resource_status_by_name. The final response includes a colored status indicator (🟢, 🟡, 🔴) for each resource along with operation summaries.

Implementation Examples by Resource Type

Instance Filtering in set_instance.py

The instance filtering logic combines API searches with local substring matching:


# Detect filter mode

has_filter_params = any([name_contains, status, flavor_contains, image_contains])

# Build candidate list

if name_contains:
    result = _search_instances(search_term=name_contains,
                               search_fields=['name'],
                               limit=200,
                               include_inactive=True)
    # result may be a dict with 'instances' or a plain list

if status:
    status_instances = _get_instances_by_status(status.upper())
    search_results.extend(status_instances)

# Apply extra filters

if flavor_contains or image_contains:
    filtered_results = []
    for instance in search_results:
        if flavor_contains and flavor_contains.lower() not in instance.get('flavor', '').lower():
            continue
        if image_contains and image_contains.lower() not in instance.get('image', '').lower():
            continue
        filtered_results.append(instance)
    search_results = filtered_results

This implementation in src/mcp_openstack_ops/tools/set_instance.py demonstrates how the tool handles complex filtering scenarios while maintaining compatibility with varying OpenStack API response formats.

Network Filtering in set_networks.py

Network filtering follows a similar pattern but operates against the full network list retrieved from src/mcp_openstack_ops/services/network.py:


# Retrieve all networks, then apply the two possible filters

all_networks_info = _get_network_details("all")
for network in all_networks_info:
    network_name = network.get('name', '')
    network_status = network.get('status', '')

    if name_contains and name_contains.lower() not in network_name.lower():
        continue
    if status and status.upper() != network_status.upper():
        continue
    target_names.append(network_name)

As shown in src/mcp_openstack_ops/tools/set_networks.py, this approach retrieves all networks once, then applies filters locally to minimize API traffic.

Usage Examples

Practical implementations of the bulk operations filtering logic include:


# Stop all ACTIVE instances whose name contains "dev"

await set_instance(name_contains="dev", status="ACTIVE", action="stop")

# Delete every network whose name includes "test" and is currently DOWN

await set_networks(action="delete", name_contains="test", status="DOWN")

Both calls trigger the seven-step pipeline automatically, discovering matching resources and applying the requested action without manual name enumeration.

Key Files and Functions

Understanding the internal logic for bulk operations filtering requires familiarity with these components:

Summary

  • The bulk operations filtering logic enforces mutual exclusivity between direct target names and filter parameters at validation time.
  • Initial candidates are retrieved through OpenStack API calls (_search_instances, _get_instances_by_status), while secondary filtering occurs locally to optimize performance.
  • A deduplication mechanism using seen_ids prevents duplicate operations when resources match multiple filter criteria.
  • The pipeline includes comprehensive error handling for empty result sets and provides detailed post-operation status verification with visual indicators.
  • Similar filtering architectures are implemented across set_instance, set_networks, and set_snapshot tools, ensuring consistent behavior across resource types.

Frequently Asked Questions

How does the toolkit handle case sensitivity in filter parameters?

The tools normalize case sensitivity by converting status parameters to uppercase using .upper() before comparison, while name-related filters use .lower() for substring matching. This ensures that filters like status="active" and status="ACTIVE" match identically, and name_contains="Dev" captures resources named "development" or "DEV-01".

What happens if both direct names and filter parameters are provided?

The code explicitly prevents this combination. In set_instance.py and set_networks.py, the tool checks for the presence of both has_direct_targets and has_filter_params, raising a mutually-exclusive error if both are true. This design prevents ambiguous targeting and ensures predictable operation scopes.

Can filters be combined to match multiple criteria simultaneously?

Yes, filters within the same category combine with AND logic. For example, providing both name_contains="prod" and status="ACTIVE" returns only instances that satisfy both conditions. The code iterates through all candidates and applies each active filter sequentially, keeping only resources that pass every check.

Why does the network filter retrieve all networks instead of using a search API?

The set_networks implementation calls _get_network_details("all") from src/mcp_openstack_ops/services/network.py and performs client-side filtering because OpenStack Neutron's API doesn't provide substring search capabilities equivalent to Nova's instance search. This approach trades bandwidth for functionality, retrieving the full list once and applying name_contains and status filters locally in the Python loop shown at lines L25-L45.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →