本设计中的同步等待和直接返回文件 URL 合同已由
2026-07-22-mcp-async-export-task-design.md取代;本文只保留为历史设计背景。
fmsoperate/app/admin/view/outbound/add.html 已提供“导出未排舱订单”功能。页面把当前筛选条件提交到
export/asyncExportData,固定使用 EXPORT_PEND_OUTBOUND_ORDER,并通过 is_sync=1 同步等待导出
任务完成后取得 OSS 下载链接。
本次在 MCP 中开放相同能力。MCP 不重新实现订单筛选或 Excel 生成逻辑,只复用 fmsoperate 已有的 员工会话、数据权限、未排舱订单查询和导出任务,最终向调用方返回下载链接。
export_pending_outbound_orders。list_pending_outbound_export_filter_options,让 AI 先把用户提供的筛选名称解析成当前员工有权使用的值。outbound/add.html 完全一致。ExportPendOutboundOrderLogic 和 OutboundModel::getPendOutboundOrder(),确保导出内容与页面一致。所有筛选参数均为可选。不传筛选条件时,行为与页面清空筛选后点击“导出未排舱订单”一致。
| 页面中文名称 | MCP 参数名 | 类型与传参方式 | 业务说明 |
|---|---|---|---|
| 单号 | number |
字符串 | 订单号、参考号。可录入多个单号,以空格、英文逗号或回车分割。保持页面原始字符串格式,由现有导出逻辑调用 format_numbers()。 |
| 产品分类 | product_type_id |
整数 | 单选产品分类 ID。 |
| 物流产品 | product_id |
整数数组 | 多选物流产品 ID。与页面 product_id 多选提交的数组一致。 |
| 集货仓库 | order_warehouse_id |
整数 | 单选集货仓库 ID。 |
| 目的国 | receiver_country |
字符串 | 单选目的国国家代码,如 US。 |
| 是否装柜剔除 | is_remove |
整数 | 1 表示是,0 表示否;不传表示全部。必须保留 0 的有效含义。 |
| 派送地址 | address |
字符串 | 按页面现有规则模糊匹配派送地址。 |
| 入库时间 | inbound_date |
字符串 | 日期范围,格式为 YYYY-MM-DD - YYYY-MM-DD。由现有导出逻辑按员工时区转换开始和结束时间。 |
| 订单状态 | status |
整数数组 | 多选订单状态。页面可选值为 0、10、20、30、40,默认选中 30、40;MCP 不传时不擅自补默认值,只有用户明确要求按页面默认筛选时才传 [30, 40]。 |
| 商品属性 | is_battery |
字符串枚举 | 页面选择“带电”后提交 is_battery="Y"。 |
| 商品属性 | is_magnetic |
字符串枚举 | 页面选择“带磁”后提交 is_magnetic="Y"。 |
| 商品属性 | is_wood |
字符串枚举 | 页面选择“带木”后提交 is_wood="Y"。 |
| 商品属性 | is_other |
字符串枚举 | 页面选择“其它”后提交 is_other="Y"。 |
| 商品属性 | is_fda |
字符串枚举 | 页面选择“FDA产品”后提交 is_fda="Y"。 |
| 商品属性 | is_toy |
字符串枚举 | 页面选择“玩具”后提交 is_toy="Y"。 |
| 商品属性 | is_ultra_limit |
字符串枚举 | 页面选择“单箱尺寸超长超重”后提交 is_ultra_limit="Y"。 |
| 商品属性 | is_sensitive |
字符串枚举 | 页面选择“敏感货”后提交 is_sensitive="Y"。 |
| 商品属性 | is_food |
字符串枚举 | 页面选择“食品”后提交 is_food="Y"。 |
| 商品属性 | no_property |
字符串枚举 | 页面选择“无属性”后提交 no_property="Y"。 |
| 合并报关单号 | merge_declare_number |
字符串 | 精确匹配合并报关单号。 |
| 进口商 | importer_id |
整数 | 单选进口商 ID。 |
| 货物类型 | packing_type |
字符串 | 页面多选后以英文逗号拼接,例如 散货,整柜;不能改为数组。 |
多选参数必须严格保持页面的三种不同传法:
product_id、status 使用数组。property_2;每个选中属性转换为对应字段并传字符串 Y。packing_type 使用英文逗号拼接的字符串。Gateway 只接受白名单中的参数。property_2、export_type、is_sync、company_id、operator_id、
is_super、timezone 等页面内部字段或身份字段不放入 MCP Schema。
用户提供产品、仓库、国家、进口商等业务名称时,AI 必须先调用
list_pending_outbound_export_filter_options 查询当前员工有权使用的选项,再把返回的 value 原样传给
导出工具。不得根据名称、历史调用或示例猜测 ID。
product_id、product_type_id、order_warehouse_id、importer_id 使用筛选项返回的 ID。receiver_country 使用国家选项返回的国家代码。packing_type 使用货物类型选项返回的名称值;多选时以英文逗号拼接。Y。status 使用订单状态选项返回的整数值。新增 ExportPendingOutboundOrdersTool:
export_pending_outbound_orders。/mcp/tools/exportPendingOutboundOrders。ApiClient / ScopedApiClient 转发,并携带工具代码和 request ID。本地 stdio 与公网 Gateway 都注册该工具;是否展示和允许调用继续由 fmsoperate 的动态工具注册表控制。
新增 ListPendingOutboundExportFilterOptionsTool:
list_pending_outbound_export_filter_options。/mcp/tools/listPendingOutboundExportFilterOptions。filter_type,可选 keyword、page、limit;查询物流产品时可选传
product_type_id,实现与 add 页面相同的产品分类联动。filter_type 支持 product_type、product、warehouse、country、importer、
packing_type、order_status、goods_attribute、is_remove。records,每项包含可直接用于导出参数的 value、显示名称 label 和辅助识别字段
code;分页信息放在 meta。新增 MCP Controller 路由、Validate 规则和专用 Logic。Controller 仅接收请求、调用 Logic 并返回统一响应。
Logic 执行以下步骤:
export_type=EXPORT_PEND_OUTBOUND_ORDER、is_sync=1。ExportPendOutboundOrderLogic,不复制 SQL、Excel 表头或 OSS 上传逻辑。url 标准化为 MCP 返回字段 file_url。为了保证与后台页面权限一致,MCP 工具必须复用后台“新增排舱/导出未排舱订单”对应菜单权限,并继续经过 动态工具白名单校验。不得仅依赖工具注册表绕过后台菜单权限。
筛选项工具必须先通过动态工具白名单和后台“新增排舱/导出未排舱订单”菜单权限,再查询选项。所有查询只
使用 MCP token 恢复出的服务端会话,禁止接收 company_id、admin_id、is_super、account_type、
country_auth、platform_company_id、platform_customer_id 等外部身份或权限参数。
各类筛选项必须复用 add 页面的数据来源和权限口径:
filter_type |
add 页面数据来源与权限要求 | 返回 value |
|---|---|---|
product_type |
OutboundTypeModel::getAllOutboundType(),按当前公司和模型现有条件返回可用排舱分类 |
分类 ID |
product |
ProductModel::getProductList(),保留当前公司或平台客户产品配置限制,以及页面对产品状态的展示条件;传 product_type_id 时只能在已授权产品内继续过滤 |
产品 ID |
warehouse |
OrderModel::getSortWarehouse(),保留当前公司、账号和仓库权限排序/过滤规则 |
仓库 ID |
country |
getTcAddCountryCode() 可用国家范围;非超级管理员且账号类型包含 3 时,继续按当前员工 country_auth 取交集;无授权返回空数组 |
国家代码 |
importer |
fms_importer.company_id=session('company_id') 且 status=1,并保留页面的“由EAC提供”选项 |
进口商 ID,或 -1 |
packing_type |
dictionary('fms_packing_type') 当前有效字典值 |
页面提交的货物类型名称 |
order_status |
OrderModel::getOperateOrderStatus() 中 add 页面实际展示的 0/10/20/30/40 |
整数状态值 |
goods_attribute |
GoodsModel::getGoodsAttr() 及页面附加的“无属性” |
对应属性字段名,如 is_battery 或 no_property |
is_remove |
页面固定选项“是/否” | 整数 1/0 |
不得为了分页或关键字搜索改成绕过上述业务方法的无权限全表查询。关键字过滤必须在授权结果集内执行;先按 关键字查全表再补权限过滤也不允许。对于静态字典项,仍需先通过工具和菜单权限后才返回。
筛选项查询只负责减少错误输入,不授予数据权限。导出接口收到筛选值后,仍由
OutboundModel::getPendOutboundOrder() 和现有导出链路再次按当前员工上下文限制实际订单数据。
成功响应示例:
{
"code": "MCP_0000",
"msg": "导出成功",
"data": {
"file_url": "https://example.com/fms_export/order-20260714.xlsx"
},
"meta": {
"request_id": "rq_xxx"
}
}
以下情况返回业务错误:
业务错误继续由现有 MCP 协议适配器转换为 isError=true,保留 code、msg 和 request_id,不产生
JSON-RPC 协议错误,不中断会话。
product_id、status 保持数组。Y 字段,不暴露 property_2。packing_type 保持英文逗号字符串。is_remove=0 不会被当作空值删除。filter_type、产品分类联动、分页结构和名称解析引导。add.html 实际提交结构一致。file_url,无数据和导出失败返回明确错误。country_auth 允许的目的国,无国家授权时返回空列表。product_type_id 只能缩小已授权产品范围,不能通过分类联动扩大权限。outbound/add.html 或其现有导出行为。OutboundModel::getPendOutboundOrder() 的查询口径。