io.github.bvenkata/legacy2mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@io.github.bvenkata/legacy2mcpWhat operations does the demo calculator service expose?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
legacy2mcp introspects every operation in a WSDL, builds a real JSON Schema for each one from the WSDL's own XSD types, and exposes them as MCP tools — with every call schema-validated before it reaches your SOAP endpoint, write-like operations excluded by default, and every call audit-logged. No hand-written adapter code, no hand-maintained schemas.
Contents
Related MCP server: soap-api-gateway
Install
pip install legacy2mcp
# or: uv tool install legacy2mcp · pipx install legacy2mcpAlso published to the MCP Registry as io.github.bvenkata/legacy2mcp, so registry-aware MCP clients can discover it directly.
Quick start
Try it end-to-end against the bundled mock SOAP service — no external network, no real backend:
git clone https://github.com/bvenkata/legacy2mcp.git
cd legacy2mcp
pip install -e ".[dev]"
# 1. start the demo SOAP service (dneonline-style Calculator WSDL)
python examples/soap/run_mock_calculator.py &
# 2. see the MCP tools generated from its WSDL
legacy2mcp inspect --config examples/soap/config.calculator.yamldocker compose up demo-soap-service -d
docker compose run --rm legacy2mcp legacy2mcp inspect \
--config examples/soap/config.calculator.docker.yamlHow it works
flowchart LR
WSDL["WSDL / XSD"] --> GEN["legacy2mcp<br/>schema generation"]
GEN --> TOOLS["Typed MCP tools<br/>one per operation"]
AGENT["AI agent /<br/>MCP client"] -->|tool call| VAL{"schema<br/>validation"}
TOOLS -. defines .-> VAL
VAL -->|invalid args| REJ["rejected, never<br/>reaches SOAP"]
VAL -->|valid and allowed| SOAP["SOAP endpoint"]
SOAP --> RESP["plain JSON<br/>back to the agent"]
VAL --> LOG[("audit log")]Loads the WSDL with
zeep, a mature, widely-used Python SOAP client.For every operation on every port/binding, converts the XSD input type into a JSON Schema (
schema/xsd_to_jsonschema.py) — simple types, nested complex types, enums and arrays, recursively, depth-limited for pathological WSDLs.Registers one MCP tool per operation, named
<adapter_id>_<OperationName>.On a tool call: validates arguments with
jsonschema(schemas useadditionalProperties: false), calls the operation viazeep, serializes the response to plain JSON, and writes an audit entry.Operations whose names look like writes are excluded unless
allow_write_operations: true.
Point it at your own WSDL
# config.yaml
server:
name: my-legacy-mcp
adapters:
- id: legacy
type: soap
config:
wsdl_url: "https://service.example.com/LegacyService?wsdl"
auth:
type: basic
username: "svc-account"
password_env: "SERVICE_PASSWORD" # value read from the environment, never the file
allow_write_operations: false # Create*/Update*/Delete*/… stay hidden
include_operations: ["GetRecord", "GetRecordDetails", "SearchRecords"]
security:
audit:
enabled: true
path: "./legacy-mcp-audit.log"export SERVICE_PASSWORD=...
legacy2mcp inspect --config config.yaml # review the generated tools
legacy2mcp run --config config.yaml # start the MCP server (stdio)A production-shaped template with comments lives at examples/soap/config.template.yaml.
Use it from Claude Desktop (or any MCP client)
{
"mcpServers": {
"legacy": {
"command": "legacy2mcp",
"args": ["run", "--config", "/absolute/path/to/config.yaml"]
}
}
}What's handled
Area | Covered |
Type mapping |
|
Structure | nested complex types, repeated elements → arrays, |
Discovery | every service → port → binding → operation; duplicate tool names rejected at startup |
Invocation | argument validation, |
Errors | SOAP faults and transport errors caught and returned as clean messages — no stack traces to the caller |
Auth | HTTP basic (username + |
Transport |
|
See docs/security.md for the full, honest security model — what's covered today and what isn't yet.
Safety model
Layer | What it does |
Schema validation | No arguments reach the SOAP layer without passing |
Read-only by default | Operation names are matched against write-verb prefixes ( |
Explicit allow / deny |
|
Audit log | One JSON line per call — tool, arguments, timestamp, outcome, duration. |
Secret hygiene | Credentials come from named environment variables; the YAML stays safe to commit. |
The write-operation filter is aname heuristic, not semantic analysis — an operation called ProcessRecord that deletes data would not be caught. For any system where a wrong call has real consequences, set include_operations explicitly and don't rely on the heuristic. There is also no auth/authz on the MCP server itself yet — don't expose a v0.1 server to untrusted callers. Details in docs/security.md.
Use cases
Domain | Shape |
Systems of record | An agent reads status/detail records from a legacy back-office platform, read-only, every lookup logged. |
Financial services | Expose account and transaction reads without exposing transfers or adjustments. |
Supply chain / ERP | Surface order status, inventory, shipment tracking from an old SOAP middleware layer. |
Internal support tooling | A support copilot gets safe, typed access to the system of record instead of a scraped UI. |
Migration & modernization | Put an MCP layer in front of a legacy service now; swap the backend later without touching the agent. |
Real-world usage
In CI/CD — catch WSDL drift before it reaches production
legacy2mcp inspect loads the config, contacts the WSDL, builds every schema, and exits non-zero if anything fails:
- name: Check the WSDL still generates valid MCP tools
env:
SERVICE_PASSWORD: ${{ secrets.SERVICE_PASSWORD }}
run: |
pip install legacy2mcp
legacy2mcp inspect --config config/legacy.yaml > tools.json
git diff --exit-code --no-index tools/legacy.snapshot.json tools.json # optional: pin the contractAs a sidecar / long-running MCP server
legacy2mcp run speaks MCP over stdio. Package it with your config using the provided Dockerfile and let your MCP client launch it.
In a data pipeline
Call the same generated, validated tools from your own code via any MCP client library to pull records on a schedule — the audit log records exactly what was fetched.
Configuration reference
Key | Default | Meaning |
|
| MCP server name reported to clients |
|
| only |
| — | prefix for this adapter's tool names |
| — |
|
| — | WSDL location ( |
|
|
|
|
| expose write-like operations |
| all | allowlist of operation names |
|
| denylist of operation names |
|
| per-call SOAP timeout |
|
| write the audit log |
|
| audit log location |
Roadmap
Version | Scope | Status |
v0.1 | SOAP/WSDL adapter, schema generation, validation, read-only default, audit log, | ✅ shipped |
v0.2 | Database adapter (parameterized-query-only, table/operation allowlists), HTTP/SSE transport, role→tool authorization, OAuth2 for SOAP | planned |
v0.3+ | Queue adapter (Kafka/RabbitMQ/SQS), workflow composition with approval gates, OpenTelemetry export | ideas |
Full detail in docs/roadmap.md. The BaseAdapter interface (discover_tools() + invoke()) is the extension point — the server core handles validation, dispatch and audit for any adapter.
Development
pip install -e ".[dev]"
pytest tests/ -v # runs against an in-process mock SOAP service — no networkCI runs the suite on Python 3.10–3.12 (ci.yml). Releases to PyPI and the MCP Registry are tag-triggered — see docs/releasing.md. The demo GIF is regenerated with vhs demo/demo.tape (demo/).
Contributing
Adapters for new legacy systems are the highest-value contribution — implement BaseAdapter and the core handles the rest. Issues and PRs welcome.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Related MCP Servers
- AlicenseCqualityDmaintenanceExposes SOAP-based web services as MCP servers by parsing WSDL files. Enables AI assistants to interact with legacy SOAP/WS-\* web services through the Model Context Protocol.214MIT
- AlicenseNot gradedqualityDmaintenanceConverts SOAP WSDL services into a REST interface and provides MCP tools to describe, invoke, and manage SOAP operations with caching and WS-Security support.1Apache 2.0
- AlicenseNot gradedqualityBmaintenanceExposes SOAP web services as Model Context Protocol (MCP) servers, allowing AI models to interact with legacy SOAP services through automatic method discovery and type mapping.MIT
- FlicenseCqualityCmaintenanceWraps a legacy SOAP + stored-procedure backend with governed MCP tools, including a semantic data dictionary, compensation for transactionless writes, and load protection, enabling AI agents to safely operate on enterprise systems.10-