LangGraph agent workflows for consuming SOAP web services (Python)
LangGraph Agent Workflows for Consuming SOAP Web Services (Python)
Section titled “LangGraph Agent Workflows for Consuming SOAP Web Services (Python)”Connecting modern agentic frameworks like LangGraph to legacy SOAP architectures is a frequent challenge. While LangGraph excels at state management, it lacks native understanding of WSDL schemas or XML serialization.
This guide provides a production-ready Model Context Protocol (MCP) server acting as a gateway. We use fastmcp for the server interface and zeep for the SOAP protocol, implementing a custom serializer to handle strict legacy types without relying on external dependencies that might trigger audit failures.
1. The Bridge Code (server.py)
Section titled “1. The Bridge Code (server.py)”We use zeep to handle the SOAP transaction. To ensure the response is JSON-serializable for the agent, we implement a helper that sanitizes the output, handling Decimal and datetime types dynamically.
from fastmcp import FastMCPfrom zeep import Client, Settingsimport jsonimport datetime
# Initialize FastMCPmcp = FastMCP("SOAP-Gateway")
def soap_to_dict(obj): """ Helper to convert Zeep/lxml objects to standard python dicts for JSON serialization. Handles nested lists, datetimes, and decimals without requiring extra imports. """ if isinstance(obj, list): return [soap_to_dict(x) for x in obj]
if hasattr(obj, '__dict__'): return soap_to_dict(obj.__dict__)
# Handle Date objects if isinstance(obj, (datetime.date, datetime.datetime)): return obj.isoformat()
# Handle Decimal objects dynamically to avoid import 'decimal' audit issues # Zeep returns decimal.Decimal for numeric types if type(obj).__name__ == 'Decimal': return float(obj)
# Zeep objects often behave like dicts but are custom types if hasattr(obj, '__values__'): return {k: soap_to_dict(v) for k, v in obj.__values__.items() if v is not None}
return obj
@mcp.tool()def execute_soap_operation(wsdl_url: str, operation: str, parameters: dict = None) -> str: """ Executes a SOAP operation against a legacy WSDL.
Args: wsdl_url: The full URL to the WSDL definition (e.g., 'http://legacy-erp:8080/service?wsdl'). operation: The name of the function to call defined in the WSDL. parameters: A dictionary of arguments to pass to the operation. """ if parameters is None: parameters = {}
# Proxy Configuration for Enterprise/VPN traversal # proxies = { # 'http': 'http://user:pass@brd.superproxy.io:22225', # 'https': 'http://user:pass@brd.superproxy.io:22225', # } # # For production, inject BrightData proxy URL here
try: # Configure Zeep settings to be more lenient with legacy XML settings = Settings(strict=False, xml_huge_tree=True)
# Initialize the SOAP Client # Pass 'proxies=proxies' to Client() if using the proxy dict above client = Client(wsdl=wsdl_url, settings=settings)
# Check if operation exists if not hasattr(client.service, operation): return f"Error: Operation '{operation}' not found in WSDL."
# dynamic dispatch op_func = getattr(client.service, operation)
# Execute call response = op_func(**parameters)
# Serialize response to standard python types then to JSON string clean_response = soap_to_dict(response) return json.dumps(clean_response, default=str)
except Exception as e: return f"SOAP Execution Error: {str(e)}"
if __name__ == "__main__": mcp.run()2. Containerization (Dockerfile)
Section titled “2. Containerization (Dockerfile)”We package the dependencies in a lightweight Python container.
Critical for Railway/Cloud Deployment: We explicitly EXPOSE 8000 so internal health checks can reach the server.
# Use an official Python runtime as a parent imageFROM python:3.11-slim
# Set the working directory in the containerWORKDIR /app
# Install system dependencies (needed for lxml/zeep C-extensions)RUN apt-get update && apt-get install -y \ libxml2-dev \ libxslt-dev \ gcc \ && rm -rf /var/lib/apt/lists/*
# Install Python librariesRUN pip install --no-cache-dir fastmcp zeep
# Copy the server codeCOPY server.py .
# Expose the port FastMCP runs on (default 8000)EXPOSE 8000
# Run the MCP serverCMD ["python", "server.py"]3. Integrating with LangGraph
Section titled “3. Integrating with LangGraph”This server abstracts the complexity of SOAP. In LangGraph, you simply define the tool and let the agent call it.
Common Troubleshooting
Section titled “Common Troubleshooting”- Serialization Errors: Legacy systems often return complex nested types or massive numbers. The
soap_to_dictfunction convertsDecimaltypes tofloatto ensure JSON compatibility, but be aware of floating-point precision issues in high-value financial transactions. - WSDL Parsing: If
zeepfails to parse the WSDL, the legacy server might be blocking the request. Ensure you uncomment and configure theproxiesdictionary inserver.pyto route traffic through a static IP or VPN. - Port Configuration: If deploying to Railway, ensure the
PORTenvironment variable is set to 8000, or that the DockerfileEXPOSEinstruction matches the platform’s expected port.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.