# How the MCP Server Filters OpenStack Images by Visibility (Public, Community, Shared)

> Learn how the MCP server filters OpenStack images by visibility public community and shared for your projects using Glance image attributes and owner checks.

- Repository: [JungJungIn/mcp-openstack-ops](https://github.com/call518/mcp-openstack-ops)
- Tags: how-to-guide
- Published: 2026-02-26

---

**The MCP server filters images by inspecting each Glance image's `visibility` and `owner` attributes, returning public and community images to all projects while restricting private images to their owning project.**

The `call518/mcp-openstack-ops` repository implements visibility-based filtering for OpenStack Glance images within its MCP server tools. This article examines how the server determines image accessibility across public, community, shared, and private visibility types by analyzing the filtering logic in the Image service and its corresponding tool implementations.

## Visibility Filtering Implementation in the Image Service

The core filtering logic resides in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) between lines 34 and 52. When retrieving images, the service fetches all records from Glance using `conn.image.images()`, then applies project-scoped visibility rules to determine which records to return.

### The Five Visibility Rules

The algorithm evaluates each image against five specific conditions:

- **Public images**: Always included regardless of the requesting project.
- **Community images**: Always included and treated identically to public images in the filtering logic.
- **Shared images**: Included without additional membership validation; the code assumes shared images are accessible to the current context.
- **Private images**: Included only when the image's `owner` attribute matches `conn.current_project_id`.
- **Project-owned images**: Included as a fallback when the owner matches the current project, regardless of the visibility field value.

### Core Filtering Code

The following Python implementation from [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) (lines 34-52) demonstrates the exact filtering logic:

```python

# src/mcp_openstack_ops/services/image.py

# … lines 34‑52

visibility = getattr(image, 'visibility', 'private')
owner = getattr(image, 'owner', None)

include_image = False
if visibility in ['public', 'community']:
    include_image = True
elif visibility == 'shared':
    include_image = True          # all shared images are considered accessible

elif visibility == 'private' and owner == current_project_id:
    include_image = True
elif owner == current_project_id: # fallback for project‑owned images

    include_image = True

```

Both `get_image_list()` and `get_image_detail_list()` utilize this identical filtering block, ensuring consistent visibility enforcement across all image listing operations.

## Tools That Expose Visibility Controls

The MCP server exposes visibility filtering through dedicated tools that wrap the service layer functionality.

### Listing Images with Visibility Filters

The `list_images` and `list_images_detailed` tools invoke `get_image_list()` and `get_image_detail_list()` respectively. These service functions automatically apply the visibility logic described above, returning only images that satisfy the public, community, shared, or private-owned criteria.

### Modifying Image Visibility

The `set_image_visibility` tool provides a controlled interface for changing an image's visibility status. Located in [`src/mcp_openstack_ops/tools/set_image_visibility.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/tools/set_image_visibility.py) (lines 10-41), the tool performs several validation steps before executing the change.

First, the tool wrapper checks if the server is in read-only mode using `_is_modify_operation_allowed()`:

```python

# src/mcp_openstack_ops/tools/set_image_visibility.py

# … lines 10‑41

if not _is_modify_operation_allowed() and action.lower() in ['set']:
    return json.dumps({...})   # reject modification in read‑only env

result = _set_image_visibility(
    action=action,
    image_name=image_name,
    visibility=visibility if visibility else None
)

```

Then, the service function in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) (lines 442-456) validates that the requested visibility is one of the allowed values before applying the update:

```python

# src/mcp_openstack_ops/services/image.py

# … lines 442‑456

valid_visibilities = ['public', 'private', 'shared', 'community']
if visibility not in valid_visibilities:
    return {...}   # reject invalid value

conn.image.update_image(image.id, visibility=visibility)

```

## Visibility Statistics and Diagnostics

For operational monitoring, the server aggregates visibility statistics in [`src/mcp_openstack_ops/services/core.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/core.py) (lines 329-347). This diagnostic function counts images per visibility type, providing visibility into the distribution of public, community, shared, and private assets across the OpenStack deployment.

## Summary

- The MCP server filters OpenStack images by evaluating `visibility` and `owner` attributes in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) (lines 34-52).
- **Public** and **community** images are always visible to all projects.
- **Shared** images are included without additional membership validation.
- **Private** images are restricted to their owning project by comparing the `owner` field against `conn.current_project_id`.
- The `set_image_visibility` tool validates changes against allowed values (`public`, `private`, `shared`, `community`) and enforces read-only mode checks.
- Both `get_image_list()` and `get_image_detail_list()` apply identical filtering logic, ensuring consistent visibility enforcement across all MCP tools.

## Frequently Asked Questions

### How does the MCP server determine which images are visible to a user?

The server retrieves all images from OpenStack Glance using `conn.image.images()`, then applies the filtering logic in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) (lines 34-52). It inspects each image's `visibility` attribute and `owner` field, including public and community images for all users while restricting private images to the current project identified by `conn.current_project_id`.

### What is the difference between public and community visibility in the MCP OpenStack tools?

According to the source code in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py), public and community visibilities are treated identically during filtering. Both values cause `include_image` to be set to `True` regardless of the requesting project, making these images visible to all users across the OpenStack deployment.

### Can users see private images owned by other projects?

No. The filtering logic explicitly checks the `owner` attribute against `conn.current_project_id` when `visibility` is set to `private`. Only when these values match is the image included in the results. Private images owned by different projects are filtered out and never returned to the user.

### How does the set_image_visibility tool validate visibility changes?

The tool validates changes through a two-layer process. First, the tool wrapper in [`src/mcp_openstack_ops/tools/set_image_visibility.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/tools/set_image_visibility.py) checks if the server is in read-only mode using `_is_modify_operation_allowed()`. Then, the service function in [`src/mcp_openstack_ops/services/image.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/services/image.py) (lines 442-456) validates that the requested visibility is one of the allowed values: `public`, `private`, `shared`, or `community`. Only after both checks pass does the tool call `conn.image.update_image()` to apply the change.