Files
mcp-auth/mcp-for-crm/MCP工具说明文档.md
T
2026-08-10 20:57:49 +08:00

20 KiB
Raw Blame History

MCP for CRM — 工具说明文档

服务对象:汽车零部件(小型阀体外壳)智能报价智能体 服务定位:CRM 侧客户/询价/报价/商机数据服务(业务写入 + 只读回读 + 受限清理) 版本:v1.1(2026-08-09)


1 服务概览

项 值
服务名 mcp-for-crm-auto
框架 MCPServer(mcp 2.0.0 内置高级框架),@app.tool() 装饰器注册
传输协议 Streamable HTTP(JSON-RPC 2.0)
远程端点 https://crm-data.dongsk.top/mcp
本地端点 http://0.0.0.0:8002/mcp(cd src && python3 server.py)
数据库 PostgreSQL 15+,库 smart_quotation_auto(仅服务层内部经 db.py 连接池访问)
工具数 10 个 = 6 个业务工具 + 4 个验证/管理工具

工具一览

# 工具 功能 类型 报价环节
1 get_customer_info 查询客户信用/折扣/账期 只读 Step 2 客户查询
2 create_inquiry 创建询价单 写入 Step 7 存档
3 save_quotation 保存报价单(自动版本+1) 写入(事务) Step 7 存档
4 get_quotation_history 历史报价/版本链查询 只读 Step 7 前置检查
5 update_opportunity 创建/更新商机 写入 Step 7 存档
6 get_inquiry_info 询价单整行回读 只读 存档后验证
7 get_opportunity_info 商机回读 只读 存档后验证
8 get_record_counts 三表行数统计 只读 数据卫生检查
9 purge_test_records 受限测试数据清理 写入(带防护) 回归测试清理
10 save_quotation_mock 报价写入 CRM(Mock 模拟) 写入(独立 mock 表) 模拟报价写入 CRM

单号与状态约定

实体 单号规则 状态机
询价单 INQ-2026-NNNN(自增) pending → quoted(首次报价自动推进)
报价单 QUO-2026-NNNN(自增) draft → superseded(被新版替代);won / lost 为终态,受保护
商机 OPP-2026-NNNN(自增) lead → quoted → won / lost

2 调用约定

2.1 客户端注册(mcpServers)

{
  "mcpServers": {
    "crm": { "url": "https://crm-data.dongsk.top/mcp" }
  }
}

2.2 兜底命令行客户端(纯标准库)

python3 scripts/mcp_http_client.py crm <工具名> '<JSON参数>'
# 示例
python3 scripts/mcp_http_client.py crm get_customer_info '{"customer_code":"OEM-2024-003"}'

2.3 返回通用约定

  • 所有工具返回 JSON 字符串(ensure_ascii=False,中文不转义)。
  • 查询类:{"total": N, "<集合名>": [...]};写入/操作类:{"success": true|false, ...}。
  • 失败统一形态:{"success": false, "message": "<原因>"}。
  • 金额字段(decimal 列)在 JSON 中为字符串,如 "180000.00";日期 YYYY-MM-DD。
  • 日期入参格式必须为 YYYY-MM-DD,否则返回格式错误。

3 业务工具详解(6 个)

3.1 get_customer_info — 查询客户信息

功能:按客户编码精确查询,或按名称、OEM 层级模糊搜索。返回信用等级、折扣率、账期、历史订单统计,用于报价前的客户校验与商务条款确定。

入参(全部可选;全部不传 = 返回全表):

参数 类型 必填 默认 说明
customer_code string 否 — 客户编码,精确匹配,如 OEM-2024-003
name string 否 — 客户名称,%模糊% 匹配
oem_tier string 否 — 层级精确匹配:OEM / Tier1 / Tier2

返回字段:

字段 类型 说明
total int 命中条数
customers[].customer_code string 客户编码
customers[].name string 客户名称
customers[].oem_tier string OEM / Tier1 / Tier2
customers[].credit_level string 信用等级 A/B/C/D 或「无评级」
customers[].discount_rate decimal 折扣率(字符串,如 "0.040" = 4%)
customers[].payment_days int 账期天数(月结 N 天)
customers[].contact_person / phone / email string 联系人信息
customers[].industry / region string 行业 / 区域
customers[].total_orders int 历史订单数
customers[].total_amount decimal 历史订单总额
customers[].notes string 备注

返回示例:

{
  "total": 1,
  "customers": [
    {
      "customer_code": "OEM-2024-003",
      "name": "某新能源主机厂",
      "oem_tier": "OEM",
      "credit_level": "A",
      "discount_rate": "0.040",
      "payment_days": 60,
      "contact_person": "刘工",
      "phone": "0551-2222-0005",
      "email": "liu@oem-nev.example.com",
      "industry": "汽车",
      "region": "合肥",
      "total_orders": 22,
      "total_amount": "9800000.00",
      "notes": "新能源三电系统配套,增长快",
      "created_at": "2026-08-07 17:31:56.244396"
    }
  ]
}

3.2 create_inquiry — 创建询价记录

功能:客户提交询价后建档。校验客户存在性,自动生成 INQ-2026-NNNN 单号,初始状态 pending。

入参:

参数 类型 必填 默认 说明
customer_code string 是 — 客户编码(不存在则失败)
drawing_number string 否 null 图纸号
part_number string 否 null 零件号
annual_volume int 否 null 年用量(件/年)
target_price float 否 null 客户目标价 ¥
notes string 否 null 备注

返回字段:

字段 类型 说明
success bool 成功标记
inquiry_id string 生成的询价单号
customer_name string 客户名称
status string 固定 pending
message string 提示信息

失败返回:{"success": false, "message": "未找到客户 XXX"}

返回示例:

{
  "success": true,
  "inquiry_id": "INQ-2026-0028",
  "customer_name": "某新能源主机厂",
  "status": "pending",
  "message": "询价记录 INQ-2026-0028 已创建"
}

业务规则:同一询价单可多次创建(每次生成新单号);「同一询价单多次报价」通过 3.3 save_quotation 的版本机制实现,不重复建档。


3.3 save_quotation — 保存报价单(多版本核心)

功能:报价存档核心工具。同一询价单不限报价次数,版本号自动 MAX+1;旧版非终态自动置 superseded;首报自动推询价单 pending → quoted;won 终态保护(仍存档但带 warning)。事务内完成:作废旧版 → 推询价状态 → 写报价主表 → 写成本明细表。

入参:

参数 类型 必填 默认 说明
inquiry_id string 是 — 询价单号(不存在则失败并提示先建档)
customer_code string 是 — 客户编码(不存在则失败)
mold_cost float 是 — 模具费 ¥(一次性)
unit_price float 是 — 单价 ¥
annual_volume int 是 — 年用量
material_cost float 是 — 材料成本 ¥/件
casting_cost float 是 — 压铸成本 ¥/件
machining_cost float 是 — 机加工成本 ¥/件
post_process_cost float 是 — 后处理成本 ¥/件
overhead_rate float 否 0.12 管理费率
profit_rate float 否 0.15 利润率
tax_rate float 否 0.13 税率
payment_terms string 否 月结30天 付款条款
delivery_terms string 否 含税含运 交付条款
valid_days int 否 30 报价有效天数(自当日起)
remarks string 否 null 备注

返回字段:

字段 类型 说明
success bool 成功标记
quotation_id string 生成的报价单号
status string 固定 draft(草稿,待人工审核后发出)
version int 本次版本号(自动递增)
previous_quotation_id string|null 上一版报价单号(首报为 null)
price_change_pct float|null 较上版价差百分比(首报为 null)
summary.mold_cost / unit_price / annual_volume float/int 回显
summary.total_annual float 年总额 = 单价×年用量
summary.tax_rate string 税率百分比字符串,如 "13%"
summary.tax_amount float 税额
summary.total_amount float 含税总额
summary.currency string 固定 CNY
valid_until string 有效期至 YYYY-MM-DD
warning string(可选) 存在中标旧版时的提示
message string 提示信息

返回示例(第 2 版议价):

{
  "success": true,
  "quotation_id": "QUO-2026-0029",
  "status": "draft",
  "version": 2,
  "previous_quotation_id": "QUO-2026-0028",
  "price_change_pct": -3.0,
  "summary": {
    "mold_cost": 180000,
    "unit_price": 42.7,
    "annual_volume": 80000,
    "total_annual": 3416000.0,
    "tax_rate": "13%",
    "tax_amount": 444080.0,
    "total_amount": 3860080.0,
    "currency": "CNY"
  },
  "valid_until": "2026-09-08",
  "message": "报价单 QUO-2026-0029(第 2 版)已保存为草稿,待人工审核后发出"
}

业务规则:

  • 版本链查询用 3.4;won/lost 终态永不被 superseded 覆盖。
  • 并发安全由数据库 (inquiry_id, version) 唯一约束兜底。
  • 草稿态报价单在 HTML 上带「草稿·待人工审核」水印,人工审核后才可发出。

3.4 get_quotation_history — 查询历史报价

功能:历史报价与版本链查询,用于再报价前置检查(有没有报过、上一版多少钱)与价格一致性校验。同一询价单按版本号降序返回,并逐行标记 is_latest。

入参(全部可选):

参数 类型 必填 默认 说明
customer_code string 否 — 按客户筛选
inquiry_id string 否 — 按询价单筛选
start_date string 否 — 报价日期起,YYYY-MM-DD
end_date string 否 — 报价日期止,YYYY-MM-DD
status string 否 — 状态筛选:draft/superseded/won/lost
latest_only bool 否 false true 时每个询价单仅返回最新一版

返回字段:

字段 类型 说明
total int 命中条数
quotations[] array 报价行(quotation 全字段 + customer_name)
quotations[].version int 版本号
quotations[].status string 状态
quotations[].is_latest bool 是否为该询价单最新版本(全表口径,不受筛选影响)
quotations[].cost_detail object 成本明细(四项成本 + 费率 + total_cost + unit_price)

返回示例(INQ-2026-0019 三版议价链,latest_only=true):

{
  "total": 1,
  "quotations": [
    {
      "quotation_id": "QUO-2026-0018",
      "inquiry_id": "INQ-2026-0019",
      "customer_code": "OEM-2024-002",
      "quotation_date": "2026-08-07",
      "valid_until": "2026-09-06",
      "version": 3,
      "status": "draft",
      "mold_cost": "180000.00",
      "unit_price": "41.50",
      "annual_volume": 80000,
      "customer_name": "某商用车主机厂",
      "is_latest": true,
      "cost_detail": { "...": "四项成本与费率" }
    }
  ]
}

注意:日期参数格式错误(非 YYYY-MM-DD)会抛出解析异常,调用方应保证格式。


3.5 update_opportunity — 创建/更新商机

功能:双模式。传 opportunity_id = 更新已有商机的阶段/金额/概率等字段(仅更新非 null 字段);不传 opportunity_id = 按 customer_code + title 新建商机(默认 stage=lead、probability=20、expected_amount=0,source=智能报价自动生成)。

入参:

参数 类型 必填 默认 说明
opportunity_id string 否 — 商机号(传入则走更新模式)
customer_code string 新建时必填 — 客户编码
title string 新建时必填 — 商机标题
stage string 否 新建时 lead 阶段:lead/quoted/won/lost
expected_amount float 否 新建时 0 预期金额 ¥
probability int 否 新建时 20 成交概率 %
oem_program string 否 — OEM 项目/平台
expected_close_date string 否 — 预期关单日期 YYYY-MM-DD
notes string 否 — 备注(保留参数)

返回字段:

字段 类型 说明
success bool 成功标记
opportunity_id string 商机号(更新时为传入值,新建时为生成值)
message string 「已更新」或「已创建」

失败返回:

  • {"success": false, "message": "expected_close_date 格式错误:...,应为 YYYY-MM-DD"}
  • {"success": false, "message": "未找到商机 OPP-2026-XXXX"}
  • {"success": false, "message": "新建商机需要提供 customer_code 和 title"}
  • {"success": false, "message": "未找到客户 XXX"}

返回示例(新建):

{
  "success": true,
  "opportunity_id": "OPP-2026-0019",
  "message": "商机 OPP-2026-0019 已创建"
}

3.6 save_quotation_mock — 报价写入 CRM(Mock 模拟)

用途:模拟「报价写入 CRM」动作。写入独立 mock 表 quotation_mock,不校验客户/询价单/商机,与其他工具无任何关联,适合演示与联调场景单独调用。

入参:

参数 类型 必填 默认值 说明
part_name string ✅ — 零件名称
unit_price number ✅ — 报价单价
customer_name string — null 客户名称(自由文本,不做存在性校验)
part_number string — null 零件号
material_grade string — null 材质牌号
mold_cost number — 0.0 模具费
annual_volume integer — null 年用量(提供时自动计算 total_annual = unit_price × annual_volume)
currency string — CNY 币种
remarks string — null 备注

返回示例:

{
  "success": true,
  "quotation_id": "QUO-MOCK-0001",
  "status": "draft",
  "summary": {
    "part_name": "变速箱阀体外壳", "unit_price": 41.66, "mold_cost": 180000.0,
    "annual_volume": 300000, "total_annual": 12498000.0, "currency": "CNY"
  },
  "message": "报价单 QUO-MOCK-0001 已写入 CRM mock 表(quotation_mock)"
}

关键说明:

  • 单号 QUO-MOCK-#### 自增,独立于正式 QUO-2026-#### 序列。
  • quotation_mock 表无外键,写入不影响正式三表(inquiry/quotation/opportunity),get_record_counts 也不统计该表。
  • 无版本管理、无状态流转:每次调用新增一行,状态固定 draft。

4 验证/管理工具详解(4 个)

用途:MCP 读写分离交叉验证——写工具的返回值与只读回读工具交叉核对;测试数据清理经受限工具完成。 原则:验证/清理环节禁止直连数据库;db.py 仅为服务层内部连接池。

4.1 get_inquiry_info — 询价单回读(只读)

功能:按询价单号回读询价单整行,用于存档后验证(状态、图号、零件号、年用量、目标价、创建时间)。

入参:

参数 类型 必填 说明
inquiry_id string 是 询价单号

返回:命中 {"success": true, "inquiry": {<整行字段>}};未命中 {"success": false, "message": "未找到询价单 XXX"}。

示例:

{
  "success": true,
  "inquiry": {
    "inquiry_id": "INQ-2026-0025",
    "customer_code": "T1-2025-002",
    "inquiry_date": "2026-08-08",
    "drawing_number": "DWG-VHB-MN-Rev1",
    "part_number": "P-VHB-009",
    "annual_volume": 5000,
    "target_price": "30.00",
    "status": "quoted",
    "notes": "TC-05生产报价:微型泵阀体壳 ADC12 96.3cc 160T一模两腔...",
    "created_at": "2026-08-08 13:34:11.945841"
  }
}

4.2 get_opportunity_info — 商机回读(只读)

功能:按商机号或客户编码回读商机,用于存档后验证(stage/probability/expected_amount/更新时间)。两参数二选一,opportunity_id 优先。

入参:

参数 类型 必填 说明
opportunity_id string 二选一 商机号(精确单条)
customer_code string 二选一 客户编码(该客户全部商机,按创建时间倒序)

返回:{"total": N, "opportunities": [<整行字段>]};两参数都未提供时 {"success": false, "message": "需提供 opportunity_id 或 customer_code"}。

示例:

{
  "total": 1,
  "opportunities": [
    {
      "opportunity_id": "OPP-2026-0018",
      "customer_code": "T1-2025-002",
      "title": "微型泵阀体壳 ADC12(P-VHB-009)首单",
      "stage": "quoted",
      "expected_amount": "40300.00",
      "probability": 50,
      "oem_program": "大陆制动系统配套",
      "expected_close_date": "2026-09-30",
      "source": "智能报价自动生成",
      "created_by": "AI智能报价",
      "updated_at": "2026-08-08"
    }
  ]
}

4.3 get_record_counts — 三表行数统计(只读)

功能:返回 inquiry/quotation/opportunity 三表行数,用于数据卫生检查(如回归前后行数一致性核对)。

入参:无。

返回示例:

{
  "success": true,
  "counts": { "inquiry": 24, "quotation": 27, "opportunity": 18 }
}

4.4 purge_test_records — 受限测试数据清理(管理)

功能:清理 TC-03 回归测试写入的数据。带硬性防护:仅当报价单 remarks、询价单 notes 含「TC-03回归测试」,或商机 title 以「TC-03」开头时才允许删除;其余一律进入 rejected 列表,防止误删演示/生产数据。级联删除子表(quotation_cost_detail / inquiry_item)。

入参(至少传一组;均为 ID 数组):

参数 类型 必填 说明
quotation_ids array[string] 否 待清理报价单号列表
inquiry_ids array[string] 否 待清理询价单号列表
opportunity_ids array[string] 否 待清理商机号列表

返回字段:

字段 类型 说明
success bool 固定 true(单条拒绝不影响整体)
deleted.quotations / deleted.inquiries / deleted.opportunities int 实际删除条数
deleted.rejected array[string] 被防护拒绝的 ID 列表(非测试标记或不存在)

示例一:正常清理(回归测试自动调用)

{
  "success": true,
  "deleted": { "quotations": 3, "inquiries": 3, "opportunities": 1, "rejected": [] }
}

示例二:防护生效(对生产数据调用)

{
  "success": true,
  "deleted": {
    "quotations": 0, "inquiries": 0, "opportunities": 0,
    "rejected": ["QUO-2026-0027", "INQ-2026-0025", "OPP-2026-0018"]
  }
}

5 附录

5.1 依赖数据表

表 用途
customer 客户主数据(信用/折扣/账期/历史统计)
inquiry 询价单(pending→quoted)
quotation 报价单主表(版本链/状态机/金额)
quotation_cost_detail 报价成本明细(四项成本+费率)
opportunity 商机(阶段/金额/概率/关单日期)

5.2 标准存档链路(智能体 Step 7)

get_quotation_history(inquiry_id)          ← 前置:查有无历史版本
  ├─ 无 → create_inquiry(...)              ← 建询价单
  └─ 有 → 复用原 inquiry_id
save_quotation(...)                        ← 存报价(版本自动+1,事务)
update_opportunity(...)                    ← 商机同步最新版年总额(stage=quoted)
get_inquiry_info / get_opportunity_info    ← 可选:存档后交叉验证

5.3 与 ERP 服务的协作

核价计算(材质对照/压铸参数/机加工工时/汇总核价)由 mcp-for-erp 承担,见《MCP for ERP — 工具说明文档》;CRM 服务不做核价计算,只做客户与商务数据管理。