Giving AI Agents Safe Access to Legacy Systems: Introducing legacy2mcp
legacy2mcp is a Python toolkit that generates secure Model Context Protocol servers from legacy SOAP services with input validation and audit logging.
The Problem: Agents Are Ready, Legacy Systems Aren't
AI agents are getting good at reasoning and tool use. The systems they need to reach, though, are often 10-20 years old: SOAP services, relational databases, message queues. These systems hold the claims, orders, accounts, and policies that businesses run on. Most enterprises can't rewrite them, and most can't safely expose them to an LLM either.
Model Context Protocol (MCP) gives agents a standard way to discover and call tools. But someone still has to write an MCP server for every legacy system by hand, and get the security right each time. Every new server means new code for validation, logging, and permissions. That repetition is where projects stall: the agent demo works in a week, and the security review takes months.
What legacy2mcp Does
legacy2mcp is an Apache 2.0 Python toolkit that auto-generates MCP servers from legacy systems. Instead of hand-writing tool definitions, you point the toolkit at the system's own description of itself and get a working, policy-enforced MCP server.
- Today: a WSDL/SOAP adapter. Point it at a WSDL, and it exposes the operations as MCP tools.
- Planned: database adapters (Postgres, SQL Server, Oracle) and queue adapters (Kafka, RabbitMQ, SQS).
- Extensible: a small adapter interface, so new legacy-system types can be added without touching the core.
Design Principles
Letting an LLM call into a system of record is a risk, so the defaults are conservative.
- Safe by default. No arbitrary SQL and no write operations unless you explicitly opt in. An agent can't do anything you didn't deliberately allow, and a misconfigured prompt can't turn a read-only tool into a destructive one.
- Validated inputs. Every tool's input is checked against a JSON Schema before it reaches the legacy system. Malformed or unexpected arguments are rejected early, which protects fragile older systems that were never designed to handle LLM-generated input.
- Audit logging. Every call is recorded: who, what, with which arguments. When someone asks what the agent did last Tuesday, you have an answer.
- Adapter interface. One contract for all backends, so safety behavior stays consistent whether the source is a SOAP service, a database, or a queue.
How It Works
WSDL / DB / Queue -> Adapter -> Tool definitions + JSON Schemas -> MCP server -> Agent
(safety policy + audit log applied here)
- The adapter introspects the source. For SOAP, that means reading the WSDL.
- It generates MCP tool definitions and JSON Schemas from the discovered operations and types, so the agent sees clear names, descriptions, and typed parameters.
- The generated server applies the safety policy and audit logging on every call. These aren't optional add-ons; they sit in the call path.
- Any MCP-compatible agent can discover and use the tools, with no custom client code.
Quick Start
# TODO: install command
pip install legacy2mcp
# TODO: generate a server from a WSDL
legacy2mcp generate --wsdl https://example.com/service?wsdl
(Replace with the actual CLI usage from the README.)
Example: An Agent Calling a SOAP Service
Picture a claims system that has exposed a SOAP operation for looking up claim status for a decade. An agent asked, "What's the status of claim 12345?" discovers the generated get_claim_status tool, sees from its schema that it needs a claim ID, and calls it. The server validates the input, forwards the request to the SOAP service, logs the call, and returns the result. Nobody wrote an MCP server by hand, and the agent can't reach any operation that wasn't exposed.
TODO: short transcript or screenshot of an agent discovering and calling a generated tool.
Why Not Just Write the MCP Server by Hand?
You can, and for one service it's fine. At ten services, you're copying the same validation, logging, and permission logic ten times, and each copy can drift. One team tightens its input checks, another forgets to log arguments, a third leaves a write operation exposed. Generating servers from the source definition keeps behavior uniform and makes safety a property of the toolkit rather than of each developer's diligence. It also means that when the legacy service changes, you regenerate instead of re-editing by hand.
Roadmap
- DB adapters (Postgres, SQL Server, Oracle), read-only by default
- Queue adapters (Kafka, RabbitMQ, SQS)
- More granular per-tool permission policies
- Community-contributed adapters
Get Involved
- Repo: https://github.com/bvenkata/legacy2mcp
- Star it, try it on a service you have, and open issues for the adapters you need most.
- Adapter contributions are welcome, especially for systems that are painful to integrate today.
Takeaway
Agents don't need legacy systems replaced. They need a safe, standard way in. legacy2mcp aims to make that a generated artifact, not a custom project.
Opinions expressed by DZone contributors are their own.
Comments