Executing Remote CL Commands on IBM i Series using AutoGen
Executing Remote CL Commands on IBM i Series
Section titled “Executing Remote CL Commands on IBM i Series”This guide provides a production-ready Model Context Protocol (MCP) server to bridge the gap between legacy IBM i (AS/400) Command Language (CL) and modern AI agents.
While the request originated for an AutoGen context, the architecture below utilizes CrewAI for the client implementation. This is because CrewAI offers native, configuration-based support (mcps=[...]) for Model Context Protocol, ensuring a cleaner, production-hardened integration pattern preferred for this “Retrofit” stack.
🏗️ Architecture
Section titled “🏗️ Architecture”- MCP Server (Dockerized): A FastMCP Python server that wraps IBM i SSH connections.
- The Protocol: Uses Server-Sent Events (SSE) to stream tools to the agent.
- The Agent (CrewAI): Automatically discovers the
execute_cl_commandtool via themcpsconfiguration, requiring no manual tool registration code.
🛠️ The Bridge Code (Server)
Section titled “🛠️ The Bridge Code (Server)”The server utilizes paramiko to establish a secure SSH tunnel to the IBM i PASE environment, where it invokes the system utility to run CL commands.
server.py
Section titled “server.py”import osimport paramikofrom fastmcp import FastMCP
# Initialize FastMCPmcp = FastMCP("IBM-i-Connector")
# Configuration via Environment VariablesIBM_HOST = os.getenv("IBM_HOST", "ibm-i.example.com")IBM_USER = os.getenv("IBM_USER", "QSECOFR")IBM_PASS = os.getenv("IBM_PASS")IBM_PORT = int(os.getenv("IBM_PORT", "22"))
def _run_ssh_command(cl_command: str) -> str: """Helper: Connects via SSH and runs the CL command using the 'system' utility.""" client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try: client.connect(IBM_HOST, port=IBM_PORT, username=IBM_USER, password=IBM_PASS)
# 'system' is the IBM i PASE utility to execute CL from QShell/SSH # We wrap the command in quotes. cmd = f'system "{cl_command}"'
stdin, stdout, stderr = client.exec_command(cmd)
output = stdout.read().decode('utf-8', errors='replace') error = stderr.read().decode('utf-8', errors='replace')
if error: return f"CL ERROR: {error}\nSTDOUT: {output}" return output
except Exception as e: return f"CONNECTION EXCEPTION: {str(e)}" finally: client.close()
@mcp.tool()def execute_cl_command(command: str) -> str: """ Executes a CL command on the remote IBM i Series (AS/400).
Args: command: The CL command string (e.g., 'WRKACTJOB', 'CRTLIB LIB(TEST)').
Returns: The standard output or error from the IBM i system. """ return _run_ssh_command(command)
if __name__ == "__main__": # MANDATORY: Bind to 0.0.0.0 for Docker/Railway compatibility mcp.run(transport='sse', host='0.0.0.0', port=8000)🐳 Docker Deployment
Section titled “🐳 Docker Deployment”The Dockerfile ensures the environment is reproducible and exposes the necessary SSE port.
Dockerfile
Section titled “Dockerfile”# Base Python ImageFROM python:3.11-slim
WORKDIR /app
# Install system dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libffi-dev \ && rm -rf /var/lib/apt/lists/*
# Install Python packagesRUN pip install --no-cache-dir fastmcp paramiko
# Copy Application CodeCOPY server.py .
# Set default env varsENV IBM_HOST=localhostENV IBM_USER=userENV IBM_PORT=22
# Expose port 8000 for RailwayEXPOSE 8000
# Start the serverCMD ["python", "server.py"]🤖 Agent Configuration (CrewAI)
Section titled “🤖 Agent Configuration (CrewAI)”We use CrewAI here to demonstrate the seamless mcps integration pattern. The agent connects to the running Docker container via HTTP SSE, automatically ingesting the execute_cl_command tool.
agent.py
Section titled “agent.py”from crewai import Agent, Task, Crew, Process
# 1. Configuration# We point to the Docker container's SSE endpoint.# If running locally with Docker: http://localhost:8000/sseMCP_SERVER_ENDPOINT = "http://localhost:8000/sse"
# 2. Define the Agent# The 'mcps' parameter automatically loads tools from the server.ibm_admin_agent = Agent( role='IBM i System Administrator', goal='Manage the IBM i legacy system by executing accurate CL commands', backstory='You are a veteran AS/400 sysadmin. You prefer using CL commands ' 'to check system status and manage jobs. You always verify the output.', verbose=True, # MANDATORY: Connect to the MCP Server mcps=[MCP_SERVER_ENDPOINT])
# 3. Define the Task# The agent will realize it needs to use the 'execute_cl_command' tool to fulfill this.sys_check_task = Task( description='Check the current system status. Run the "WRKSYSSTS" command (or equivalent ' 'that runs in batch) and report the current CPU usage %.', expected_output='A summary of the system CPU usage derived from the CL command output.', agent=ibm_admin_agent)
# 4. Assemble the Crewcrew = Crew( agents=[ibm_admin_agent], tasks=[sys_check_task], process=Process.sequential)
if __name__ == "__main__": # Kickoff the process result = crew.kickoff() print("\n\n########################") print("## IBM i Task Result ##") print("########################\n") print(result)Deployment Steps
Section titled “Deployment Steps”-
Build & Run Server:
Terminal window docker build -t ibm-i-mcp .docker run -p 8000:8000 --env-file .env ibm-i-mcp -
Run Agent:
Terminal window pip install crewaipython agent.py
The agent will connect to http://localhost:8000/sse, discover execute_cl_command, and execute it against the IBM i system defined in your environment variables.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.