# MCP for ERP — 工具说明文档 > 服务对象:汽车零部件(小型阀体外壳)智能报价智能体 > 服务定位:ERP 侧核价基础数据与成本计算引擎(只读 + 计算,不写库) > 版本:v1.1(2026-08-09) --- ## 1 服务概览 | 项 | 值 | |----|----| | 服务名 | `mcp-for-erp-auto` | | 框架 | MCPServer(mcp 2.0.0 内置高级框架),`@app.tool()` 装饰器注册 | | 传输协议 | Streamable HTTP(JSON-RPC 2.0) | | 远程端点 | `https://erp-data.dongsk.top/mcp` | | 本地端点 | `http://0.0.0.0:8001/mcp`(`cd src && python3 server.py`) | | 数据库 | PostgreSQL 15+,库 `smart_quotation_auto`(仅服务层内部经 `db.py` 连接池访问) | | 工具数 | **5 个**(全部只读/计算) | ### 工具一览 | # | 工具 | 功能 | 报价环节 | |---|------|------|----------| | 1 | `query_material_master` | 查询物料主数据(体积/密度/吨位/后处理) | 基础数据 | | 2 | `match_material_grade` | 客户牌号 → 内部等效牌号对照 | 材质确认 | | 3 | `get_die_casting_params` | 压铸参数:铝水重量、节拍、铸造成本 | 压铸成本 | | 4 | `get_machining_estimate` | 机加工工时估算(固化工装节拍) | 机加工成本 | | 5 | `calculate_part_cost` | 汇总核价,输出最终单价 | 最终报价 | --- ## 2 调用约定 ### 2.1 客户端注册(mcpServers) ```json { "mcpServers": { "erp": { "url": "https://erp-data.dongsk.top/mcp" } } } ``` ### 2.2 JSON-RPC 调用流程 1. `initialize`(握手,获取 `Mcp-Session-Id`) 2. `notifications/initialized`(通知,无响应体) 3. `tools/list`(可选,列出工具) 4. `tools/call`(调用工具,`params: {name, arguments}`) ### 2.3 兜底命令行客户端(纯标准库) ```bash python3 scripts/mcp_http_client.py erp <工具名> '' # 示例 python3 scripts/mcp_http_client.py erp calculate_part_cost '{"material_code":"VHB-AT-001","annual_qty":300000}' ``` ### 2.4 返回通用约定 - 所有工具返回 **JSON 字符串**(`ensure_ascii=False`,中文不转义)。 - 查询类工具返回 `{"total": N, "<集合名>": [...]}`;操作/计算类工具返回 `{"success": true|false, ...}`。 - 失败统一形态:`{"success": false, "message": "<原因>"}`(查询类失败以 `total: 0` 空集表达)。 - 金额/重量:浮点数,成本保留 2 位小数,重量保留 3 位小数;日期 `YYYY-MM-DD`,月份 `YYYY-MM`。 --- ## 3 工具详解 ### 3.1 query_material_master — 查询物料主数据 **功能**:按物料编码精确查询,或按零件类别、材质牌号、压铸吨位组合过滤。返回物料档案(含体积、密度、净重、吨位、表面处理),是核价的起点数据。 **入参**(全部可选;全部不传 = 返回全表): | 参数 | 类型 | 必填 | 默认 | 说明 | |------|------|------|------|------| | `material_code` | string | 否 | — | 物料编码,精确匹配,如 `VHB-AT-001` | | `part_category` | string | 否 | — | 零件类别,精确匹配,如 `阀体外壳` | | `material_grade` | string | 否 | — | 客户材质牌号,精确匹配,如 `ADC12` | | `die_casting_ton` | int | 否 | — | 压铸机吨位,精确匹配,如 `400` | **返回字段**: | 字段 | 类型 | 说明 | |------|------|------| | `total` | int | 命中条数 | | `materials[]` | array | 物料行列表 | | `materials[].material_code` | string | 物料编码(内部主键) | | `materials[].part_name` | string | 零件名称 | | `materials[].part_category` | string | 零件类别 | | `materials[].material_grade` | string | 客户材质牌号 | | `materials[].density` | decimal | 密度 g/cm³(JSON 中为字符串) | | `materials[].volume_cc` | decimal | 零件体积 cm³(算铝水重量的依据) | | `materials[].net_weight_kg` | decimal | 净重 kg(算后处理成本的依据) | | `materials[].die_casting_ton` | int | 压铸机吨位 | | `materials[].surface_treatment` | string | 表面处理(阳极氧化/钝化/无等) | | `materials[].unit` | string | 计量单位 | | `materials[].created_at` | string | 建档时间 | **返回示例**: ```json { "total": 1, "materials": [ { "material_code": "VHB-AT-001", "part_name": "变速箱阀体外壳", "part_category": "阀体外壳", "material_grade": "ADC12", "density": "2.700", "volume_cc": "444.44", "net_weight_kg": "1.200", "die_casting_ton": 400, "surface_treatment": "阳极氧化", "unit": "件", "created_at": "2026-08-07 12:18:51.484993" } ] } ``` --- ### 3.2 match_material_grade — 材质牌号对照 **功能**:把客户指定牌号(GB/ASTM/JIS/EN/ISO 任一体系或内部码)对照为企业内部等效牌号,返回密度与铝锭参考价。支持模糊匹配与热处理后缀自动剥离(如 `A356-T6` → `A356`,最多剥 2 段)。 **入参**: | 参数 | 类型 | 必填 | 默认 | 说明 | |------|------|------|------|------| | `customer_grade` | string | **是** | — | 客户牌号,大小写不敏感,模糊匹配六大码系 | | `standard` | string | 否 | — | 标准体系提示(当前实现未参与过滤,保留参数) | **返回字段**(命中时): | 字段 | 类型 | 说明 | |------|------|------| | `matched` | bool | 是否命中 | | `customer_grade` | string | 原客户牌号 | | `internal_code` | string | 内部等效牌号,如 `AL-ADC12` | | `density` | float | 密度 g/cm³ | | `price_per_kg` | float | 铝锭参考价 ¥/kg(兜底价,核价优先取月度价) | | `all_mappings[]` | array | 全部命中行(含 gb/astm/jis/en/iso/internal 六码、grade_group 材质族) | **未命中返回**: ```json { "matched": false, "message": "未找到材质 AD12" } ``` **返回示例**(`ADC12`): ```json { "matched": true, "customer_grade": "ADC12", "internal_code": "AL-ADC12", "density": 2.7, "price_per_kg": 18.5, "all_mappings": [ { "grade_group": "铝合金", "gb_code": "ZAlSi10Cu(ADC12)", "astm_code": "A380", "jis_code": "ADC12", "en_code": "EN AC-4600", "iso_code": "AlSi9Cu3", "internal_code": "AL-ADC12", "density": "2.700", "price_per_kg": "18.50" } ] } ``` **业务规则**:未命中时 Skill 层应回退默认铝价并产生 warning(TC-06 场景),不应中断报价。 --- ### 3.3 get_die_casting_params — 获取压铸参数 **功能**:按物料编码取压铸参数。核心输出:铝水重量(体积×密度×1.05 损耗)、压铸机吨位、模次节拍、单件压铸成本。体现 MVP 原则「**靠体积算铝水重量、压铸机吨位固定工时**」。 **入参**: | 参数 | 类型 | 必填 | 默认 | 说明 | |------|------|------|------|------| | `material_code` | string | **是** | — | 物料编码 | | `volume_cc` | float | 否 | 物料档案体积 | 覆盖体积(图纸实测体积优先于档案默认值) | **返回字段**: | 字段 | 类型 | 说明 | |------|------|------| | `success` | bool | 成功标记 | | `material_code` | string | 物料编码 | | `volume_cc` | float | 采用体积 cm³ | | `density` | float | 密度 g/cm³ | | `aluminum_weight_kg` | float | 铝水重量 = 体积×密度/1000×1.05,3 位小数 | | `die_casting_ton` | int | 压铸机吨位 | | `cycle_time_sec` | float | 模次节拍(秒/模,按吨位固化) | | `machine_rate` | float | 机台费率 ¥/小时 | | `mold_cavities` | int | 模穴数 | | `casting_cost_per_part` | float | 单件压铸成本 = (节拍/3600)×费率/模穴数,2 位小数 | **失败返回**:`{"success": false, "message": "未找到物料 XXX"}` 或 `{"success": false, "message": "未找到 400T 压铸机参数"}` **返回示例**(VHB-AT-001,444.44cc,400T): ```json { "success": true, "material_code": "VHB-AT-001", "volume_cc": 444.44, "density": 2.7, "aluminum_weight_kg": 1.26, "die_casting_ton": 400, "cycle_time_sec": 30.0, "machine_rate": 260.0, "mold_cavities": 1, "casting_cost_per_part": 2.17 } ``` --- ### 3.4 get_machining_estimate — 机加工工时估算 **功能**:按孔清单(钻孔/攻丝/铰孔)与铣面数量估算机加工总工时与刀具成本。所有规格节拍来自固化表 `machining_cycle`(工装节拍),逐项累加。 **入参**: | 参数 | 类型 | 必填 | 默认 | 说明 | |------|------|------|------|------| | `material_code` | string | **是** | — | 物料编码(回显用) | | `drill_holes` | array[object] | 否 | [] | 钻孔清单,元素 `{"spec": "Φ6", "count": 2}` | | `tap_holes` | array[object] | 否 | [] | 攻丝清单,元素 `{"spec": "M6×1.0", "count": 2}` | | `ream_holes` | array[object] | 否 | [] | 铰孔清单,元素 `{"spec": "Φ8H7", "count": 1}` | | `mill_faces` | int | 否 | 0 | 铣面数量 | 孔元素字段:`spec`(规格字符串,缺省 Φ8 / M8×1.25 / Φ8H7)、`count`(数量,缺省 1)。 **返回字段**: | 字段 | 类型 | 说明 | |------|------|------| | `success` | bool | 成功标记 | | `material_code` | string | 物料编码 | | `total_time_sec` | float | 总工时(秒),2 位小数 | | `total_time_hours` | float | 总工时(小时),4 位小数 | | `total_tool_cost` | float | 刀具成本合计 ¥ | | `details[]` | array | 逐项明细:`operation`(drill/tap/ream/mill)、`spec`、`count`、`total_time_sec` | **返回示例**(钻 Φ6×2 + 攻 M6×1.0×2 + 铣面×1): ```json { "success": true, "material_code": "VHB-AT-001", "total_time_sec": 26.0, "total_time_hours": 0.0072, "total_tool_cost": 1.5, "details": [ { "operation": "drill", "spec": "Φ6", "count": 2, "total_time_sec": 6.0 }, { "operation": "tap", "spec": "M6×1.0", "count": 2, "total_time_sec": 8.0 }, { "operation": "mill", "spec": "face", "count": 1, "total_time_sec": 12.0 } ] } ``` **注意**:固化表中不存在的规格**静默跳过**(不计工时也不报错);毛坯件(无孔无面)返回总工时 0,Skill 层应产生 warning(TC-07 场景)。 --- ### 3.5 calculate_part_cost — 汇总核价(最终单价) **功能**:一站式核价。材料成本(铝水重量×当月铝价)+ 压铸成本 + 机加工成本 + 后处理成本 → 小计 × (1+管理费率) × (1+利润率) = 最终单价。铝价优先取 `material_price_history` 最新月度价并留痕月份;机加工费率按材质族(铝合金 60 / 灰铁 75 / 球铁 80 ¥/h)取 `machining_rate`。 **入参**: | 参数 | 类型 | 必填 | 默认 | 说明 | |------|------|------|------|------| | `material_code` | string | **是** | — | 物料编码 | | `annual_qty` | int | **是** | — | 年用量(件/年) | | `drill_holes` | array[object] | 否 | [] | 同 3.4 | | `tap_holes` | array[object] | 否 | [] | 同 3.4 | | `ream_holes` | array[object] | 否 | [] | 同 3.4 | | `mill_faces` | int | 否 | 0 | 铣面数量 | | `overhead_rate` | float | 否 | 0.12 | 管理费率 | | `profit_rate` | float | 否 | 0.15 | 利润率 | **返回字段**: | 字段 | 类型 | 说明 | |------|------|------| | `success` | bool | 成功标记 | | `material_code` / `part_name` | string | 物料编码 / 零件名称 | | `cost_breakdown.material_cost` | float | 材料成本 = 铝水重量×铝价 | | `cost_breakdown.aluminum_weight_kg` | float | 铝水重量(含 1.05 损耗) | | `cost_breakdown.aluminum_price_per_kg` | float | 采用铝价 ¥/kg | | `cost_breakdown.price_basis_month` | string | 铝价月份 `YYYY-MM`(留痕;无月度价时为 null) | | `cost_breakdown.internal_code` | string | 内部牌号 | | `cost_breakdown.grade_group` | string | 材质族(决定机加工费率) | | `cost_breakdown.casting_cost` | float | 单件压铸成本 | | `cost_breakdown.die_casting_ton` | int | 压铸机吨位 | | `cost_breakdown.machining_cost` | float | 机加工成本 = 工时×费率 | | `cost_breakdown.machining_hours` | float | 机加工总工时(小时) | | `cost_breakdown.machining_rate_per_hour` | float | 机加工费率 ¥/h | | `cost_breakdown.post_process_cost` | float | 后处理成本 = 净重×工艺费率 | | `cost_breakdown.surface_treatment` | string | 表面处理工艺 | | `total_cost` | float | 四项成本小计 | | `overhead_rate` / `overhead` | float | 管理费率 / 管理费额 | | `profit_rate` | float | 利润率 | | `unit_price` | float | **最终单价** = (total_cost+overhead)×(1+profit_rate) | | `currency` | string | 固定 `CNY` | **返回示例**(VHB-AT-001,30 万件/年,钻 Φ6×2/攻 M6×1.0×2/铰 Φ8H7×1/铣面×1): ```json { "success": true, "material_code": "VHB-AT-001", "part_name": "变速箱阀体外壳", "cost_breakdown": { "material_cost": 23.31, "aluminum_weight_kg": 1.26, "aluminum_price_per_kg": 18.5, "price_basis_month": "2026-08", "internal_code": "AL-ADC12", "grade_group": "铝合金", "casting_cost": 2.17, "die_casting_ton": 400, "machining_cost": 0.53, "machining_hours": 0.0089, "machining_rate_per_hour": 60.0, "post_process_cost": 6.0, "surface_treatment": "阳极氧化" }, "total_cost": 32.01, "overhead_rate": 0.12, "overhead": 3.84, "profit_rate": 0.15, "unit_price": 41.23, "currency": "CNY" } ``` **失败返回**:`{"success": false, "message": "未找到物料 XXX"}` --- ## 4 附录 ### 4.1 核心公式 ``` 铝水重量(kg) = 体积(cm³) × 密度(g/cm³) / 1000 × 1.05(损耗系数) 材料成本 = 铝水重量 × 铝锭单价(当月月度价,缺省 18.5) 压铸成本 = (节拍秒 / 3600) × 机台费率 / 模穴数 ← 吨位固化节拍 机加工成本 = Σ(工序固化节拍×数量) / 3600 × 材质族费率 后处理成本 = 净重(kg) × 表面处理费率 单价 = (四项成本小计 × (1+管理费率)) × (1+利润率) ``` ### 4.2 依赖数据表 | 表 | 用途 | |----|------| | `material_master` | 物料主数据(体积/密度/吨位/后处理) | | `material_grade_mapping` | 五标准体系牌号对照 + 材质族 + 参考铝价 | | `material_price_history` | 月度铝价留痕(核价取最新月) | | `die_casting_params` | 吨位 → 节拍/费率/模穴数 | | `machining_cycle` | 工序规格固化节拍与刀具费率 | | `machining_rate` | 材质族机加工费率(60/75/80 ¥/h) | | `post_process_rate` | 表面处理费率(¥/kg) | ### 4.3 与 CRM 服务的协作 ERP 服务只读不写。报价存档链路(create_inquiry → save_quotation → update_opportunity)由 `mcp-for-crm` 承担,见《MCP for CRM — 工具说明文档》。