Skip to content

Securing AI Agent access to legacy SOAP APIs (Python)

Securing AI Agent access to legacy SOAP APIs (Python)

Section titled “Securing AI Agent access to legacy SOAP APIs (Python)”

As organizations deploy autonomous AI agents into production, they often hit a “hard” security boundary: Legacy SOAP APIs. These interfaces, common in SAP, Oracle, and old banking systems, rely on strict XML schemas (WSDL) and outdated authentication protocols that modern LLMs struggle to navigate natively.

This guide demonstrates a Secure Gateway Pattern. We will build a lightweight Model Context Protocol (MCP) server using FastMCP. This server acts as a firewall and translator, holding the credentials and WSDL logic, while exposing a simple tool interface to your AI agents.

  • Python 3.10+
  • Docker Desktop
  • WSDL URL for your legacy service.

This server exposes a single tool invoke_soap_operation. It handles the proxies configuration to ensure traffic can traverse enterprise firewalls.

import os
import requests
from fastmcp import FastMCP
from zeep import Client, Settings
from zeep.transports import Transport
from zeep.helpers import serialize_object
# Initialize FastMCP
mcp = FastMCP("SecureSOAPGateway")
# Configuration
# Using a public SOAP service for demonstration
WSDL_URL = os.getenv("SOAP_WSDL_URL", "http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL")
SOAP_USER = os.getenv("SOAP_USER", "admin")
SOAP_PASS = os.getenv("SOAP_PASS", "secret")
@mcp.tool()
def invoke_soap_operation(operation_name: str, parameters: dict = {}) -> str:
"""
Securely invokes a legacy SOAP operation.
Args:
operation_name: The name of the SOAP method to call (e.g., 'FullCountryInfo').
parameters: A dictionary of arguments expected by the SOAP method.
"""
try:
# Security: Configure Transport with Proxies and Timeouts
session = requests.Session()
# PROXY CONFIGURATION
# proxies = {
# 'http': 'http://user:pass@proxy_host:port',
# 'https': 'http://user:pass@proxy_host:port',
# }
# # For production, inject BrightData proxy URL here
# session.proxies.update(proxies)
# Add Basic Auth if required
# session.auth = (SOAP_USER, SOAP_PASS)
transport = Transport(session=session, timeout=30)
# Strict Mode: strict=False allows for loose WSDL parsing which is helpful for old systems
settings = Settings(strict=False, xml_huge_tree=True)
client = Client(wsdl=WSDL_URL, transport=transport, settings=settings)
# Dynamically get the operation from the client service
service_method = getattr(client.service, operation_name, None)
if not service_method:
return f"Error: Operation '{operation_name}' not found in WSDL."
# Execute the call
# We unwrap **parameters to pass them as named arguments
result = service_method(**parameters)
# Serialize the Zeep object to a standard Python dict/list structure
clean_result = serialize_object(result)
return str(clean_result)
except Exception as e:
return f"SOAP Execution Error: {str(e)}"
if __name__ == "__main__":
# Binds to 0.0.0.0 to allow access from outside the container
mcp.run(transport='sse', host='0.0.0.0', port=8000)

We encapsulate dependencies in a container to ensure libxml and zeep versions are consistent.

# Use an official Python runtime as a parent image
FROM python:3.11-slim
# Set the working directory in the container
WORKDIR /app
# Install system dependencies for lxml (required by Zeep)
RUN apt-get update && apt-get install -y \
libxml2-dev \
libxslt-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Install Python libraries
RUN pip install --no-cache-dir fastmcp zeep requests
# Copy the current directory contents into the container at /app
COPY server.py .
# Make port 8000 available to the world outside this container
EXPOSE 8000
# Run server.py when the container launches
CMD ["python", "server.py"]

This is a complete, executable CrewAI implementation. The agent connects to the running Docker container via the SSE transport, queries the SOAP service for country information, and summarizes the result.

Note: Ensure your Docker container is running before executing this script.

from crewai import Agent, Task, Crew, Process
# 1. Define the Agent with MCP Connectivity
# The 'mcps' parameter connects the agent to our Dockerized SOAP Gateway
soap_agent = Agent(
role='Legacy Systems Integrator',
goal='Retrieve and interpret data from legacy SOAP web services',
backstory=(
"You are a specialist backend engineer. "
"Your job is to fetch technical data from old SOAP APIs "
"and translate it into clean, human-readable summaries."
),
# Connects to the server running on localhost:8000
mcps=["http://localhost:8000/sse"],
verbose=True,
allow_delegation=False
)
# 2. Define the Task
# We ask the agent to use the 'invoke_soap_operation' tool implicitly provided by the MCP server
fetch_country_task = Task(
description=(
"Call the 'invoke_soap_operation' tool. "
"The operation_name is 'FullCountryInfo'. "
"The parameters should be {'sCountryISOCode': 'US'}. "
"Get the details for the US and summarize the capital city and currency."
),
expected_output="A brief summary of the country's capital and currency code.",
agent=soap_agent
)
# 3. Create the Crew and Run
crew = Crew(
agents=[soap_agent],
tasks=[fetch_country_task],
process=Process.sequential
)
if __name__ == "__main__":
print("Starting SOAP Agent...")
result = crew.kickoff()
print("######################")
print("Agent Result:")
print(result)
  1. Build the Docker Image:

    Terminal window
    docker build -t soap-gateway .
  2. Run the Server:

    Terminal window
    docker run -p 8000:8000 soap-gateway
  3. Run the Agent:

    Terminal window
    # In a new terminal window
    pip install crewai
    python agent.py

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

Transparency: This page may contain affiliate links.