MCP Connection Test Server
README.md
# 兴先达订单与库存 MCP Server
这是一个只使用 Streamable HTTP 的云端 MCP Server。它把下单系统与库存系统
封装成 Agent 可以发现和调用的 MCP 工具。公网入口为:
```text
https://你的域名/mcp
```
MCP Server 本身不调用模型,Agent 负责决定何时调用工具。服务保留
`mcp_connection_test` 作为链路检查,并提供 3 个业务工具:
- `get_latest_inventory`:获取全部库存,或查询一个 SKU 的最新库存。
- `update_inventory_from_order`:读取一张已存在订单,并把订单中的
`inventoryDelta` 幂等地应用到库存系统。
- `create_order`:在订单系统中创建订单,但不会隐式调用库存更新。
## 部署结构
```text
上游 MCP 客户端 -> 已有 HTTPS 服务 443 -> 127.0.0.1:18080 -> MCP 容器 8000
-> 订单系统 API
-> 库存系统 API
```
项目不再启动 Caddy,也不占用 80、443。MCP 只绑定服务器本机回环地址,
由现有 Nginx、Apache 或 Caddy 使用已有证书反向代理。
## 一、准备服务器和域名
1. 云服务器安装 Docker Engine 和 Docker Compose 插件。
2. 准备已有证书覆盖的域名,例如 `mcp.example.com`。
3. 确认现有 HTTPS 服务能够修改反向代理配置。
`MCP_DOMAIN` 只填写域名,不要包含 `https://` 或路径。
## 二、上传项目
在本地 Mac 执行,将 `SERVER_USER` 和 `SERVER_IP` 换成真实值。这里明确排除
本地 `.env` 和虚拟环境,避免把旧 API Key 或无关文件上传到服务器:
```bash
rsync -av \
--exclude='.env' \
--exclude='.venv' \
--exclude='__pycache__' \
"/Users/clarence/Desktop/项目/兴先达/MCPtest/" \
SERVER_USER@SERVER_IP:~/mcp-connection-test/
```
登录服务器:
```bash
ssh SERVER_USER@SERVER_IP
cd ~/mcp-connection-test
```
## 三、填写域名并启动
```bash
cp deploy.env.example deploy.env
```
编辑 `deploy.env`:
```text
MCP_DOMAIN=mcp.example.com
MCP_LOCAL_PORT=18080
PYTHON_IMAGE=public.ecr.aws/docker/library/python:3.12-slim
ORDER_API_BASE_URL=http://host.docker.internal:32769
INVENTORY_API_BASE_URL=http://host.docker.internal:32768
```
`PYTHON_IMAGE` 默认使用 AWS Public ECR 中的 Python 官方镜像,构建时不会再访问
Docker Hub。Amazon ECR Public 的公开镜像无需登录即可拉取;若服务器曾保存过
错误的 ECR 登录状态,可先执行 `docker logout public.ecr.aws`。
如果订单或库存 API 不在 MCP 宿主机,把对应地址换成 Agent 网络能够访问的
`http://` 或 `https://` 地址。如果业务 API 使用 Bearer Token,再填写
`ORDER_API_TOKEN` 和 `INVENTORY_API_TOKEN`;令牌只放在 `deploy.env`,不要提交
到仓库。
配套库存系统默认固定映射为宿主机端口 `32768`。不要再使用随机端口;如果因
端口冲突确实需要修改,库存系统的 `INVENTORY_PORT` 与这里的
`INVENTORY_API_BASE_URL` 必须同步调整。
如果 18080 已被占用,可以改成其他未使用的高位端口,例如 18081。检查端口:
```bash
sudo ss -ltnp | grep ':18080'
```
构建并后台启动:
```bash
docker compose --env-file deploy.env up -d --build
```
如果之前启动过旧版 Caddy 编排,使用下面的命令同时清理已经移除的 Caddy
容器;不会影响服务器上其他项目的容器:
```bash
docker compose --env-file deploy.env up -d --build --remove-orphans
```
查看运行状态和日志:
```bash
docker compose --env-file deploy.env ps
docker compose --env-file deploy.env logs --tail=100
```
## 四、接入现有 HTTPS 服务
如果使用 Nginx,将 `nginx-mcp-location.conf.example` 中的 `location = /mcp`
配置加入已有证书域名对应的 `server { ... }` 中。确认反向代理端口与
`MCP_LOCAL_PORT` 一致,然后执行:
```bash
sudo nginx -t
sudo systemctl reload nginx
```
Nginx 的 `proxy_pass` 应指向:
```text
http://127.0.0.1:18080
```
最终公网 MCP 地址仍然是:
```text
https://mcp.example.com/mcp
```
## 五、验证工具发现和调用
在本地 Mac 执行,验证公网链路:
```bash
/opt/homebrew/Caskroom/miniconda/base/bin/python \
"/Users/clarence/Desktop/项目/兴先达/MCPtest/verify_remote.py" \
https://mcp.example.com/mcp
```
成功时会显示:
```text
发现工具:create_order, get_latest_inventory, mcp_connection_test, update_inventory_from_order
调用返回:MCP连接成功
```
这一步会真实执行 MCP 初始化、`tools/list` 和 `tools/call`,比普通的端口或
HTTP 检查更准确。
## 六、上游配置
将上游 MCP 客户端的服务器 URL 配置为:
```text
https://mcp.example.com/mcp
```
### 获取最新库存
查询全部库存:
```json
{}
```
查询单个库存:
```json
{
"sku": "003"
}
```
`sku` 同时接受 `3`、`003` 或 `X-003`。返回的 `meta.version` 可用于后续
需要并发保护的更新。
### 创建订单
```json
{
"product_id": 3,
"quantity": 5
}
```
成功后记住返回的 `order.id`。订单系统当前是补货单语义,因此新订单包含
`inventoryDelta: 5`;创建订单本身不会自动修改独立库存系统。
### 根据订单更新库存
```json
{
"order_id": "ORD-20260821153000-ABCD"
}
```
工具会读取订单,将 `X-003` 映射为库存 SKU `003`,再把
`inventoryDelta` 应用到库存。库存请求使用订单号生成幂等键,同一订单重复
调用不会重复增加库存。
如果 Agent 刚读取过库存,也可以带版本号进行乐观并发保护:
```json
{
"order_id": "ORD-20260821153000-ABCD",
"expected_version": 7
}
```
如果返回 `VERSION_CONFLICT`,Agent 应重新调用 `get_latest_inventory`,确认新
库存后再决定是否重试。普通订单同步不强制填写 `expected_version`。
### 推荐的 Agent 调用顺序
1. 需要确认现货时调用 `get_latest_inventory`。
2. 用户确认下单后调用 `create_order`。
3. 使用返回的 `order.id` 调用 `update_inventory_from_order`。
4. 如需向用户确认最终库存,再调用一次 `get_latest_inventory`。
订单创建与库存更新是两个独立动作。这样即使第二步之后网络中断,Agent 仍可
用同一订单号安全重试库存同步,也不会重复下单。
## 本地测试
业务适配层单元测试不需要启动服务:
```bash
python -m unittest -v test_mcp_tools.py
```
三系统联调测试会使用临时数据文件和随机本机端口,不会修改现有测试数据:
```bash
python integration_test.py
```
### 连接测试
工具 `mcp_connection_test` 可传空对象 `{}`,也可传:
```json
{
"probe": "upstream-health-check"
}
```
## 更新与停止
更新代码后重新部署:
```bash
docker compose --env-file deploy.env up -d --build
```
停止服务:
```bash
docker compose --env-file deploy.env down
```
## 常见问题
- 返回 `421 Invalid Host header`:`deploy.env` 中的域名与访问域名不一致。
- MCP 连接出现 `Connection refused`:检查 `MCP_LOCAL_PORT`、容器状态及反向代理端口。
- 工具返回“无法连接订单系统/库存系统”:从 MCP 容器内检查
`ORDER_API_BASE_URL`、`INVENTORY_API_BASE_URL` 与实际端口。配套库存系统的
默认地址应为 `http://host.docker.internal:32768`。
- 库存返回 `SKU_NOT_FOUND`:检查订单 SKU 与库存系统的 `001`–`010` 是否对应。
- 库存返回数量不能小于 0:该订单的 `inventoryDelta` 会使库存越界,需要先核对订单方向和当前库存。
- 查看 MCP 服务日志:`docker compose --env-file deploy.env logs mcp-server`。
- HTTPS 相关问题继续查看服务器现有 Nginx、Apache 或 Caddy 日志。
## 安全要求
这个 MCP 现在包含可创建订单和修改库存的写工具,不能把无鉴权入口直接暴露到
公网。正式使用时必须在现有 HTTPS 网关增加访问控制,例如 OAuth、受管 API
网关或固定来源 IP 白名单;业务系统自身也建议启用 Bearer Token。日志中不要
记录 `ORDER_API_TOKEN`、`INVENTORY_API_TOKEN` 或完整的 Authorization 请求头。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues