关于 ConnectWise CPQ
ConnectWise CPQ 是面向使用 ConnectWise CPQ 处理报价及相关销售记录团队的 MCP 服务,提供读写工具,并为支持 MCP Apps 的客户端提供可选的只读报价卡片。
主要功能
- 01搜索并获取报价及版本
- 02根据模板创建报价
- 03管理报价项目、客户和条款
- 04浏览模板、税码和用户
- 05更新经常性收入记录
- 06显示只读报价卡片
适用场景
- 01查找符合日期范围的报价
- 02通过复制模板创建报价
- 03在支持 MCP Apps 的客户端查看报价总额
- 04在执行破坏性更改前确认删除
MCP 相关
通过 25 个工具向 MCP 客户端提供 ConnectWise CPQ 数据和报价操作能力。兼容 2025 年 initialize 握手客户端与 2026-07-28 信封客户端,并提供只读 MCP Apps 报价卡片。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e CPQ_ACCESS_KEY -e CPQ_PUBLIC_KEY -e CPQ_PRIVATE_KEY -e MCP_TRANSPORT -e AUTH_MODE -e LOG_LEVEL ghcr.io/wyre-technology/connectwise-cpq-mcp:v1.0.4CPQ_ACCESS_KEY密钥ConnectWise CPQ tenant/site access key (from the Sell URL ...home?accesskey=<this>)CPQ_PUBLIC_KEY密钥ConnectWise CPQ public API key (Settings → Organization Settings → API Keys)CPQ_PRIVATE_KEY密钥ConnectWise CPQ private API key (shown once at creation)MCP_TRANSPORTTransport mode. Set to 'stdio' for local CLI use; the image defaults to 'http' for gateway hosting.AUTH_MODE密钥Credential source: 'env' reads vars locally, 'gateway' expects header injection from the WYRE MCP Gateway.LOG_LEVELLog verbosity: debug, info, warn, error本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/wyre-technology/connectwise-cpq-mcp:v1.0.4stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
connectwise-cpq-mcp
适用于 ConnectWise CPQ (Sell) 的 MCP 服务 — 报价、行项目、客户、条款、标签页、模板、税码、经常性收入和用户。
基于 MCP 2026-07-28 规范和拆分式 v2 SDK
(@modelcontextprotocol/server / /node / /client ^2.0.0-beta.5)构建,支持双时代
服务:一个共享的 McpServerFactory 位于 createMcpHandler({ legacy: 'stateless' }) 后,
既可响应采用 2025 时代 initialize 握手的客户端(目前为 WYRE 网关),也可响应现代
2026-07-28 信封客户端 — 所有调用方看到的 25 个工具表面均相同且确定。仅以 GHCR 容器形式
提供(无 MCPB 包)。
工具(25 个,平铺)
读取:cpq_test_connection、cpq_search_quotes、cpq_get_quote、cpq_get_quote_versions、
cpq_search_quote_items、cpq_get_quote_item、cpq_list_quote_customers、
cpq_search_quote_tabs、cpq_list_quote_terms、cpq_list_templates、cpq_list_tax_codes、
cpq_list_recurring_revenues、cpq_list_users。
写入:cpq_create_quote_from_template、cpq_update_quote(⚠ 高影响)、
cpq_create_quote_item、cpq_update_quote_item、cpq_update_quote_customer、
cpq_create_quote_term、cpq_update_quote_term,以及 ⚠ 破坏性 — 不可撤销的
删除操作:cpq_delete_quote_item、cpq_delete_quote_term、cpq_delete_quote_customer、
cpq_delete_quote_version、cpq_delete_quote。
报价创建仅支持复制(/api/quotes/copyById)— CPQ API 不提供从头创建、发布/电子签名、
订单移植、PDF 或产品目录端点(这些功能请配合 connectwise-psa 使用)。
凭据
CPQ 需要 API 用户和 CPQ 2022.2+。共三项,缺一不可:
| 环境变量(env 模式) | 网关请求头(AUTH_MODE=gateway) | 获取位置 |
|---|---|---|
CPQ_ACCESS_KEY | X-CPQ-Access-Key | Sell URL:...home?accesskey=<this> |
CPQ_PUBLIC_KEY | X-CPQ-Public-Key | Settings → Organization Settings → API Keys |
CPQ_PRIVATE_KEY | X-CPQ-Private-Key | 创建密钥时仅显示一次 |
在网关模式下,若请求缺少任何请求头,系统会在 MCP 处理程序运行前返回 401(JSON-RPC 错误 -32001)— 不会回退到环境变量凭据。
本地配置请复制 .env.example。该文件中的 CONDUIT_S2S_SECRET 请留空。
| 变量 | 必需 | 说明 |
|---|---|---|
CPQ_ACCESS_KEY、CPQ_PUBLIC_KEY、CPQ_PRIVATE_KEY | stdio 和 AUTH_MODE=env 模式下必需 | ConnectWise CPQ API 用户密钥。网关 Compose 服务不会设置这些变量。 |
MCP_TRANSPORT | 否 | stdio(默认)或 http |
AUTH_MODE | 否 | gateway(Docker 镜像和 Compose 默认值)或 env。网关模式要求每个 /mcp 请求都携带三个 X-CPQ-* 请求头,且不会回退到 CPQ_*。env 仅在 S2S 身份验证成功后使用这些变量。 |
CONDUIT_S2S_SECRET | HTTP 模式下必需 | 服务间密钥。若该值为空或为已知占位符(changeme、replace-with-a-real-secret 及其他公开示例值),HTTP 服务端会记录错误并以非零状态码退出。未设置此值时 Compose 不会启动。切勿提交真实值。可使用 openssl rand -hex 32 生成。 |
MCP_ALLOW_INSECURE_DEV | 否 | 仅限本地开发时设为 1,以便在未设置 CONDUIT_S2S_SECRET 的情况下启动 HTTP。进程会记录警告,且不强制执行 X-Gateway-S2S。即使 MCP_HTTP_HOST 是 0.0.0.0 这类更宽泛的地址,监听地址也会强制设为 127.0.0.1。仍会拒绝占位符密钥。 |
MCP_HTTP_HOST | 否 | MCP_TRANSPORT=http 时的绑定地址。默认为 127.0.0.1。设置了 CONDUIT_S2S_SECRET 时生效。容器镜像将其设为 0.0.0.0。 |
MCP_HTTP_PORT | 否 | HTTP 端口。默认为 8080。 |
/health 和 /healthz 无需身份验证,也不会读取凭据。stdio 传输不使用 CONDUIT_S2S_SECRET。
HTTP 身份验证
设置 MCP_TRANSPORT=http 和 CONDUIT_S2S_SECRET 后,每个 /mcp 请求都必须包含 X-Gateway-S2S。校验逻辑位于 src/s2s-verify.ts 中的 verifyS2sHeader:标头值为 t=<unix seconds>,v1=<hex>,其中 hex 是以 CONDUIT_S2S_SECRET 为密钥,对字面字符串 t=<unix seconds> 计算的 HMAC-SHA256(64 个小写十六进制字符)。时间戳与服务器时钟的偏差必须在 300 秒以内。若标头缺失或无效,将在读取供应商凭据前返回 401。
TS=$(date +%s)
SIG=$(printf 't=%s' "$TS" | openssl dgst -sha256 -hmac "$CONDUIT_S2S_SECRET" -hex | awk '{print $NF}')
curl -sS http://127.0.0.1:8080/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "X-Gateway-S2S: t=${TS},v1=${SIG}" \
-H 'X-CPQ-Access-Key: your-access-key' \
-H 'X-CPQ-Public-Key: your-public-key' \
-H 'X-CPQ-Private-Key: your-private-key' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
在 AUTH_MODE=gateway 模式下,这三个 X-CPQ-* 标头是该请求唯一的凭据来源。在 AUTH_MODE=env 模式下,如果标头缺失,已签名请求会使用环境变量中的 CPQ_ACCESS_KEY、CPQ_PUBLIC_KEY 和 CPQ_PRIVATE_KEY。
运行
export NODE_AUTH_TOKEN=$(gh auth token) # GitHub Packages auth for @wyre-ai/*
npm install
npm run build
node dist/index.js # stdio (default)
CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" MCP_TRANSPORT=http node dist/index.js
node scripts/smoke-dual-era.mjs # proves both protocol eras serve the same tools
不带密钥的本地 HTTP 仅供开发使用。它会绑定到 127.0.0.1(若 MCP_HTTP_HOST 不是环回地址,则会被覆盖并记录日志),并输出警告:
MCP_TRANSPORT=http MCP_ALLOW_INSECURE_DEV=1 node dist/index.js
本地开发说明:
@wyre-technology/node-connectwise-cpq声明的版本为^1.0.0,但 尚未发布;在 SDK 首个版本发布之前,从全新克隆的仓库执行npm ci会失败。 请改为安装本地构建的 SDK tarball:npm install /path/to/wyre-ai-node-connectwise-cpq-0.0.0-semantically-released.tgz(然后将package.json保持为^1.0.0)。
Docker(根据集群规范使用 linux/amd64):
镜像会在容器内监听 0.0.0.0(MCP_HTTP_HOST),并默认使用 AUTH_MODE=gateway。请将端口发布到环回地址,并传入 S2S 密钥。在 gateway 模式下,CPQ 凭据会作为标头随每个请求传入;不会从环境变量中读取。
docker build --platform linux/amd64 --build-arg GITHUB_TOKEN=$(gh auth token) \
-t connectwise-cpq-mcp .
docker run \
-e CONDUIT_S2S_SECRET \
-p 127.0.0.1:8080:8080 \
connectwise-cpq-mcp
若未设置 CONDUIT_S2S_SECRET,Compose 将拒绝启动;默认将 AUTH_MODE 设为 gateway,发布 127.0.0.1:8080:8080,且不会注入 CPQ_ACCESS_KEY、CPQ_PUBLIC_KEY 或 CPQ_PRIVATE_KEY:
export CONDUIT_S2S_SECRET="$(openssl rand -hex 32)"
GITHUB_TOKEN=$(gh auth token) docker compose up
单租户 HTTP(AUTH_MODE=env)仍需要 S2S 密钥,然后使用 CPQ_* 变量:
docker run \
-e CONDUIT_S2S_SECRET \
-e AUTH_MODE=env \
-e CPQ_ACCESS_KEY=... \
-e CPQ_PUBLIC_KEY=... \
-e CPQ_PRIVATE_KEY=... \
-p 127.0.0.1:8080:8080 \
connectwise-cpq-mcp
MCP Apps 报价卡片
cpq_get_quote 提供只读的 MCP Apps 卡片
(ui://connectwise-cpq/quote-card.html),用于展示报价抬头、状态徽章、
明细项摘要和总计。该卡片纯属附加内容:不支持 MCP Apps 的宿主会收到完整的 QuoteView JSON(_card 字段是额外内容,绝不会取代 JSON),而任何卡片构建失败都不会影响 JSON。使用 npm run build:ui
重新构建内嵌 UI(构建结果已提交至 src/generated/quote-card-html.ts)。可在服务运行时通过
MCP_BRAND_* 环境变量设置品牌。
引导式输入与破坏性操作的授权确认
如果已连接的客户端支持引导式输入,服务会在操作前进行询问:对未筛选的报价搜索询问日期范围、对有歧义的名称询问模板选择、添加项目时询问标签页选择,并在每次删除前请求确认。引导式输入通过 SDK v2 MRTR 接口实现:处理程序会返回 input_required 结果(其中嵌入了 elicitation/create 请求),由 2026-07-28 客户端完成处理并重试;对于 2025 年时期的有状态连接(stdio),则由 SDK 的旧版兼容层在服务端完成处理。所有引导式输入都符合 MRTR 安全要求:在引导式输入环节之前,绝不会触发供应商端变更,因此客户端重试原始请求不会导致重复写入。
从未声明表单引导式输入能力的调用方——包括无状态旧版 HTTP 请求,WYRE Conduit 网关就是通过这种方式连接的——完全无法收到提示。这意味着什么取决于风险程度:
- 可选的引导式输入会优雅降级(design.md §4):未筛选的搜索会回退到默认的 90 天范围,并说明这一点;有歧义的模板/标签页选择器则会返回一条列出候选项的错误。
- 破坏性工具会默认拒绝执行。无法作答的客户端并未表示同意,因此五个
cpq_delete_*工具会拒绝运行,并返回说明应采取什么操作的可执行错误。非交互式调用方可在每次调用时通过"confirm_destructive_action": true明确授权;该参数已声明在每个破坏性工具的输入架构中,因此该门槛确实可以满足。只有在无法显示提示时,才会检查此参数——它绝不会跳过交互式用户本应看到的确认步骤。
此处编码的供应商特性
- 缺少
Authorization标头 → CPQ 返回 500(而非 401);在发出任何请求前,客户端都会先验证凭据。 - 实际的 401 响应正文包含供应商拼写错误(
"...has occured during basic auth validation")。 - 每个请求都使用
Content-Type: application/json; version=1.0(媒体类型版本控制)。 - 列表响应是裸 JSON 数组——当页数不足时,分页即告结束。
- 条件日期必须仅包含日期并用方括号括起:
createDate >= [2026-07-01]。 - PATCH 请求正文是 RFC 6902 JSON Patch 数组。
许可证
Apache-2.0 © WYRE Technology
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。