Infor MCP
by zyx5256
README.md
# Infor MCP:可扩展的多请求服务
这个工程把已验证的 Infor HTTP/SOAP 请求发布为 MCP 工具。
**一个请求配置对应一个有名字的工具;添加其他服务或操作时,不需要改公共服务器代码。**
当前接入的第一个请求是 `list_sales_orders()`。公共认证、请求发送、参数处理、错误处理和
MCP 注册均独立于 SalesOrder。其他 SOAP 服务及 HTTP/JSON API 可以加入同一个服务。
本项目是独立的社区工程,与 Infor 无官方隶属关系。目前为本机运行的概念验证版本。
## 工程结构
```text
server.py 通用 MCP 启动入口
config.json 服务器设置、命名认证配置、请求目录(本机文件)
.env 地址和凭据(本机文件)
requests/ 当前启用的请求目录(本机文件)
sales_order/
list.request.json list_sales_orders 工具定义
list.xml 这个请求的完整 SOAP Body
<其他服务>/
<操作>.request.json 后续新增请求
<操作>.xml / <操作>.body.json 该请求自己的报文
infor/
config.py 公共配置与认证配置验证
catalog.py 加载请求目录,编译参数定义
templates.py URL/XML/JSON 参数编码
auth.py OAuth/Bearer 与按认证配置隔离的 token 缓存
http_client.py 通用请求执行与响应处理
registry.py 将每个请求注册成独立 MCP 工具
examples/ 可复制模板,不会自动注册
sales_order/ 第一个已验证请求的配置样例
http_lookup/ 带参数的 HTTP 请求结构示例,默认关闭
request.template.json 新请求起点
smoke_test.py 发现工具,或调用明确指定的工具
tests/ 模拟上游测试
docs/adding-requests.md 添加请求、参数和认证配置的步骤
```
配置文件负责指定实际接口,公共代码不推测 Infor 的 URL、WSDL operation、SOAPAction 或业务字段。
同一个服务可以有多个操作,每个操作有自己的工具名、Headers、Body 和参数定义。
## 开始使用
在项目目录运行(需要 Python 3.10+):
```bash
git clone https://github.com/zyx5256/Inforn-LN-MCP.git
cd Inforn-LN-MCP
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
```
Windows PowerShell 使用 `.venv\Scripts\Activate.ps1` 激活环境。
首次使用时准备本机配置(已有配置时不要覆盖):
```bash
cp .env.example .env
cp config.oauth.example.json config.json
mkdir -p requests/sales_order
cp examples/sales_order/* requests/sales_order/
```
然后在 `.env` 填写真实值。认证凭据和业务地址不写入公共代码。
启动:
```bash
python server.py
```
地址为 `http://127.0.0.1:8000/mcp`,传输方式为 **Streamable HTTP**。
配置在启动时加载,修改后重启。`MCP_PORT` 可改变监听端口,`INFOR_CONFIG` 可指定配置文件。
启动入口通过 Uvicorn 提供 SDK 的 HTTP 应用,显式设置 `ws="none"`。
本服务不需要 WebSocket;这样也避免 Conda 等环境中已有旧版 `websockets` 干扰 HTTP 服务启动。
## 发现和调用工具
在另一个已激活环境的终端中:
```bash
# 仅查看已注册工具及参数,不调用 Infor
python smoke_test.py
# 明确调用当前的订单列表请求
python smoke_test.py --tool list_sales_orders
# 以后调用带参数的工具,按该工具的参数定义填写
python smoke_test.py --tool 你的工具名 --args '{"参数名":"参数值"}'
```
命令行客户端支持整个工具目录,仅在指定工具名时执行请求。
MCP Inspector 也可以选择 Streamable HTTP 连接上述地址,查看多个工具并单独调用。
## 添加第二个及更多请求
详见 [扩展请求指南](docs/adding-requests.md)。核心流程:
1. 在 `requests/<服务名>/` 新建 `<操作名>.request.json`。
2. 设置唯一工具名、说明、认证配置名称、URL、方法和该请求自己的 Headers。
3. 把 Postman 中已跑通的 Body 放在同目录的独立文件中。
4. 有输入参数时声明 `parameters`,并在报文或 URL 中使用 `{{参数名}}`。
5. 完成配置后设置 `enabled: true`,重启,先查看工具列表,再单独测试新工具。
只加载 `*.request.json`,不会把 JSON Body 当成工具配置。
`enabled: false` 的请求不注册,也不要求其环境变量或报文文件已存在。
重复工具名、缺失认证配置、未声明的参数占位符会在启动时报告错误。
## 认证与 token
`config.json` 的 `auth_profiles` 保存可复用的命名认证配置。
每个请求通过 `"auth": "ion"` 选择自己的认证配置;不同服务可以共用,也可以分别配置。
支持 OAuth 表单请求、手动 Bearer token;不选认证配置时可以使用请求自己的 API key Header。
当前 `ion` 配置复用已验证的 Postman 方式:
- Client ID / Client Secret 通过 Basic Auth 发送。
- 表单发送 `grant_type=password`、Username、Password。
- 同一个认证配置的多个请求共用有效 token,不同配置隔离。
- 返回有效 `expires_in` 时按有效期缓存,提前最多 30 秒重新获取;缺少有效期时不缓存。
- 收到业务接口 401 后清除该配置的缓存,下一次调用重新获取。
- 不自动重发业务请求;尚未实现 refresh token 流程。
## 第一个已接入的请求
`requests/sales_order/list.request.json` 对应 `list_sales_orders()`,无需参数。
示例 XML 使用公司 `101`、`bo:List` 和 `maxNumberOfObjects=5`。
使用前请按你的 LN 环境修改公司编号,并核对服务定义与访问权限。
它最多取 5 条,没有实现分页或最新排序。这个范围只属于该请求,不限制其他工具。
目前这个请求使用:
```dotenv
INFOR_SOAP_ACTION='""'
```
外层单引号是 `.env` 语法,实际发送 `SOAPAction: ""`。
其他请求可以有自己的 SOAPAction、完全不使用 SOAPAction,或使用不同的 Content-Type。
每个请求按实际接口定义配置。
## 返回数据与扩展边界
所有工具返回统一外层结构:`source`、`request`、`status_code`、`format`、`data`。
XML 原文位于 `data`;JSON 响应解析为 JSON 值。没有针对某个业务对象硬编码字段映射。
HTTP 错误和 SOAP Fault 会作为 MCP 工具错误返回,不回退成模拟数据。
请求可配置 GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS,并明确声明 `read_only`。
该标记用于 MCP 工具提示,不是权限校验;配置内容决定实际执行的操作。
当前启用目录只包含已知的订单列表请求,示例不会自动产生额外业务调用。
需要复杂字段映射、分页、组合多个 API、上传文件或严格的嵌套业务数据校验时,
可在公共执行层之外增加专用适配模块。当前声明式请求已支持参数类型、默认值、数值和长度范围;
尚未实现 Postman Collection 自动导入和 Postman 脚本执行。
## 验证与运行环境
```bash
python -m unittest discover -s tests -v
```
业务和协议测试用多个模拟服务验证工具注册、不同认证配置隔离、参数编码、token 复用、错误处理,
并通过内存 ASGI 传输验证 Streamable HTTP 协议处理;这些测试不访问真实 Infor,也不需要监听端口。
另外,`tests/test_startup.py` 会实际启动 `server.py`、监听临时本机端口并执行工具发现,
验证真实启动链路。它使用隔离的测试配置,不调用 Infor。
### TLS 证书错误
TLS 握手失败会阻止 OAuth 或业务请求。程序会分别报告 TLS、DNS、连接失败和超时。
如果使用公司内部 CA,请从管理员取得可信的 CA 证书链(PEM 格式,不含私钥),
在 `.env` 添加实际文件路径并重启服务:
```dotenv
INFOR_CA_FILE="certs/company-ca.pem"
```
相对路径以 `config.json` 所在目录为基准,也可填写绝对路径。
也可以在 `config.json` 设置 `tls_ca_file`;该项优先于环境变量。
该信任配置同时用于 OAuth 和业务请求,保留证书链、有效期和主机名验证。
如果证书过期、主机名不匹配或本身不合规,仅添加 CA 仍可能失败,需要服务器管理员修复证书。
Postman 成功不等于它启用了相同的证书校验,请检查该请求的 SSL certificate verification 设置。
此服务保持 TLS 校验,仅监听本机,尚未实现 MCP 入站认证或正式云端部署。
`.env`、`config.json`、`requests/`、`certs/`、证书/私钥文件和 `.local-backup/` 均被 Git 忽略。
可复用的请求示例放在 `examples/`,提交前去掉真实地址、账号、客户数据和公司内部配置。
实现使用 [官方 MCP Python SDK](https://py.sdk.modelcontextprotocol.io/)。
## 许可证
本项目采用 [Apache License 2.0](LICENSE)。允许在遵守许可证条款的前提下使用、修改、分发和商用。
托管、部署和技术支持可以作为付费服务提供;这些服务不改变本仓库代码的开源许可。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues