# How the MCP Server Manages Asynchronous Operations and Post-Action Feedback

> Discover how the MCP server manages asynchronous operations and provides instant post-action feedback. Learn about status messaging, verification commands, and client polling in this technical deep dive.

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

---

**The MCP server centralizes all OpenStack operation processing through the `handle_operation_result` function in [`src/mcp_openstack_ops/mcp_main.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/mcp_main.py), which automatically detects asynchronous actions via a static configuration map and enriches responses with human-readable status messages, verification commands, and boolean flags indicating whether client-side polling is required.**

The `call518/mcp-openstack-ops` repository implements a Model Context Protocol (MCP) server that standardizes how OpenStack operations are executed and reported back to clients. Understanding how this server handles asynchronous workflows—such as volume attachments or instance resizing—is critical for building reliable client integrations that can properly track operation completion.

## Centralized Async Handling in handle_operation_result

Every tool in the MCP server delegates its final response processing to `handle_operation_result`, defined in [`src/mcp_openstack_ops/mcp_main.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/mcp_main.py) (lines 94-119). This function serves as the single point of truth for determining whether an operation requires asynchronous monitoring and how to communicate that requirement to the client.

### The Async Operations Map

The server maintains a static dictionary called `async_operations` (lines 55-92) that categorizes which actions are asynchronous based on the operation domain. For example, under "Instance Management" or "Volume Management" keys, the map lists specific `async_actions` such as `attach`, `detach`, or `resize`.

```python

# src/mcp_openstack_ops/mcp_main.py (simplified excerpt)

async_operations = {
    "Instance Management": {
        "async_actions": ["resize", "reboot", "migrate"],
        "expected_time": "30-60 seconds"
    },
    "Volume Management": {
        "async_actions": ["attach", "detach"],
        "expected_time": "10-30 seconds"
    }
}

```

### Detecting Asynchronous Actions

When `handle_operation_result` receives a result dictionary from a tool, it inspects the `details['Action']` field and checks whether that action exists in the `async_operations` map for the given `operation_name`. If matched, the function triggers the asynchronous enrichment logic.

## Enriching Responses with Post-Action Feedback

The MCP server transforms raw OpenStack SDK responses into structured, actionable feedback that clients can consume programmatically or display to end users.

### Human-Readable Status Messages

For asynchronous operations, `handle_operation_result` appends a detailed note to `result['message']` (lines 100-107) that includes:

- A clear indication that the operation is asynchronous
- The expected completion time range (e.g., "10-30 seconds")
- A specific verification command the client can execute to check status

```python

# src/mcp_openstack_ops/mcp_main.py (lines 100-107)

if is_async:
    result['message'] += (
        f"\n\n📋 Note: This is an asynchronous operation. "
        f"The command has been initiated successfully "
        f"(expected completion: {expected_time}). "
        f"You can verify the status using '{verification_command}'."
    )

```

### Verification Flags and Operation Types

The function sets two critical metadata fields (lines 108-113) that enable automated client workflows:

- `result["operation_type"]`: Either `"asynchronous"` or `"synchronous"`
- `result["verification_needed"]`: Boolean `True` for async operations, `False` otherwise

These flags allow client applications to implement polling logic without parsing human-readable text.

## Implementation Example: Attaching a Volume

Tools in the MCP server remain agnostic about async handling by delegating to `handle_operation_result`. Consider the volume attachment tool in [`src/mcp_openstack_ops/tools/set_server_volume.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/tools/set_server_volume.py):

```python

# src/mcp_openstack_ops/tools/set_server_volume.py

@conditional_tool
@mcp.tool()
async def set_server_volume(
    instance_name: str,
    volume_name: str,
    action: str = "attach",
) -> str:
    # Execute OpenStack SDK call

    sdk_result = await attach_volume_to_server(instance_name, volume_name)
    
    # Prepare raw result

    result = {
        "success": True, 
        "message": f"Volume {volume_name} {action}ed"
    }
    
    # Delegate async handling to central processor

    return handle_operation_result(
        result,
        operation_name="Instance Management",
        details={
            "Action": action,
            "Instance": instance_name,
            "Volume": volume_name
        }
    )

```

The tool focuses purely on executing the OpenStack operation and constructing a basic result. The `handle_operation_result` function automatically detects that `"attach"` is an asynchronous action under `"Instance Management"` and enriches the response accordingly.

## Client-Side Integration

When the MCP server returns a response, clients receive a structured JSON payload that clearly indicates whether polling is required:

```json
{
  "success": true,
  "message": "✅ Volume data-disk attached\n\n📋 Note: This is an asynchronous operation. The attach command has been initiated successfully (expected completion: 10-30 seconds). You can verify the status using 'List all volumes'.",
  "operation_type": "asynchronous",
  "verification_needed": true
}

```

Client applications should implement logic that checks `verification_needed`. When `true`, the client can extract the verification command from the message or implement custom polling logic using the OpenStack SDK to monitor the resource status until the operation completes.

## Summary

- **Centralized Processing**: All OpenStack operations route through `handle_operation_result` in [`src/mcp_openstack_ops/mcp_main.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/mcp_main.py), ensuring consistent async detection and response formatting.

- **Static Configuration**: The `async_operations` map (lines 55-92) defines which actions are asynchronous per operation domain, enabling the server to detect async requirements without external API calls.

- **Rich Feedback**: Asynchronous operations receive enriched messages containing expected completion times and verification commands, plus machine-readable flags (`operation_type`, `verification_needed`) for automated client workflows.

- **Tool Agnostic Implementation**: Individual tools remain simple by delegating response processing to the central handler, allowing the async logic to be maintained in a single location.

## Frequently Asked Questions

### How does the MCP server determine if an operation is asynchronous?

The server consults a static dictionary called `async_operations` defined in [`src/mcp_openstack_ops/mcp_main.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/mcp_main.py) (lines 55-92). This map lists specific actions—such as `attach`, `detach`, or `resize`—under operation categories like "Instance Management" or "Volume Management". When `handle_operation_result` processes a response, it checks if the `details['Action']` value exists in the corresponding async list for that operation domain.

### What fields are added to the response for asynchronous operations?

For asynchronous operations, the server adds or modifies three key fields in the result dictionary: `operation_type` is set to `"asynchronous"`, `verification_needed` is set to `True`, and the `message` field is appended with a human-readable note containing the expected completion time and a recommended verification command. Synchronous operations receive `operation_type: "synchronous"` and `verification_needed: False`.

### Where is the async operation configuration defined?

The configuration mapping which actions are asynchronous is defined in [`src/mcp_openstack_ops/mcp_main.py`](https://github.com/call518/mcp-openstack-ops/blob/main/src/mcp_openstack_ops/mcp_main.py) between lines 55 and 92. This `async_operations` dictionary uses operation domains as keys (e.g., "Instance Management", "Volume Management") and contains nested dictionaries specifying `async_actions` (lists of action strings) and `expected_time` (human-readable duration strings).

### How should clients handle the verification_needed flag?

Clients should treat the `verification_needed` boolean as a signal to implement polling logic. When this flag is `True`, the client should parse the `message` field to extract the suggested verification command, or use the operation details to construct an appropriate status query using the OpenStack SDK. The client should then poll the resource status periodically until the operation completes or fails, rather than assuming immediate completion when `success` is `True`.