内容
# 连接智慧管理MCP服务器
MCP(模型上下文协议)服务器,暴露连接智慧管理PSA REST API给Claude,使IT工程师能够通过自然语言处理工单、管理项目、记录时间以及查询数据。
## 功能特点
- **120种工具**,涵盖10个模块:工单、项目、时间与日程、公司、联系人、协议与财务、配置、机会、费用、系统
- **4种原始逃生工具**(需选择加入,`CWM_ENABLE_RAW_TOOLS=true`)供高级用户使用
- 生产级别认证,正确构造Basic + clientId头部
- JSON补丁(RFC 6902)用于所有更新 — 绝不会意外清空字段
- 内置分页、429速率限制重试以及结构化错误响应
- 严格的TypeScript、zod验证输入、pino日志输出到stderr
## 前置条件
- Node.js 20 LTS 或更新版本
- 一个连接智慧管理API成员,附带生成的API密钥(见下文)
- 从 [developer.connectwise.com](https://developer.connectwise.com) 注册的开发者客户端ID
### 生成CWM API凭证
您需要从连接智慧管理获取三个信息:**公钥**、**私钥** 和 **公司ID**。
**步骤 1 — 查找公司ID**
您的公司ID是在CWM登录屏幕上输入的登录公司名称(例如 `MyCompany`)。它 **不是** 一个数字。
**步骤 2 — 生成API密钥**
1. 登录连接智慧管理
2. 点击右上角的个人资料图标
3. 点击 **我的账户**
4. 切换到 **API密钥** 标签页
5. 点击 **新建API密钥**
6. 输入描述(例如 `Claude Desktop`)并点击 **保存**
7. **立即复制私钥** — 它只显示一次,无法再次检索
8. 同时复制 **公钥**
**步骤 3 — 获取客户端ID**
联系您的连接智慧管理管理员获取客户端ID(一个GUID)。他们在 [developer.connectwise.com](https://developer.connectwise.com) 上管理注册的开发者应用程序。
## 安装(Windows — 手动)
> **推荐大多数用户:** 使用下面的 [团队安装一键脚本](#团队安装一键脚本) 代替。手动安装适用于开发者或高级用户。
### 1. 安装Node.js 20
从 [nodejs.org](https://nodejs.org/) 下载并安装。验证:
```cmd
node --version
```
您应该看到 `v20.x.x` 或更高版本。
### 2. 克隆仓库
```cmd
git clone https://github.com/Allied-Business-Solutions/connectwise-manage-mcp.git C:\Users\YOUR_USERNAME\AppData\Local\Programs\ConnectWiseMCP
cd C:\Users\YOUR_USERNAME\AppData\Local\Programs\ConnectWiseMCP
```
用您的Windows用户名替换 `YOUR_USERNAME`。
### 3. 安装依赖
> **必需 — 不要跳过。** 这会下载服务器运行所需的所有包。
```cmd
npm install
```
### 4. 构建服务器
> **必需 — 不要跳过。** 这会将TypeScript编译为JavaScript。服务器没有此步骤将无法启动。
```cmd
npm run build
```
您应该看到没有错误。将会创建 `dist\` 文件夹。
### 5. 配置Claude Desktop
打开 `%APPDATA%\Claude\claude_desktop_config.json` 并添加以下内容(如果文件不存在,请创建):
```json
{
"mcpServers": {
"connectwise": {
"command": "node",
"args": ["C:\\Users\\YOUR_USERNAME\\AppData\\Local\\Programs\\ConnectWiseMCP\\dist\\index.js"],
"env": {
"CWM_SITE": "your-cwm-instance.example.com",
"CWM_COMPANY_ID": "YourCompanyId",
"CWM_PUBLIC_KEY": "your_public_key",
"CWM_PRIVATE_KEY": "your_private_key",
"CWM_CLIENT_ID": "your-client-id-guid"
}
}
}
}
```
用您的凭证替换 `YOUR_USERNAME` 并填写上文中的凭证。保存后重启Claude Desktop。
### 更新
#### 一键安装(大多数用户)
重新运行相同的安装命令 — 安装程序处理所有内容:
```powershell
irm https://raw.githubusercontent.com/Allied-Business-Solutions/connectwise-manage-mcp/master/deploy/install.ps1 | iex
```
#### 手动安装
```cmd
cd %LOCALAPPDATA%\Programs\ConnectWiseMCP
git pull
npm install
npm run build
```
然后 **重启Claude Desktop**,更新后您的 `claude_desktop_config.json` 中的凭证不会被触及。
#### 验证更新是否成功
重启Claude Desktop后,询问Claude: *"运行cw_ping并告诉我服务器版本。"* 响应应该反映您更新到的版本。
## 团队安装(一键脚本)
打开PowerShell并运行:
```powershell
irm https://raw.githubusercontent.com/Allied-Business-Solutions/connectwise-manage-mcp/master/deploy/install.ps1 | iex
```
安装程序将:
1. 通过 `winget` 安装Node.js 20 LTS(如果已存在则跳过)
2. 从GitHub下载最新版本
3. 提示输入个人CWM API凭证
4. 自动写入您的 `claude_desktop_config.json`
**前置条件:**
- Windows 10 1709+ 或 Windows 11(`winget` 需要)
- 已安装Claude Desktop
- 您的CWM API成员凭证(参见上文前置条件部分)
**升级:** 重新运行相同的命令。
**卸载:**
```powershell
irm https://raw.githubusercontent.com/Allied-Business-Solutions/connectwise-manage-mcp/master/deploy/uninstall.ps1 | iex
```
**Ninja RMM:** 将 `winget install OpenJS.NodeJS.LTS --silent --accept-package-agreements --accept-source-agreements` 作为先决条件策略推送。技术人员然后为自己的凭证运行上述安装程序。
## 环境变量
| 变量 | 是否必需 | 描述 |
|---|---|---|
| `CWM_SITE` | 是 | CWM主机名,例如 `your-cwm-instance.example.com`(不含 https://) |
| `CWM_COMPANY_ID` | 是 | 登录公司ID(不是数字ID) |
| `CWM_PUBLIC_KEY` | 是 | 您的API公钥(来自CWM的“我的账户” > “API密钥”) |
| `CWM_PRIVATE_KEY` | 是 | 您的API私钥(仅在生成时显示一次) |
| `CWM_CLIENT_ID` | 是 | 来自developer.connectwise.com的开发者应用GUID |
| `CWM_ENABLE_RAW_TOOLS` | 否 | 设置为 `true` 以启用原始逃生工具(默认为 `false`) |
| `CWM_MAX_PAGES` | 否 | paginateAll的最大页数(默认为 `20`) |
| `LOG_LEVEL` | 否 | pino日志级别:`debug`、`info`、`warn`、`error`(默认为 `info`) |
## 已知限制与注意事项
### 1. 认证头部格式(最常见的401原因)
用户名为 `CompanyId+PublicKey:PrivateKey` — `+` 在公司ID和公钥之间是 **字面字符**,而非URL编码。缺少 `+` 是最常见的 `401 Unauthorized` 错误原因,伴有误导性错误信息。`clientId` 头部也是必需的 — 没有它的请求会返回401。
### 2. 条件查询语言(非OData)
CWM使用其自己的过滤器语法:
- 字符串使用 **双引号**:`status/name="Open"` ✓ (不是单引号)
- 布尔值是无引号的小写字母:`closedFlag=false`
- 日期使用 **方括号**:`dateEntered>[2025-01-01T00:00:00Z]`
- 嵌套字段引用使用 `/`:`status/name`、`company/id`
### 3. PATCH使用RFC 6902 JSON补丁
CWM PATCH **不** 接受部分合并对象。它需要一个JSON补丁数组:
```json
[{ "op": "replace", "path": "/summary", "value": "新标题" }]
```
本服务器中的所有更新工具通过 `flatToJsonPatch()` 助手自动处理此操作。**不要使用PUT** — 它替换整个记录,并会清空未包含的字段。
### 4. 嵌套资源路径使用 `{parentId}`
子资源端点使用 `{parentId}` 表示父资源,而非 `{id}`:
- 正确:`/service/tickets/{parentId}/notes`
- 错误:`/service/tickets/{id}/notes`
这是规范约定 — 本服务器中的所有工具都使用正确的路径。
### 5. 状态ID特定于板块
状态ID因服务板块而异。使用 `cw_list_board_statuses` 获取板块的有效ID,然后再更改状态。便捷工具 `cw_change_ticket_status` 自动处理此查找。
**注意**:板块状态值特定于板块。在更改状态之前,请验证您的服务板块的正确状态名称。使用 `cw_list_board_statuses` 检查可用的状态。
### 6. 自定义字段 — 始终发送完整数组
更新自定义字段时,您必须发送 **完整** 的 `customFields` 数组,包括未更改的字段。省略数组中的字段 **会清除它**。在修补自定义字段值时使用 `mergeCustomFields()` 助手。
### 7. 分页
CWM默认不返回总计数。使用 `cw_count_tickets` (或等效的计数端点)在分页前获取总数。默认页面大小为25;最大为1000。`paginateAll()` 在 `CWM_MAX_PAGES` (默认为20)处上限,以防止失控的请求。
### 8. 429速率限制
服务器在429时自动重试,指数退避(最多3次重试,遵循 `Retry-After` 头部)。如果您遇到持续的速率限制,请增加工具调用之间的间隔。
## 工具索引
### 服务台 — 工单(25种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_tickets` | 列出工单,支持完整的筛选/分页 |
| `cw_search_tickets` | 按板块、状态、指派人、公司、摘要搜索工单 |
| `cw_get_ticket` | 按ID获取完整的工单详情 |
| `cw_count_tickets` | 统计匹配条件的工单数量 |
| `cw_create_ticket` | 创建新的服务工单 |
| `cw_update_ticket` | 通过JSON补丁更新工单字段 |
| `cw_delete_ticket` | 永久删除工单 |
| `cw_list_ticket_notes` | 列出工单的备注 |
| `cw_add_ticket_note` | 向工单添加备注 |
| `cw_update_ticket_note` | 更新现有的工单备注 |
| `cw_delete_ticket_note` | 永久删除工单备注 |
| `cw_list_ticket_tasks` | 列出工单的检查清单任务 |
| `cw_add_ticket_task` | 向工单添加任务 |
| `cw_update_ticket_task` | 更新工单任务 |
| `cw_complete_ticket_task` | 将任务标记为已完成 |
| `cw_delete_ticket_task` | 永久删除工单任务 |
| `cw_list_ticket_time_entries` | 列出工单的时间记录 |
| `cw_list_ticket_configurations` | 列出附加到工单的资产 |
| `cw_list_ticket_documents` | 列出工单的文件/附件 |
| `cw_change_ticket_status` | 按名称更改工单状态(自动解析ID) |
| `cw_assign_ticket` | 将工单指派给成员(按用户名) |
| `cw_merge_tickets` | 将源工单合并到目标工单 |
| `cw_list_boards` | 列出所有服务板块 |
| `cw_list_board_statuses` | 列出板块的有效状态 |
| `cw_list_board_types` | 列出板块的工单类型 |
### 项目(25种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_projects` | 列出项目,支持筛选 |
| `cw_get_project` | 获取完整的项目详情 |
| `cw_create_project` | 创建项目 |
| `cw_update_project` | 更新项目字段 |
| `cw_delete_project` | 永久删除项目 |
| `cw_list_project_phases` | 列出项目的阶段 |
| `cw_get_project_phase` | 获取单个阶段 |
| `cw_create_project_phase` | 创建项目阶段 |
| `cw_update_project_phase` | 更新阶段 |
| `cw_delete_project_phase` | 永久删除阶段 |
| `cw_list_project_tickets` | 列出项目中的工单(按项目ID) |
| `cw_get_project_ticket` | 按工单ID获取单个项目工单 |
| `cw_create_project_ticket` | 在项目中创建工单 |
| `cw_update_project_ticket` | 通过JSON补丁更新项目工单 |
| `cw_delete_project_ticket` | 永久删除项目工单 |
| `cw_list_project_ticket_notes` | 列出项目工单的备注 |
| `cw_add_project_ticket_note` | 向项目工单添加备注 |
| `cw_list_project_workplan` | 获取完整的阶段+工单工作计划树 |
| `cw_list_project_notes` | 列出项目备注 |
| `cw_add_project_note` | 向项目添加备注 |
| `cw_list_project_contacts` | 列出项目联系人 |
| `cw_list_project_team_members` | 列出项目团队成员 |
| `cw_add_project_team_member` | 向项目添加团队成员 |
| `cw_remove_project_team_member` | 从项目中移除团队成员 |
| `cw_list_project_documents` | 列出项目的文件/附件 |
### 时间与日程(12种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_time_entries` | 列出时间记录,支持筛选 |
| `cw_get_time_entry` | 按ID获取时间记录 |
| `cw_create_time_entry` | 记录工单或项目的时间 |
| `cw_update_time_entry` | 更新时间记录 |
| `cw_delete_time_entry` | 永久删除时间记录 |
| `cw_list_schedule_entries` | 列出日程/调度预约 |
| `cw_get_schedule_entry` | 按ID获取日程记录 |
| `cw_create_schedule_entry` | 创建日程记录 |
| `cw_update_schedule_entry` | 更新日程记录 |
| `cw_delete_schedule_entry` | 永久删除日程记录 |
| `cw_list_members` | 列出活跃的CWM成员 |
| `cw_get_member` | 按ID获取成员 |
### 公司(7种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_companies` | 列出公司 |
| `cw_get_company` | 按ID获取公司 |
| `cw_search_companies` | 按名称、标识符、城市、状态搜索公司 |
| `cw_update_company` | 更新公司字段 |
| `cw_list_company_sites` | 列出公司的站点 |
| `cw_list_company_notes` | 列出公司的备注 |
| `cw_add_company_note` | 向公司添加备注 |
### 联系人(7种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_contacts` | 列出联系人 |
| `cw_get_contact` | 按ID获取联系人 |
| `cw_search_contacts` | 按公司、名称、电子邮件搜索联系人 |
| `cw_create_contact` | 创建联系人 |
| `cw_update_contact` | 更新联系人 |
| `cw_list_contact_notes` | 列出联系人的备注 |
| `cw_add_contact_note` | 向联系人添加备注 |
### 协议与财务(12种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_agreements` | 列出协议 |
| `cw_get_agreement` | 按ID获取协议 |
| `cw_create_agreement` | 创建新协议 |
| `cw_update_agreement` | 更新协议字段 |
| `cw_delete_agreement` | 永久删除协议 |
| `cw_list_agreement_additions` | 列出协议的添加项(行项目) |
| `cw_get_agreement_addition` | 按ID获取单个添加项 |
| `cw_create_agreement_addition` | 向协议添加产品行项目 |
| `cw_update_agreement_addition` | 更新添加项(包括数量、按比例计算标志) |
| `cw_delete_agreement_addition` | 从协议中移除行项目 |
| `cw_list_invoices` | 列出发票 |
| `cw_get_invoice` | 按ID获取发票 |
### 配置(5种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_configurations` | 列出托管资产 |
| `cw_get_configuration` | 按ID获取资产 |
| `cw_create_configuration` | 创建配置记录 |
| `cw_update_configuration` | 更新配置 |
| `cw_list_configuration_types` | 列出配置类型 |
### 机会(10种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_opportunities` | 列出销售机会 |
| `cw_get_opportunity` | 按ID获取机会 |
| `cw_update_opportunity` | 更新机会 |
| `cw_delete_opportunity` | 永久删除机会 |
| `cw_list_opportunity_notes` | 列出机会备注 |
| `cw_add_opportunity_note` | 向机会添加备注 |
| `cw_convert_opportunity_to_project` | 将机会转换为项目 |
| `cw_convert_opportunity_to_ticket` | 将机会转换为服务工单 |
| `cw_list_opportunity_documents` | 列出机会的文件/附件 |
| `cw_list_quote_documents` | 列出销售报价的文件/附件 |
### 费用(10种工具)
| 工具 | 描述 |
|---|---|
| `cw_list_expense_entries` | 列出费用记录,支持筛选 |
| `cw_get_expense_entry` | 按ID获取费用记录 |
| `cw_create_expense_entry` | 创建费用记录 |
| `cw_update_expense_entry` | 更新费用记录 |
| `cw_delete_expense_entry` | 永久删除费用记录 |
| `cw_list_expense_reports` | 列出费用报告 |
| `cw_get_expense_report` | 按ID获取费用报告 |
| `cw_submit_expense_report` | 提交报告审批 |
| `cw_approve_expense_report` | 批准费用报告 |
| `cw_reject_expense_report` | 拒绝费用报告 |
### 系统/参考(7种工具)
| 工具 | 描述 |
|---|---|
| `cw_ping` | 健康检查 — 验证连接性和认证 |
| `cw_list_work_types` | 列出时间记录工作类型 |
| `cw_list_work_roles` | 列出时间记录工作角色 |
| `cw_list_priorities` | 列出工单优先级 |
| `cw_list_locations` | 列出系统位置 |
| `cw_list_departments` | 列出部门 |
| `cw_download_document` | 下载任意文档 — 从PDF中提取文本,为其他类型返回base64 |
### 原始逃生工具(4种,需选择加入)
| 工具 | 描述 |
|---|---|
| `cw_raw_get` | GET任意API路径 |
| `cw_raw_post` | POST任意API路径 |
| `cw_raw_patch` | PATCH任意API路径,使用JSON补丁 |
| `cw_raw_delete` | DELETE任意API路径 |
## 故障排除
**401 未授权**
- 检查是否设置了 `clientId`(每个请求都需要)
- 确认基本认证格式:`CompanyId+PublicKey:PrivateKey` — `+` 必须是字面字符
- 验证API成员是否活跃并已配置API密钥
**404 未找到**
- 确认 `CWM_SITE` 不包含 `https://` 或尾部斜杠
- API基准路径为 `/v4_6_release/apis/3.0/` — 此路径自动设置
**预期数据时返回空结果**
- 检查条件语法:字符串需要双引号,布尔值是无引号的小写字母
- 验证字段名称对嵌套路径使用 `/`:`status/name` 而非 `status.name`
**PATCH 无效**
- 所有更新工具都使用JSON补丁 — 验证您传递的是 `changes` 而非完整对象
- 检查字段路径:嵌套字段需要 `/`,例如 `"status/id": 42`
**速率限制(429)**
- 服务器在必要时最多重试3次
- 如果持续出现,请降低请求频率或增加工具调用之间的间隔
## 开发
```cmd
# 构建
npm run build
# 监视模式
npm run dev
# 运行测试
npm test
# 仅类型检查
npm run lint
# 烟雾测试(需要真实凭证)
set SMOKE_TEST=1 && npm run smoke
```
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器