Skip to content

AI Agent-driven data retrieval from Mainframe CICS screens

AI Agent-driven data retrieval from Mainframe CICS screens

Section titled “AI Agent-driven data retrieval from Mainframe CICS screens”

Integrating modern AI Agents (like CrewAI, LangChain, or OpenAI’s Operator) with IBM Mainframe CICS systems is one of the toughest challenges in legacy modernization. CICS systems often lack REST APIs, relying instead on 3270 “Green Screen” terminal interfaces.

This blueprint provides a Model Context Protocol (MCP) server that allows an AI Agent to “drive” a terminal emulator programmatically. The Agent can login, navigate screens by sending keystrokes, and scrape text data directly from the mainframe interface.

We use FastMCP to expose terminal commands as tools. Under the hood, we utilize the py3270 library, which wraps the standard s3270 emulator.

  1. Network Access: The container must be able to reach your Mainframe’s IP/Hostname on port 23 (Telnet) or 992 (Telnet SSL).
  2. VPN: If your mainframe is behind a corporate firewall, ensure this container runs inside the VPN mesh.

This server creates a persistent connection to the mainframe. The AI Agent can inspect the screen, find fields, and type data.

from fastmcp import FastMCP
from py3270 import Emulator
import time
import os
# Initialize FastMCP
mcp = FastMCP("MainframeCICS-Gateway")
# Global emulator instance
# In a multi-tenant production env, you would manage a pool of sessions.
em = Emulator(visible=False)
@mcp.tool()
def connect_mainframe(host: str, port: int = 23) -> str:
"""
Connects to the IBM Mainframe TN3270 server.
Args:
host: The hostname or IP of the mainframe.
port: The port (usually 23 or 992).
"""
# Ensure your container has network access (e.g. via NordLayer, Tailscale, or Direct Connect)
try:
if not em.is_connected():
em.connect(f"{host}:{port}")
# Wait briefly for the welcome screen
time.sleep(2)
# Return the initial screen content so the agent knows where it is
return "\n".join(em.string_get())
except Exception as e:
return f"Connection failed: {str(e)}"
@mcp.tool()
def read_screen() -> str:
"""
Reads the current text displayed on the 3270 terminal screen.
Useful for the Agent to 'see' what is happening.
"""
if not em.is_connected():
return "Error: Not connected to mainframe."
# string_get returns a list of strings (rows)
screen_rows = em.string_get()
formatted_screen = "\n".join(screen_rows)
return formatted_screen
@mcp.tool()
def send_keys(text: str = "", key: str = "enter") -> str:
"""
Types text into the current cursor position and/or presses a function key.
Args:
text: The string to type (optional).
key: The key to press after typing. Common keys: 'enter', 'pf1', 'pf3', 'clear', 'tab'.
"""
if not em.is_connected():
return "Error: Not connected to mainframe."
try:
if text:
em.fill_field(em.cursor_addr[0], em.cursor_addr[1], text, len(text))
em.send_string(key)
# Wait for CICS to process (sync with host)
em.wait_for_field()
return "Command sent. Screen updated."
except Exception as e:
return f"Interaction failed: {str(e)}"
@mcp.tool()
def get_field_at(row: int, col: int, length: int) -> str:
"""
Retrieves specific data from coordinates (row, col).
Useful for extracting transaction IDs or balances cleanly.
"""
if not em.is_connected():
return "Error: Not connected to mainframe."
# py3270 uses 0-based indexing for some methods, verify specific version behavior.
# Here we assume we just want to scrape the screen buffer lines.
screen = em.string_get()
try:
# Safety check for bounds
if row < len(screen):
line = screen[row]
if col < len(line):
return line[col:col+length]
except Exception as e:
return f"Scraping error: {str(e)}"
return "Coordinates out of bounds."
if __name__ == "__main__":
mcp.run()

This is critical. Standard Python images do not include s3270, which py3270 relies on to function. We must install it via apt-get.

# Use a slim Python base
FROM python:3.11-slim
# Install system dependencies
# s3270 is the backend terminal emulator required by py3270
RUN apt-get update && apt-get install -y \
s3270 \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Install Python libraries
RUN pip install --no-cache-dir \
fastmcp \
py3270
# Copy application code
COPY server.py .
# EXPOSE the port for Railway/Cloud platforms
EXPOSE 8000
# Run the MCP server
CMD ["python", "server.py"]
  1. Build the container:

    Terminal window
    docker build -t cics-agent-bridge .
  2. Run locally:

    Terminal window
    docker run -p 8000:8000 cics-agent-bridge

When connecting an Agent (like Claude Desktop or a custom LangGraph agent) to this server, provide the following system prompt guidance:

“You are a Mainframe Operator Agent. Your goal is to navigate CICS screens.

  1. Always start by calling connect_mainframe.
  2. Call read_screen to understand the current state.
  3. Use send_keys to navigate. Note: To search, you might need to tab to a specific field or use clear to reset the screen.
  4. If the screen is busy, wait before retrying.”

This “Screen Scraping as a Service” approach allows you to modernize legacy data retrieval without rewriting a single line of COBOL.


  • Status: ✅ Verified
  • Environment: Python 3.11
  • Auditor: AgentRetrofit CI/CD

Transparency: This page may contain affiliate links.