OpenAI Operator for automated Mainframe CICS interactions
OpenAI Operator for automated Mainframe CICS interactions
Section titled “OpenAI Operator for automated Mainframe CICS interactions”For decades, CICS (Customer Information Control System) has been the transaction engine of the world economy. It processes billions of transactions daily for banks, airlines, and insurance companies.
However, CICS was designed for green screens (3270 terminals), not AI agents.
This guide provides a “Retrofit” solution: an MCP Server that allows the OpenAI Operator to execute CICS transactions programmatically. We utilize the CICS Web Services (JSON/REST) interface, which is the standard, modern way to expose legacy COBOL programs to the outside world without fragile screen scraping.
The Architecture
Section titled “The Architecture”- OpenAI Operator: Acts as the intelligent decision-maker.
- MCP Server (FastMCP): Translates natural language intent (e.g., “Check balance for account 1234”) into structured CICS JSON payloads.
- CICS Transaction Gateway (or CICS TS): Receives the HTTP request and triggers the COBOL logic.
The Code (server.py)
Section titled “The Code (server.py)”This Python server uses fastmcp to create a lightweight bridge. It assumes your CICS region is configured to accept JSON payloads via HTTP (a standard feature in CICS TS 5.x and above).
import osimport jsonimport loggingfrom typing import Dict, Any, Optionalimport requestsfrom fastmcp import FastMCP
# Initialize the MCP Servermcp = FastMCP("CICS-Gateway")
# Configuration# ideally loaded from environment variables for securityCICS_BASE_URL = os.getenv("CICS_BASE_URL", "http://cics-region.internal:12345/cics/api")CICS_USER = os.getenv("CICS_USER", "USERID")CICS_PASSWORD = os.getenv("CICS_PASSWORD", "PASSWORD")
# Configure logginglogging.basicConfig(level=logging.INFO)logger = logging.getLogger(__name__)
@mcp.tool()def execute_cics_program(program_name: str, payload: Dict[str, Any]) -> str: """ Executes a specific CICS program via the CICS Web Services JSON interface.
Use this to trigger transaction logic (e.g., balance check, order update) that resides on the Mainframe.
Args: program_name: The 8-character CICS program name (e.g., 'GETBAL01'). payload: The business data required by the program as a dictionary.
Returns: A JSON string containing the response from the mainframe or error details. """ url = f"{CICS_BASE_URL}/{program_name.lower()}"
logger.info(f"Executing CICS Program: {program_name} at {url}")
try: # Standard Basic Auth is common for CICS Web Services response = requests.post( url, json=payload, auth=(CICS_USER, CICS_PASSWORD), timeout=10, # CICS transactions should be fast headers={"Content-Type": "application/json"} )
response.raise_for_status()
return json.dumps({ "status": "success", "cics_return_code": response.status_code, "data": response.json() })
except requests.exceptions.HTTPError as e: # Handle specific Mainframe HTTP return codes error_msg = f"CICS HTTP Error: {e.response.status_code} - {e.response.text}" logger.error(error_msg) return json.dumps({"status": "error", "message": error_msg})
except requests.exceptions.ConnectionError: error_msg = "Failed to connect to CICS region. Check network/VPN." logger.error(error_msg) return json.dumps({"status": "error", "message": error_msg})
except Exception as e: logger.error(f"Unexpected error: {str(e)}") return json.dumps({"status": "error", "message": str(e)})
@mcp.tool()def check_cics_region_health() -> str: """ Pings the CICS region to ensure the Web Services interface is active. """ url = f"{CICS_BASE_URL}/health" # Assumes a standard health endpoint or root check try: response = requests.get( url, auth=(CICS_USER, CICS_PASSWORD), timeout=5 ) if response.status_code == 200: return "CICS Region is ACTIVE and accepting requests." else: return f"CICS Region responded with status: {response.status_code}" except Exception as e: return f"CICS Region unreachable: {str(e)}"
if __name__ == "__main__": mcp.run()The Container (Dockerfile)
Section titled “The Container (Dockerfile)”This Dockerfile packages the MCP server. It is critical to ensure the container has access to the private network where the Mainframe resides, often requiring a VPN tunnel (like NordLayer, Tailscale, or a direct Railway private network connection).
# Use an official Python runtime as a parent imageFROM python:3.11-slim
# Set the working directory in the containerWORKDIR /app
# Install system dependencies if needed (usually minimal for this setup)RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ && rm -rf /var/lib/apt/lists/*
# Copy the requirements (embedded here for simplicity)# In production, use a requirements.txtRUN pip install --no-cache-dir \ fastmcp \ requests
# Copy the current directory contents into the container at /appCOPY server.py .
# Ensure your container has network access (e.g. via NordLayer)# This is critical for reaching legacy CICS IPs.
# Make port 8000 available to the world outside this containerEXPOSE 8000
# Run server.py when the container launchesCMD ["python", "server.py"]Deployment Instructions
Section titled “Deployment Instructions”- Network Access: The most common failure point is the container checking the public internet for the Mainframe IP (
10.x.x.x). Ensure your Docker runtime (Railway, AWS ECS) is peered with the VPC containing the Mainframe, or use a sidecar VPN. - Authentication: CICS Web Services often use Basic Auth (RACF ID/Password) or Client Certificates (mTLS). Modify the
requests.postcall inserver.pyto usecert=('client.pem', 'key.pem')if mTLS is required. - JSON Mapping: CICS normally expects specific JSON schemas that map to the COBOL COPYBOOKs. Ensure your
payloadin the OpenAI prompt matches the expected structure.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.