Skip to content

Architecture

Component overview

The library is organized around four core components:

Session
The main entry point. Owns authentication, base URL construction, request/response handling, and diagnostic state. Provides generated command methods for all MQSC commands. A single session represents a connection to one queue manager's REST API.
Command methods
~144 generated MQSC command methods. Each method is a thin wrapper that calls the internal command dispatcher with the correct command verb and qualifier. Method names follow the pattern verb_qualifier (or verbQualifier in camelCase languages), mapping directly to MQSC commands. For example, DISPLAY QUEUE becomes display_queue / displayQueue, and DEFINE QLOCAL becomes define_qlocal / defineQlocal.
Ensure methods
16 idempotent ensure methods for declarative object management. Each method checks current state with DISPLAY, then DEFINE, ALTER, or no-ops as needed. Returns an ensure result indicating what action was taken. The queue manager variant is a special singleton (no name, no DEFINE). Only changed attributes are sent in ALTER commands, preserving ALTDATE/ALTTIME audit timestamps.
Mapping pipeline
Bidirectional attribute translation between developer-friendly names and native MQSC parameter names. Includes key mapping (attribute names), value mapping (enumerated values), and key-value mapping (combined name+value translations). The mapping tables were bootstrapped from IBM MQ 9.4 documentation and cover all standard MQSC attributes.
Exception hierarchy
Structured error types for transport failures, malformed responses, authentication errors, MQSC command errors, and polling timeouts. All exceptions carry diagnostic context including the full MQ response payload when available.

In the Python implementation, the core components map to these modules:

  • MQRESTSession (session.py): The main entry point. Owns authentication, base URL construction, request/response handling, and diagnostic state. Inherits generated command methods from MQRESTCommandMixin.
  • MQRESTCommandMixin (commands.py): Provides ~144 generated MQSC command methods. Each method is a thin wrapper that calls _mqsc_command with the correct command verb and qualifier.
  • MQRESTEnsureMixin (ensure.py): Provides 16 idempotent ensure_* methods for declarative object management. ensure_qmgr() is a special singleton variant (no name, no DEFINE).
  • Mapping pipeline (mapping.py, mapping_data.py): Bidirectional attribute translation between Python snake_case names and native MQSC parameter names. See the mapping pipeline for details.
  • Exception hierarchy (exceptions.py): Structured error types rooted at MQRESTError. All exceptions carry diagnostic context.

Request lifecycle

Every MQSC command follows the same path through the system:

Method call (e.g. displayQueue / display_queue)
  → command dispatcher
    → Map request attributes (friendly names → MQSC)
    → Map response parameter names
    → Map WHERE keyword
    → Build runCommandJSON payload
    → Transport POST
    → Parse JSON response
    → Extract commandResponse items
    → Flatten nested objects
    → Map response attributes (MQSC → friendly names)
  → Return result

Build phase

  1. The command method calls the internal dispatcher with the MQSC verb (e.g. DISPLAY), qualifier (e.g. QUEUE), and user-supplied parameters.
  2. If mapping is enabled, request attributes are translated from friendly names to MQSC parameter names via the qualifier's request key map and request value map.
  3. Response parameter names are mapped similarly.
  4. A WHERE clause keyword, if provided, is mapped through the same qualifier key maps.
  5. The runCommandJSON payload is assembled and sent via the transport.

Parse phase

  1. The JSON response is parsed and validated.
  2. Error codes (overallCompletionCode, overallReasonCode, per-item completionCode/reasonCode) are checked. Errors raise a command exception.
  3. The parameters dict is extracted from each commandResponse item.
  4. Nested objects lists (e.g. from DISPLAY CONN TYPE(HANDLE)) are flattened into the parent parameter set.
  5. If mapping is enabled, response attributes are translated from MQSC to friendly names.

In Python, the command dispatcher is the internal _mqsc_command() method on MQRESTSession. Every public command method (e.g. display_queue(), define_qlocal()) delegates to it with the appropriate verb and qualifier.

The session retains diagnostic state from the most recent command for inspection:

session.display_queue("MY.QUEUE")

session.last_command_payload    # the JSON sent to MQ
session.last_response_payload   # the parsed JSON response
session.last_http_status        # HTTP status code
session.last_response_text      # raw response body

Transport abstraction

The session object does not make HTTP calls directly. Instead, it delegates to a transport interface that defines a single method for posting JSON payloads:

  • URL: The fully-qualified endpoint URL.
  • Payload: The runCommandJSON request body.
  • Headers: Authentication, CSRF token, and optional gateway headers.
  • Timeout: Per-request timeout duration.
  • TLS verification: Whether to verify server certificates.

The transport returns a response object containing the HTTP status code, response body, and response headers.

The default implementation wraps the language's standard HTTP client. Tests inject a mock transport to avoid network calls, making the entire command pipeline testable without an MQ server.

In Python, the transport is defined by the MQRESTTransport protocol:

class MQRESTTransport(Protocol):
    def post_json(
        self,
        url: str,
        payload: Mapping[str, object],
        *,
        headers: Mapping[str, str],
        timeout_seconds: float | None,
        verify_tls: bool,
    ) -> TransportResponse: ...

The default implementation, RequestsTransport, wraps the requests library.

For testing, inject a mock transport:

from unittest.mock import MagicMock

mock_transport = MagicMock(spec=MQRESTTransport)
mock_transport.post_json.return_value = TransportResponse(
    status_code=200,
    text='{"commandResponse": []}',
    headers={},
)

session = MQRESTSession(
    rest_base_url="https://localhost:9443/ibmmq/rest/v2",
    qmgr_name="QM1",
    credentials=LTPAAuth("admin", "passw0rd"),
    transport=mock_transport,
)

This makes the entire command pipeline testable without an MQ server.

Single-endpoint design

All MQSC operations go through a single REST endpoint:

POST /ibmmq/rest/v2/admin/action/qmgr/{qmgr}/mqsc

The runCommandJSON payload specifies the MQSC verb, qualifier, object name, parameters, and response parameters. This design means the library needs exactly one HTTP method and one URL pattern to cover all MQSC commands.

In Python, this means every command method on MQRESTSession ultimately calls the same post_json() method on the transport with the same URL pattern. The only variation is the JSON payload content.

Gateway routing

The MQ REST API is available on all supported IBM MQ platforms (Linux, AIX, Windows, z/OS, and IBM i). The library is developed and tested against the Linux implementation.

In enterprise environments, a gateway queue manager can route MQSC commands to remote queue managers via MQ channels — the same mechanism used by runmqsc -w and the MQ Console.

When a gateway queue manager is configured on the session:

  • The URL path targets the remote queue manager: POST /admin/action/qmgr/{TARGET_QM}/mqsc
  • The ibm-mq-rest-gateway-qmgr HTTP header names the local queue manager that routes the command.

When no gateway is configured (the default), no gateway header is sent and the REST API talks directly to the queue manager in the URL. This makes the feature purely additive — existing sessions are unaffected.

Client                     Gateway QM (QM1)              Target QM (QM2)
  │                              │                              │
  │  POST /qmgr/QM2/mqsc        │                              │
  │  Header: gateway-qmgr=QM1   │                              │
  │─────────────────────────────>│   MQSC via MQ channel        │
  │                              │─────────────────────────────>│
  │                              │<─────────────────────────────│
  │<─────────────────────────────│                              │

Prerequisites

  • The gateway queue manager must have a running REST API.
  • MQ channels must be configured between the gateway and target queue managers.
  • A QM alias (QREMOTE with empty RNAME) must map the target QM name to the correct transmission queue on the gateway.

In Python, configure gateway routing via the gateway_qmgr parameter:

session = MQRESTSession(
    rest_base_url="https://qm1-host:9443/ibmmq/rest/v2",
    qmgr_name="QM2",           # target (remote) queue manager
    credentials=LTPAAuth("mqadmin", "mqadmin"),
    gateway_qmgr="QM1",        # local gateway queue manager
)

Zero runtime dependencies

The library uses only the Python standard library plus requests for HTTP. No other runtime dependencies are required.

Generated command methods

The command methods in MQRESTCommandMixin are generated from mapping-data.json by st-generate-commands (from standard-tooling). Each method:

  • Accepts name, request_parameters, response_parameters, and where (for DISPLAY commands).
  • Calls self._mqsc_command() with the correct verb and qualifier.
  • Returns list[dict[str, object]] for DISPLAY commands, None for others.

Queue manager commands (DISPLAY QMGR, DISPLAY QMSTATUS, etc.) have singleton helpers that return dict | None instead of a list.

Ensure pipeline

See ensure for details on the idempotent create-or-update pipeline.

Sync pipeline

See sync for details on the synchronous polling pipeline.