mcpField
L
legacy2mcp

legacy2mcp

本地服务
github.com/bvenkata开发工具65 天前更新

关于 legacy2mcp

legacy2mcp 可根据 SOAP/WSDL、数据库结构及 REST API 描述或发现结果生成带类型的 MCP 服务。它按生成的 JSON Schema 校验工具参数,默认隐藏写操作,并记录每次调用以供审计。

主要功能

  1. 01从旧系统接口生成带类型的工具
  2. 02检查 WSDL、数据库和 REST 定义
  3. 03依据 JSON Schema 校验参数
  4. 04默认隐藏写操作
  5. 05记录每次工具调用
  6. 06通过 init 生成起始配置

适用场景

  1. 01向 MCP 客户端开放 SOAP 服务
  2. 02向 Agent 提供允许列表中的数据库操作
  3. 03让 MCP 客户端连接 REST API
  4. 04启动服务前检查发现的工具

MCP 相关

可从 SOAP 操作、允许列表中的数据库表和查询,或已配置的 REST 端点生成 MCP 工具。服务通过 stdio 运行,并在请求到达后端前校验调用。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"bvenkata-legacy2mcp": {
"command": "uvx",
"args": [
"legacy2mcp"
]
}
}
}
启动命令uvx legacy2mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypilegacy2mcp0.5.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

legacy2mcp

legacy2mcp — 将旧版 SOAP/WSDL、数据库、REST API 或网站转化为安全、类型化的 MCP 工具

CI PyPI Python 版本 MCP 注册表 Glama 评分 许可证

星标数 复刻数 贡献者 最近提交 PyPI 下载量

已验证:Claude Desktop 已验证:Cursor 已验证:VS Code Claude Code 已通过 MCP Inspector 测试

60 秒内将任何内容转换为 MCP。默认只读,并记录每次调用以供审计。


快速开始

无需 API 密钥,也无需克隆仓库——选择适合你现有环境的方式, 连接到实时公开演示目标:

pip install legacy2mcp

# REST API -- tries OpenAPI/Swagger discovery
legacy2mcp init --rest-url "https://petstore3.swagger.io/api/v3"

# WSDL / SOAP service -- zeep introspects it live, no scan needed
legacy2mcp init --wsdl-url "http://www.dneonline.com/calculator.asmx?WSDL"

# A website with no API docs at all -- crawls it for forms/content
legacy2mcp init --webpage-url "https://legacy2mcp.com/"

在真实终端中运行其中任意一条命令,整个流程就完成了:它会写入 config.yaml,打开本地测试聊天页面,并在每个发现的工具下方显示一个可点击的示例问题——点击后即可看到实时数据源返回的真实响应,无需 AI 密钥,只通过本地关键词匹配来检查服务是否正常工作——同时还会输出一段可直接粘贴到 Claude Desktop、Cursor、VS Code 和 Claude Code 中的连接配置。将它接入真实 AI 客户端只需复制粘贴,无需单独执行其他步骤。 (更喜欢原始工具列表?运行 legacy2mcp inspect --config config.yaml。)

legacy2mcp discover 适用于需要先经过审核的来源(Postman 集合、HAR 捕获文件等),执行相同的流程:编写契约、打开同一个测试聊天页面、输出同一段连接配置——两种方式都只需一条命令。

你有自己的 WSDL、REST API、网站或代码库吗?legacy2mcp init(不带标志)会引导你完成配置——请参阅 自动生成配置。更多演示(本地 SOAP 服务、Docker、通过原始 URL 提供的 WSDL)列在 examples/ 中。

说明

legacy2mcp 会实时检查你的旧系统——所有 WSDL 操作、所有数据库表,以及它能找到的所有 REST 规范——并据此为每个工具构建真实的 JSON Schema。每次 MCP 工具调用在到达后端前都会经过架构验证,默认排除写入操作,并且每次调用都会记录审计日志。无需手写适配器代码,无需手动维护架构,也不会让大模型执行任意 SQL。

目录

安装

# Full install (recommended)
pip install "legacy2mcp[ai]"

# Or the identical, scan-only-ready core -- AI-assisted `legacy2mcp init`
# needs no extra package either way, just an API key at runtime; `[ai]`
# above installs nothing extra today, it's just a stable, familiar name
pip install legacy2mcp
# or:  uv tool install legacy2mcp   ·   pipx install legacy2mcp

该项目也已发布到 MCP Registry,名称为 io.github.bvenkata/legacy2mcp,因此支持注册表的 MCP 客户端可以直接发现它。

工作原理

flowchart LR
  WSDL["WSDL / XSD"] --> GEN["legacy2mcp<br/>schema generation"]
  DB["DB schema<br/>(allowlisted tables)"] --> GEN
  GEN --> TOOLS["Typed MCP tools<br/>one per operation / table / query"]
  AGENT["AI agent /<br/>MCP client"] -->|tool call| VAL{"schema<br/>validation"}
  TOOLS -. defines .-> VAL
  VAL -->|invalid args| REJ["rejected, never<br/>reaches SOAP/DB"]
  VAL -->|valid and allowed| BACKEND["SOAP endpoint<br/>or database"]
  BACKEND --> RESP["plain JSON<br/>back to the agent"]
  VAL --> LOG[("audit log")]

SOAP:

  1. 使用成熟且广泛采用的 Python SOAP 客户端 zeep 加载 WSDL。
  2. 针对每个端口/绑定上的每个操作,将 XSD 输入类型转换为 JSON Schema(schema/xsd_to_jsonschema.py)——递归处理简单类型、嵌套复杂类型、枚举和数组,并限制深度以应对异常复杂的 WSDL。
  3. 为每个操作注册一个 MCP 工具,命名为 <adapter_id>_<OperationName>。
  4. 调用工具时:使用 jsonschema 验证参数(架构使用 additionalProperties: false),通过 zeep 调用操作,将响应序列化为纯 JSON,并写入一条审计记录。

DB:

  1. 使用对应方言的驱动连接(psycopg/pyodbc/oracledb,按需导入),并内省每个允许列表中表的实时列类型(adapters/db_dialects.py),将其转换为 JSON Schema(schema/sql_to_jsonschema.py)。
  2. 为每个允许列表中的表和操作注册 select_<table>/insert_<table>,并为配置中的每个命名查询注册 query_<name>。
  3. 调用工具时:验证参数,根据允许列表中的表/列构建 SQL(或运行配置提供的命名查询),使用统一且不依赖方言的 :param 占位符约定,执行查询,并写入一条审计记录。大模型看不到也不会编写 SQL 文本。
  4. 除非设置 allow_write_operations: true,否则会排除名称看起来像写入操作的操作。

REST:

  1. 普通 REST API 没有可供内省的实时架构,不像 WSDL 或 DB 目录那样;因此,端点列表(方法、路径、类型化参数)来自配置,可以手动编写,也可以由 legacy2mcp init 的 OpenAPI/Swagger 发现功能或源代码扫描生成。
  2. 为每个允许列表中的端点注册一个 MCP 工具,命名为 <adapter_id>_<name>。
  3. 调用工具时:验证参数,根据每个参数声明的 location 将其拆分为路径/查询/正文参数,将 {param} 占位符替换到 URL 中,并使用 requests 发起调用——身份验证根据适配器的 auth 配置应用(basic/bearer/none)。
  4. 除非设置 allow_write_operations: true,否则会排除标记为 write: true 的端点(默认是非 GET 端点)。

为什么不手动编写适配器?

因为手动编写的适配器会成为系统架构的第二份副本,而没人会记得更新它。WSDL 操作签名或列第一次发生变化时,工具的 JSON Schema 就会悄然偏离实际情况——而调用它的大模型只能通过传入错误参数才会发现问题,但这种错误可能无法被捕获,也可能导致 SOAP/DB 客户端深处抛出令人困惑的运行时错误。legacy2mcp 每次启动时都会根据实时系统构建架构,因此,架构偏离后,调用会在验证阶段失败,不会等到请求抵达后端才失败。

手动编写的适配器(FastMCP/原始 SDK)通用 OpenAPI-to-MCP 代理legacy2mcp
架构来源手动为每个工具编写OpenAPI 规范(如果存在)实时 WSDL/DB 架构,或发现的 OpenAPI 规范
是否可能偏离实际系统是——没有任何机制重新检查仅当规范本身过时时否——启动时会根据实时来源重新构建
是否支持 SOAP/数据库需要自行编写客户端代码否——仅支持 REST/OpenAPI是,还支持 REST 和普通网站
默认隐藏写入操作否——需要记得逐个设置门控否——通常会公开规范定义的所有内容是——需显式启用 allow_write_operations
记录每次调用的审计日志需要自行实现通常没有内置
搭建可用服务所需时间每个系统需数小时到数天对于带规范的 REST API,只需几分钟几分钟——legacy2mcp init

将其指向你自己的 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)

包含注释的生产级模板位于 examples/soap/config.template.yaml。

连接到你自己的数据库

pip install "legacy2mcp[db-postgres]"   # or db-mssql / db-oracle
# config.yaml
adapters:
  - id: orders
    type: db
    config:
      dialect: postgres             # postgres | mssql | oracle
      dsn_env: "ORDERS_DB_DSN"      # connection string, read from the environment
      allow_write_operations: false # insert_<table> / write: true queries stay hidden
      tables:
        - name: orders
          operations: [select]
          columns: [id, status, total, created_at]   # column allowlist
          filterable_columns: [status]                # equality filters on select_orders
          max_rows: 200
      queries:
        - name: orders_by_status_since
          sql: "SELECT id, status, total FROM orders WHERE status = :status AND created_at >= :since"
          params:
            - { name: status, type: string, required: true }
            - { name: since, type: string, required: true }
export ORDERS_DB_DSN=...
legacy2mcp inspect --config config.yaml   # review the generated tools

启动时会从实时架构中内省列,方式与从 WSDL 中获取 SOAP 操作架构相同——无需手动维护。LLM 绝无途径执行任意 SQL:它只能调用 tables: 下列出的表对应的 select_<table> / insert_<table>,或调用 queries: 下由你编写 SQL 的 query_<name> 工具——LLM 只能提供查询的 params 声明的占位符值,不能提供 SQL 文本。生产环境风格的模板位于 examples/db/config.template.yaml。

连接到你自己的 REST API

普通的 REST/JSON API 没有 WSDL 或实时数据库架构可供内省,因此 rest 适配器的端点列表需要在配置中显式指定——手动编写,或使用 legacy2mcp init 生成初始配置(见下一节)。

# config.yaml
adapters:
  - id: orders
    type: rest
    config:
      base_url: "https://api.example.com"
      auth:
        type: bearer
        token_env: "ORDERS_API_TOKEN"
      allow_write_operations: false
      endpoints:
        - name: get_order
          method: GET
          path: "/orders/{order_id}"
          params:
            - { name: order_id, location: path, type: integer, required: true }
        - name: create_order
          method: POST
          path: "/orders"
          write: true   # stays hidden unless allow_write_operations: true
          params:
            - { name: total, location: body, type: number, required: true }

生产环境风格的模板位于 examples/rest/config.template.yaml。

说明

非 GET 方法和 LLM 辅助分类都只是启发式判断,不能保证端点在无人监督的情况下调用是安全的——在连接真实后端运行之前,请检查 write: 标志和 allow_write_operations。SOAP 适配器下文所述的写入动词启发式判断也有同样的注意事项。

自动生成配置

legacy2mcp init 会询问你要将它指向哪里,然后为你编写一份起始 config.yaml:

legacy2mcp init
What do you want to point legacy2mcp at?
  1) WSDL URL (SOAP service)
  2) REST API URL (tries OpenAPI/Swagger discovery)
  3) A website with no API docs at all (crawls it for forms/content)
  4) GitHub repo URL or a local path to its source code
Choice [1-4]:
选项执行内容需要 LLM 密钥吗?
WSDL URL直接将 soap 适配器指向该 URL——zeep 无论如何都会在 inspect/run 时检查实时 WSDL,因此无需预先扫描。否
REST API URL尝试该 URL 下常见的 OpenAPI/Swagger 规范位置(/openapi.json、/swagger.json 等),如果找到规范,就根据真实规范构建 rest 适配器的端点列表;否则生成一个空框架。否
网站从该网站开始抓取同站页面(由 --max-pages/--max-depth 限制,默认值为 25/2),方式与 legacy2mcp discover --webpage-url 相同,然后直接生成配置,而不是停在 contract.yaml;生成的 TODO 中,每项操作仍会标记为 confidence: low / needs_review: true。使用 init 只是跳过一个文件,并不代表跳过审查。否
GitHub 仓库 / 本地路径克隆(或读取)仓库,并对其 Python 源代码进行静态扫描(仅分析 AST,从不执行代码),查找 zeep.Client(...) 调用、SQLAlchemy/Flask-SQLAlchemy 模型或 Flask/FastAPI 路由,并据此选择 soap/db/rest。可选

每种方式也都可以通过标志以非交互方式使用——--wsdl-url、--rest-url、 --webpage-url、--github-url 或 --local-path——适用于脚本或 CI。 只有 GitHub/源代码路径可以使用 LLM,而且仅用于完善静态分析已发现的内容(例如含糊不清的参数类型、读写分类)——绝不会转储你的仓库。它无需额外依赖,只需通过 --llm-api-key-env 提供一个兼容 OpenAI 的 API 密钥;如果省略该参数,则会以交互方式提示输入(不会写入磁盘)。传入 --scan-only 可直接跳过这一步,仅运行静态分析,效果与不输入密钥相同。

legacy2mcp init --github-url https://github.com/you/your-api --scan-only --out config.yaml

无论选择哪种方式,运行前都要检查生成的文件——无法有把握地推断的内容会用 # TODO 注释标出(例如未解析的 base_url、未经验证的参数类型、哪些端点被分类为 write: true);在你进行验证前,其中的任何内容都尚未根据真实后端验证:

legacy2mcp inspect --config config.yaml   # review the generated tools
legacy2mcp run     --config config.yaml   # start the MCP server

legacy2mcp init 还会在配置文件旁生成一份通俗易懂的 HTML 报告(例如,config.yaml -> config.html)。在浏览器中打开它,即可用文字而非 YAML 查看服务将公开哪些工具(发现的每个 REST 端点 / DB 表 / SOAP 目标、哪些工具可以更改数据并受 allow_write_operations 限制,以及上述审查事项)。传入 --html-out 可更改报告保存位置,传入 --no-html-report 可跳过生成。

在真实终端中,针对已经可用的配置运行 init (实时 --wsdl-url/--rest-url,或扫描发现了具体内容), 它还会在浏览器中打开一个本地测试聊天页面,每个发现的工具下方都有一个可点击的示例问题(根据该工具自身的名称和架构生成,例如 getPetById -> “按 ID 获取宠物 4”),这样你就不必猜该输入什么。点击示例,或输入自己的问题,页面会将其匹配到已发现的工具,调用真实适配器,并显示真实响应。此功能无需 AI/API 密钥——它通过工具名称/描述进行本地关键词匹配,不使用 LLM,只是足以在接入真正的 MCP 客户端前检查服务是否确实可用。当配置中仍有待填写的 TODO(尚无可连接的内容)时,会自动跳过;在非交互式/脚本运行中则完全不会打开。传入 --no-chat 可选择退出此功能。

在将其指向任何真实目标之前,请参阅 docs/security.md,了解这种启发式方法具体能保证什么、不能保证什么。

生成服务前先发现旧版接口

init 支持在线 WSDL、在线 REST URL、网站(--webpage-url)以及可供扫描的代码仓库——这些来源都会直接生成配置,无需单独步骤。其他来源则需要先执行明确的步骤,例如已有的 Postman 集合、代码仓库中尚未启动服务器的 OpenAPI 规范文件、数据库的存储过程目录、真实流量的 HAR 捕获文件,或你已知的队列:

legacy2mcp discover --postman-file my-collection.json --out contract.yaml
legacy2mcp discover --openapi-file spec.yaml --out contract.yaml
legacy2mcp discover --har-file traffic.har --out contract.yaml
legacy2mcp discover --stored-procs --db-dialect postgres --db-dsn-env LEGACY_DB_DSN --out contract.yaml
legacy2mcp discover --queue-config queues.yaml --out contract.yaml

如果想在生成任何内容之前先检查契约,网站也可以通过 discover --webpage-url 处理(见下文);init --webpage-url 会执行相同的爬取,只是不会在此处暂停。

每个命令都会生成一份 Legacy Interface Contract(contract.yaml):其中包含每个操作的输入、输出、枚举、错误代码、读写属性,以及置信度——在线架构或目录为 high,Postman 集合等经过整理的工件为 medium,根据采样流量推断的内容为 low——还会标注 needs_review 标记,并对不确定的内容附上说明。请像检查 config.yaml 中的 # TODO 一样检查它。

不过,如果在真实终端中运行同一条命令,discover 不会止步于生成契约:只要契约中包含可调用的内容(目前并非每种来源都支持,见下文),它还会生成可运行的 config.yaml,打开与 init 可自动启动的相同免 API 密钥测试聊天页面,并打印可直接粘贴的 MCP 客户端 JSON——只需运行一条命令,就能完成发现、试用并获取连接代码片段。传入 --no-chat 可跳过这些操作,只生成契约(非交互式运行或 CI 运行时默认如此);传入 --no-write-config 则只跳过写入 config.yaml。

想先检查契约,再生成或运行任何内容?可以自行直接跳到以下任一阶段:

legacy2mcp init --from-contract contract.yaml --out config.yaml
legacy2mcp demo --from-contract contract.yaml

demo 与 discover 可自动启动的“试用”步骤相同,只是可以单独调用(也支持使用现有的 --config config.yaml,不局限于契约)。它会生成一个独立的 chat.html,指向刚启动的服务(除非传入 --no-open,否则会自动打开),并在配置就绪后打印客户端 JSON,以便指向该配置。要让页面正常工作,命令必须持续运行(按 Ctrl+C 停止);这是一个没有自带后端的轻量客户端页面,因此真实的 HTTP 调用仍须由某个程序发起。这与浏览器无法直接打开配置文件并调用 REST API 的原因相同。

以下几点值得了解:

  • 绝不会将原始密钥写入契约。 Postman 集合中保存的 bearer 令牌、HAR 捕获中的 Authorization/Cookie 标头值——这些内容都不会被持久化;只会记录存在身份验证的说明,供你自行配置。唯一受控的例外是少量看起来不敏感的枚举(例如,status 字段在足够多的样本中只出现过少数几个值,因此有参考意义)——详见 docs/security.md。
  • 对于 --har-file,legacy2mcp 不会自行驱动捕获代理——你可以指定由任何工具生成的 HAR:浏览器开发者工具中的“Export HAR”、Postman 自带的流量捕获功能,或 mitmproxy 内置的导出器(mitmdump --set hardump=out.har,或在 GUI 中选择“Export as HAR”)。这是置信度最低的来源(从采样到的内容推断,而非来自明确定义的契约)——每项操作都会被标记为需要审核。
  • --webpage-url 适用于完全没有 API 文档的旧版 Web 应用或内容网站——你只需提供 URL。它会从该地址开始抓取同一网站的页面(范围受 --max-pages/--max-depth 限制,默认 25 个页面/深度 2,且绝不会离开起始主机),将每个 <form> 转换为一项操作(<select> 的选项或同名单选/复选框组会成为 enum),并将每个包含实际内容且没有表单的页面转换为只读的“获取此页面”工具。不会执行任何 JavaScript,也不会提交任何内容;对于非 GET 表单,会添加说明,提示确认后端是否接受 JSON 请求体(REST 适配器始终会发送 JSON 请求体,即使真实浏览器会以 application/x-www-form-urlencoded 发送 POST 请求)。其置信度与 --har-file 一样低——但与其他所有 discover 来源不同,base_url 会自动填充(即刚刚抓取的主机),因此测试聊天页面可以立即打开。完整的抓取机制请参阅:docs/security.md。
  • 存储过程和队列描述目前只会记录在文档中,尚不可运行。 --stored-procs 和 --queue-config 仍会生成真实的契约条目——目前还没有适配器可以实际调用它们(参见 docs/roadmap.md),因此 init --from-contract 会跳过这些条目并明确标注 TODO,而不会假装它们可以运行。出于相同原因,如果契约仅由这些条目组成,discover 的自动演示(见上文)也没有可启动的内容;它会说明原因,然后直接退出,并保留已写入的契约,而不会让整个命令失败。
  • 每个生成的服务还会免费提供一个 describe_capabilities 工具——已连接的 Agent 可以调用它,询问“这个系统能做什么?”(获取每个工具的描述、副作用、置信度、必填字段和已知错误代码),然后再实际调用任何工具。
  • --out contract.html 会生成易于阅读的报告,而不是普通 YAML——在浏览器中以表格展示相同的操作。它仍然是有效的 --from-contract/demo --from-contract 输入:完整契约会嵌入页面中的 <script type="application/json"> 标签,而不只是生成供阅读的摘要。

让你的 AI 编码 Agent 了解 legacy2mcp

上面的章节介绍的是 legacy2mcp 生成的 MCP 服务。本节有所不同:它面向这样的场景——AI 编码 Agent(Claude Code、Cursor、Codex CLI、Gemini CLI、GitHub Copilot 等)正在帮助你构建集成,而你希望它一开始就知道该怎么做。

legacy2mcp install-skill

这会将简短、以命令为先的 legacy2mcp 指引直接写入当前仓库自己的 Agent 上下文文件——Claude Code 斜杠命令(.claude/commands/legacy2mcp.md)、Cursor 规则(.cursor/rules/legacy2mcp.mdc),以及追加(或原地更新)在 AGENTS.md、GEMINI.md 和 .github/copilot-instructions.md 中的 ## legacy2mcp 章节。这样,Agent 就会掌握核心工作流——哪种 init 标志适用于哪种来源、在信任生成的配置前检查 # TODO、在实际运行任何内容前先检查 inspect——你无需在每次会话中重新解释。这项操作具有幂等性:再次运行时会替换自身章节,而不是重复添加,因此升级后可以放心再次运行。检查它写入的内容并提交,这样整个团队就能获得相同的指引(本仓库正是这么做的——参见 AGENTS.md)。

本仓库中还有一份独立的 SKILL.md,遵循开放的 Agent Skills 标准编写——它以相同的形式提供这些知识,方便 Agensi 等市场独立于任何特定仓库列出此技能,供以这种方式发现技能的 Agent 使用。

常用命令

# Print the installed legacy2mcp version
legacy2mcp --version

# Generate a config from a live REST API (tries OpenAPI/Swagger discovery)
legacy2mcp init --rest-url "https://api.example.com" --out config.yaml

# Generate a config from a WSDL URL directly -- no scan needed
legacy2mcp init --wsdl-url "https://service.example.com/Legacy?wsdl" --out config.yaml

# Generate a config from a website with no API docs at all -- crawls it
legacy2mcp init --webpage-url "https://your-legacy-app.example.com" --out config.yaml

# Generate a config by statically scanning a GitHub repo (no AI, no API key)
legacy2mcp init --github-url https://github.com/you/your-api --scan-only --out config.yaml

# Same, with AI-assisted refinement of ambiguous parameter types / read-vs-write
legacy2mcp init --github-url https://github.com/you/your-api --llm-api-key-env OPENAI_API_KEY --out config.yaml

# Review a source before generating anything -- a Postman collection, OpenAPI
# file, HAR capture, stored-procedure catalog, or queue description
legacy2mcp discover --postman-file my-collection.json --out contract.yaml

# Try a config or contract in a chat page right now, no separate init step
legacy2mcp demo --from-contract contract.yaml
legacy2mcp demo --config config.yaml

# Review the tools a config generates -- no server started
legacy2mcp inspect --config config.yaml

# Print the tool list as JSON, for scripting or a CI diff check
legacy2mcp inspect --config config.yaml > tools.json

# Show only one exact tool name
legacy2mcp inspect --config config.yaml --tool legacy_get_order

# Start the MCP server (stdio)
legacy2mcp run --config config.yaml

# Teach the AI coding agent working in *this* repo how to drive legacy2mcp
# (see "Teach your AI coding agent about legacy2mcp" above)
legacy2mcp install-skill

客户端支持

已验证:Claude Desktop 已验证:Cursor 已验证:VS Code Claude Code 已通过 MCP Inspector 测试 MCP 兼容性

这里的“已验证”有一个具体且有限的含义:下文展示的确切命令和配置格式已实际启动,并通过 stdio 完成了真实的 MCP initialize 握手——而不只是“理论上应该兼容 MCP”。对于 MCP Inspector,测试还进一步执行了真实的 tools/list、真实的 tools/call,并检查了由此生成的审计日志条目;整个过程均通过 Inspector 自带的 --cli 模式无界面运行。最后一个徽章确保这一声明能持续经受检验,而非仅仅反映某个时间点的快照:CI 任务(mcp-compatibility.yml)会在每次推送时重新运行相同的 tools/list / tools/call / 审计日志流程;如果服务无法启动或暴露了错误的工具,构建就会失败。下方所有客户端都仅通过 stdio 与 legacy2mcp 通信——目前还没有 HTTP/SSE 传输(这项功能在路线图中,尚未发布),因此 http://localhost:... 形式的 MCP URL 在这里无法使用。

客户端状态验证方式
Claude Desktop已验证启动 claude_desktop_config.json 中的确切命令,完成真实的 initialize 握手,并确认已列出工具
Cursor已验证同上,通过 .cursor/mcp.json 中的确切命令验证
VS Code已验证同上,通过 .vscode/mcp.json 中的确切命令验证
Claude Code已说明通过 claude mcp add 使用与上述已验证内容相同的启动命令;但该命令本身并未在此环境中单独重新运行
MCP Inspector已测试完整的 CLI 流程——tools/list、tools/call,以及由此生成的审计日志条目
此仓库还附带已纳入版本控制的配置文件——
.mcp.json、.cursor/mcp.json 和
.vscode/mcp.json——它们指向打包的 Petstore
演示,因此在这些工具中打开此仓库,无需设置即可获得可运行的服务。将与你的工具对应的配置文件复制到自己的项目中,并将 --config 指向你自己的 config.yaml。
Claude Desktop — claude_desktop_config.json

macOS:~/Library/Application Support/Claude/claude_desktop_config.json Windows:%APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "legacy2mcp": {
      "command": "uvx",
      "args": ["legacy2mcp", "run", "--config", "/absolute/path/to/config.yaml"]
    }
  }
}

如果你使用 pip/pipx 而非 uv 安装,请使用 "command": "legacy2mcp",并删除 args 的第一个元素。

Cursor — .cursor/mcp.json

项目本地配置(.cursor/mcp.json)或全局配置(~/.cursor/mcp.json):

{
  "mcpServers": {
    "legacy2mcp": {
      "command": "uvx",
      "args": ["legacy2mcp", "run", "--config", "/absolute/path/to/config.yaml"]
    }
  }
}
VS Code — .vscode/mcp.json
{
  "servers": {
    "legacy2mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["legacy2mcp", "run", "--config", "/absolute/path/to/config.yaml"]
    }
  }
}
Claude Code — CLI
claude mcp add legacy2mcp -- uvx legacy2mcp run --config /absolute/path/to/config.yaml

添加 --scope project,即可为团队写入共享的 .mcp.json(请勿在其中存放密钥);使用 claude mcp list 检查。

MCP Inspector — 验证工具,而非 AI 客户端
npx @modelcontextprotocol/inspector uvx legacy2mcp run --config /absolute/path/to/config.yaml

打开本地 Web 界面:连接到服务,确认工具已列出,运行一个只读工具,并检查 legacy2mcp-audit.log 中对应的条目。上方“Tested with MCP Inspector”徽章所依据的,正是这一完整流程——发现工具、实际调用一次,以及查看生成的审计日志;该流程通过 Inspector 自带的 --cli 模式在无界面环境中运行,而非仅在浏览器中打开。

传递密钥和故障排查:docs/clients.md。

已处理的内容

领域覆盖内容
类型映射string / int / long / decimal / boolean / date / dateTime / base64Binary / … → JSON Schema 类型 + 格式
结构嵌套复杂类型、重复元素 → 数组,xsd:enumeration → enum,递归深度受限
发现每个服务 → 端口 → 绑定 → 操作;启动时拒绝重复的工具名称
调用参数验证、zeep 调用、将响应序列化为纯 JSON、将单字段响应重新包装为具名结果
错误捕获 SOAP 错误和传输错误,并以清晰的消息返回——不会向调用方返回堆栈跟踪
身份验证HTTP 基本身份验证(用户名 + *_env 密码);承载令牌(*_env);匿名
传输stdio(Claude Desktop 和大多数 Agent 框架会启动的传输方式)
数据库方言Postgres、SQL Server、Oracle——表允许列表(select/insert),支持实时架构内省,以及具名参数化查询
REST从配置或 legacy2mcp init 设置显式端点允许列表(方法 + 路径 + 类型化参数)——没有可供内省的实时架构,因此运行前无法验证此处的任何内容
发现数据源Postman 集合、本地 OpenAPI/Swagger 文件、实时数据库的存储过程目录、HAR 流量捕获、声明式队列描述,以及网站(--webpage-url,可抓取表单/内容)→ 可供审核的 contract.yaml(置信度、枚举、错误代码)→ legacy2mcp init --from-contract 或直接使用 init --webpage-url/demo
describe_capabilities每个生成的服务都免费提供此元工具——Agent 可在调用任何内容之前询问服务能做什么
试用 + 连接init/discover/demo 都会自动打开一个无需 API 密钥的测试聊天页面,并打印可直接粘贴的连接代码片段,适用于 Claude Desktop、Cursor、VS Code 和 Claude Code

完整且如实的安全模型(包括目前已覆盖和尚未覆盖的内容),请参阅 docs/security.md。

安全模型

层作用
架构验证所有参数都会先根据该工具生成的架构通过 jsonschema.validate 验证,之后才会到达 SOAP/DB 层。
默认只读SOAP:操作名称会与写入动词前缀(Create、Update、Delete、Cancel、Void、Submit、Pay 等)进行匹配。DB:表/查询必须显式选择加入,此外,insert/标记为写入的查询也需要选择加入。除非设置 allow_write_operations: true,否则不会公开这些操作。
显式允许/拒绝SOAP:include_operations / exclude_operations。DB:表/列允许列表——没有等同于“所有表”或任意 SQL 的选项。
审计日志每次调用记录一行 JSON——工具、参数、时间戳、结果、耗时。
密钥管理凭据和 DB 连接字符串来自指定名称的环境变量;YAML 文件可安全提交。

警告

SOAP 写入操作过滤器是基于名称的启发式规则,而非语义分析——名为 ProcessRecord、但会删除数据的操作无法被识别。对于错误调用会造成实际后果的系统,请显式设置 include_operations,不要依赖该启发式规则。DB 适配器的允许列表在设计上是显式的,但没有列级数据屏蔽——允许列表中的列,其值始终会原样返回。此外,MCP 服务本身尚未实现身份验证/授权——请勿将服务暴露给不受信任的调用方。详情请参阅 docs/security.md。

数据流和隐私

  • 不收集遥测数据。 legacy2mcp 不收集使用数据,也不会向外发送任何信息。它发起的每个网络调用都是你配置的调用——在写下这句话之前,我们通过检查源代码中的每个出站 HTTP 调用位置进行了验证。
  • 适配器调用只会前往你指定的位置,不会前往其他地方。 SOAP 调用会发送到你的 wsdl_url,DB 调用会使用 dsn_env 连接,REST 调用会发送到你的 base_url。
  • legacy2mcp init 的发现调用仅限于你提供的内容。 WSDL 和 REST(OpenAPI)路径只会联系你传入的 URL。GitHub/源代码路径会克隆你指定的仓库,并使用 ast 在本地解析——不会执行其中的任何内容。
  • 可选的 LLM 辅助步骤只会发送已检测到的模糊片段,不会发送你的仓库。 该步骤仅在 legacy2mcp init 的 GitHub/源代码路径中运行,且只有在你提供 API 密钥时才会运行;它只会发送静态扫描已标记为模糊的具体路由名称/路径/参数,不会发送源代码转储。使用 --scan-only 可完全跳过此步骤。
  • legacy2mcp discover 会读取本地文件,但 --stored-procs 除外。 Postman/OpenAPI/HAR/队列来源不会访问网络——它们只会读取你提供的文件。--stored-procs 会像 db 适配器一样,连接到你指定的环境变量中的 DSN,但只用于读取过程/函数目录。生成的 contract.yaml 中绝不会写入原始密钥或采样值——请参阅 docs/security.md。
  • 密钥绝不会存储在 config.yaml 中。 密码、DSN 和 API 令牌都会通过环境变量名称(password_env、dsn_env、token_env)进行引用,并在运行时读取——YAML 文件可安全提交。
  • 审计日志保存在本地,且静态存储时未加密。 每次工具调用都会作为一行 JSON 追加到 security.audit.path。参数会原样记录——不会对个人身份信息(PII)进行脱敏;审计日志的完整功能说明请参阅 docs/security.md。

用例

领域形式
记录系统Agent 以只读方式从旧版后台平台读取状态和详情记录,每次查询都会记录日志。
金融服务提供账户和交易的读取功能,但不开放转账或调整操作。
供应链 / ERP从旧版 SOAP 中间件层获取订单状态、库存和货运跟踪信息。
内部支持工具支持助手可安全地以类型化方式访问记录系统,而不是使用抓取的 UI。
迁移与现代化现在在旧版服务前部署 MCP 层;以后更换后端,无需改动 Agent。

实际应用

在 CI/CD 中——在 WSDL 变更进入生产环境前发现问题

legacy2mcp inspect 会加载配置、连接 WSDL、构建所有架构;如果任何步骤失败,则以非零状态码退出:

- 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 contract

退出码:

代码含义
0成功
1配置、源或运行时错误——WSDL/DB/REST 配置错误、无法克隆仓库、缺少必需的环境变量等
2命令行参数无效(argparse 自带的默认值)
作为 sidecar / 长时间运行的 MCP 服务

legacy2mcp run 通过 stdio 使用 MCP。使用提供的 Dockerfile 将其与配置一起打包,然后让 MCP 客户端启动它。

在数据管道中

通过任意 MCP 客户端库,在自己的代码中调用同一批已生成并经过验证的工具,按计划拉取记录——审计日志会准确记录获取了哪些数据。

配置参考

键默认值含义
server.namelegacy2mcp向客户端报告的 MCP 服务名称
server.transportstdio目前仅实现了 stdio
adapters[].id—此适配器工具名称的前缀
adapters[].type—soap、db 或 rest(已实现);queue 已列入路线图

SOAP 适配器配置:

键默认值含义
adapters[].config.wsdl_url—WSDL 位置(http(s)://…?wsdl 或文件路径)
adapters[].config.auth{type: none}none 或 {type: basic, username, password_env}
adapters[].config.allow_write_operationsfalse暴露类似写入的操作
adapters[].config.include_operationsall操作名称的允许列表
adapters[].config.exclude_operations[]操作名称的拒绝列表
adapters[].config.timeout_seconds15每次 SOAP 调用的超时时间

DB 适配器配置:

键默认值含义
adapters[].config.dialect—postgres、mssql 或 oracle
adapters[].config.dsn_env—保存连接字符串/DSN 的环境变量
adapters[].config.allow_write_operationsfalse暴露 insert_<table> 和 write: true 查询
adapters[].config.timeout_seconds15连接超时时间
adapters[].config.tables[].name / .schema—允许列表中的表(以及可选的架构/所有者)
adapters[].config.tables[].operations[select]select 和/或 insert
adapters[].config.tables[].columnsall introspected列允许列表
adapters[].config.tables[].filterable_columns[]可在 select_<table> 中用作等值筛选条件的列
adapters[].config.tables[].max_rows200行数上限,在查询运行后强制执行
adapters[].config.queries[].name / .sql / .params—命名查询;sql 使用 :param_name 占位符
adapters[].config.queries[].writefalse此查询是否受 allow_write_operations 控制

REST 适配器配置:

键默认值含义
adapters[].config.base_url—已配置端点所基于的 URL
adapters[].config.auth{type: none}none、{type: basic, username, password_env} 或 {type: bearer, token_env}
adapters[].config.allow_write_operationsfalse暴露标记为 write: true 的端点
adapters[].config.timeout_seconds15每次 HTTP 调用的超时时间
adapters[].config.endpoints[].name / .method / .path / .description—允许列表中的一个端点;path 使用 {param} 占位符表示路径参数
adapters[].config.endpoints[].params[].name / .location / .type / .required—location 可以是 path、query 或 body
adapters[].config.endpoints[].params[].enumunset允许值的封闭集合,通过架构验证强制执行,而非仅作描述
adapters[].config.endpoints[].writefalse此端点是否受 allow_write_operations 控制
adapters[].config.endpoints[].confidence / .error_codes / .needs_reviewunset / [] / false仅由 legacy2mcp discover + init --from-contract 填充——表示对发现结果的信任程度、已知错误响应,以及是否需要人工审查

安全配置:

键默认值含义
security.audit.enabledtrue写入审计日志
security.audit.path./legacy2mcp-audit.log审计日志位置

文档

文档内容
docs/security.md完整、坦诚的安全模型——当前已验证和审计的内容,以及尚未完成的部分
docs/roadmap.md按版本列出的已发布与计划内容
docs/clients.md连接所有受支持的 MCP 客户端、密钥和故障排查
docs/releasing.mdPyPI / MCP Registry 发布流程
docs/registry-submissions.mdRegistry / awesome-list 提交状态和可复用文案
examples/README.md所有可运行的演示配置(SOAP、REST、Docker)
llms.txt面向大模型和 Agent 的机器可读项目摘要
skill/legacy2mcp/面向编码 Agent(Claude Code、Cursor、Copilot 等)的 SKILL.md——教 Agent 何时以及如何使用 legacy2mcp 本身
CHANGELOG.md按版本列出的重要变更
CONTRIBUTING.md开发环境设置、添加适配器的方法和 PR 要求

路线图

版本范围状态
v0.1SOAP/WSDL 适配器、架构生成、验证、默认只读、审计日志、run + inspect CLI、基本身份验证、stdio✅ 已发布
v0.2数据库适配器(Postgres / SQL Server / Oracle;表/操作允许列表 + 命名参数化查询,绝不执行任意 SQL)✅ 已发布
v0.2.xREST 适配器(显式端点允许列表);legacy2mcp init -- 扫描代码库(SOAP 客户端 / ORM 模型 / Flask/FastAPI 路由)并生成初始配置,可选用兼容 OpenAI 的 LLM 辅助处理含糊内容✅ 已发布
v0.3.xlegacy2mcp discover(Postman / OpenAPI 文件 / HAR / 存储过程 / 队列 / --webpage-url)→ 可供审核的 contract.yaml;--webpage-url 会抓取整个网站,而不只是单个页面;describe_capabilities 元工具✅ 已发布
v0.4.xlegacy2mcp demo -- 无需单独执行 init,即可在聊天页面中试用合约/配置;discover --out contract.html✅ 已发布
v0.5.xdiscover/init/demo 都会自动打开测试聊天,并打印可直接粘贴的 MCP 客户端连接代码片段;init --webpage-url 可直接生成配置✅ 已发布
计划中HTTP/SSE 传输、角色→工具授权、SOAP 的 OAuth2计划中
想法队列适配器(Kafka/RabbitMQ/SQS)、带审批关卡的工作流编排、OpenTelemetry 导出想法

详见 docs/roadmap.md。BaseAdapter 接口(discover_tools() + invoke())是扩展点——服务器核心负责处理任意适配器的验证、分发和审计。

开发

pip install -e ".[dev]"
pytest tests/ -v

测试使用进程内模拟 SOAP 服务,以及基于 SQLite 的进程内模拟数据库适配器——无需网络,也无需真实的 Postgres/SQL Server/Oracle。数据库适配器的 Postgres/SQL Server/Oracle 方言(db_dialects.py)通过不依赖驱动程序的单元测试覆盖其 SQL 转换逻辑;默认测试套件不包含连接到各类真实实例的测试。

CI 在 Python 3.10–3.12 上运行测试套件 (ci.yml)。PyPI 和 MCP Registry 的发布由标签触发——详见 docs/releasing.md。演示 GIF 使用 vhs demo/demo.tape 重新生成(demo/)。

贡献

为新的旧系统开发适配器是最有价值的贡献——实现 BaseAdapter,其余工作由核心处理。有关开发环境设置、适配器结构和 PR 要求,请参阅 CONTRIBUTING.md。本项目遵循行为准则。欢迎提交 Issue 和 PR。

许可证

Apache 2.0

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。