# 需求与功能清单 ## 产品边界 - Gateway 只处理 MCP 协议、会话转发、候选工具注册和展示适配,不直连业务数据库,不复制 ThinkPHP 业务规则。 - 所有员工、公司、菜单、工具和数据权限由 ThinkPHP 最终判断;Gateway 不接受调用方提供的身份或权限覆盖参数。 - 本地 stdio 与公网 HTTP 必须注册同一组候选工具,并共享同一套协议与展示合同。 - 写入、审批、费用修改、订单状态流转或批量业务变更工具不得在未完成独立安全评审时开放。 ## 协议合同 - 支持 MCP `initialize`、`tools/list` 和 `tools/call`;能力声明保持 `tools.listChanged=false`。 - `tools/list` 返回本地 11 个候选工具与 fmsoperate 动态启用列表的交集。 - `tools/call` 在调用前再次校验工具已注册、设备会话有效且后端仍允许当前员工使用该工具。 - 动态列表缺失、格式错误或查询失败时关闭访问,不允许回退为本地全量工具。 - 后端业务失败仍放在 JSON-RPC `result` 中并设置 `isError=true`,不得中断 stdio 或 HTTP 会话;协议、参数或未知方法错误使用 JSON-RPC `error`。 - CLI `call` 保留工具原始 `code/msg/data/meta` 信封,不经过面向 Workbuddy 的 Presenter。 ## 候选工具 | 类别 | 工具 | 核心要求 | |---|---|---| | 查询 | `query_order` | 保持旧展示协议兼容 | | 查询 | `query_order_exact`、`query_track` | 只在结果意图和号码类型明确后调用 | | 查询 | `query_customs_declaration_files` | 订单号数组与排舱单号数组必须二选一 | | 查询 | `query_outbound_list` | 排舱阶段必选;运输方式未指定时查询全部 | | 查询 | `query_outbound_detail` | 只按明确排舱单号查询,不接受内部排舱 ID | | 筛选 | `list_outbound_filter_options` | 统一返回排舱阶段、运输方式、集货仓库、是否直送柜、拖车、报关和清关七类选项 | | 筛选 | `list_order_filter_options` | 返回当前员工可用的精准订单筛选值 | | 筛选 | `list_pending_outbound_export_filter_options` | 返回当前员工可用的未排舱导出筛选值 | | 导出 | `export_pending_outbound_orders` | 复用筛选工具返回值,不猜测内部 ID | | 导出 | `export_out_of_province_port_data` | 排舱单号、柜号、提单号、SO 号四类数组严格四选一,并要求文件类型 | ## 零推断与工具选择 - AI 必须先确认用户要看的结果类别,再确认所给号码的业务类型;任一项不明确时先提问。 - 禁止按号码外观猜测类型,禁止并行调用多个候选工具,禁止跨字段试查,禁止一次失败后自行换号码字段或换工具重试。 - 多个筛选值命中时必须让用户选择;唯一命中才可把内部 `value` 传给目标工具。 - 面向用户描述筛选条件时使用中文标签,不展示英文筛选字段、内部数字代码或技术参数文案。 - 中文筛选展示约束不影响查询结果中的件数、重量、体积、日期和其他正常业务值。 ## 输出与错误安全 - `query_order` 是唯一旧展示例外,继续使用 `columns + records` 和原文本行为。 - 其余 10 个工具由 `OutputPresenter` 白名单处理:4 个表格工具、1 个排舱详情工具、3 个筛选项工具和 2 个导出工具。 - 表格使用中文 `headers + rows + pagination`;排舱详情使用 `summary + details + pagination`;导出只返回 `files[].label + files[].url`。 - 筛选项保留可继续传参的 `value`、用户显示 `label` 和业务 `code`,但不得泄露未列入白名单的后端字段。 - `request_id` 放在 MCP 结果 `_meta`;安全工具的业务错误使用固定中文消息,不透传后端 `msg`、异常数据、堆栈或原始响应。 - Gateway 已知错误码与重试策略以 `OutputPresenter.ERROR_MESSAGES`、`NON_RETRYABLE_CODES` 为代码源;未知业务码对外归一为 `MCP_9001`。 - stdio 与 public 共用同一个 Presenter;未知工具、畸形响应、未知字段和未知异常关闭失败。 ## 公网安全与运行合同 - 公网请求使用 `GWS_xxx` 查找 Redis Gateway session,并从服务端会话取得 `mcp_token`;不得把 token 返回给客户端。 - 公网入口生成可信 `rq_http_*` 追踪号;调用方 `X-Request-Id` 只允许记录短哈希,不得作为可信追踪号。 - 日志不得记录明文 Gateway 凭据、MCP token、Cookie、Authorization、授权码或后端原始响应。 - `initialize` 与 `tools/list` 不限流;`tools/call` 按已认证的 `gateway_session_id + tool_name` 使用独立滑动窗口配额。 - 公网必须位于 HTTPS 反向代理后,Redis 只允许内网访问并启用生产密码。 ## 变更与验收 - 工具变更必须同步更新工具 metadata、stdio/public 双注册表、CLI 转发、Presenter、ThinkPHP 路由/验证/Logic/Model、动态注册数据和相关测试。 - 因 `tools.listChanged=false`,工具或 Schema 变化后必须重启 Gateway 并让客户端重新连接。 - 用户已确认 fmsoperate 的 10 个 MCP SQL 与 base 的 5 个 MCP SQL 均已执行;动态启用值仍以运行环境为准。 - Python 生产代码变更必须运行全量 unittest 和 `.coveragerc` 要求的语句、分支 100% 严格覆盖率;跨仓 PHP 变更必须运行对应合同测试与语法检查。