mcp-connectwise-psa
mcp-connectwise-psa
一个用于 ConnectWise PSA (Manage) 的 MCP (Model Context Protocol) 服务器 — 覆盖 8 个工具集的精选工具,涵盖技术人员、调度员和计费,外加一个用于其余 API 的逃生舱和一个用于本地部署的只读 SQL 工具集,使 AI 助理能够像每个角色一样使用 PSA:
工单 — 搜索 / 我的工单 / 含备注的完整详情,创建,更新状态/优先级/负责人,添加讨论/内部备注,外加看板·状态·优先级发现以及每张工单的时间和任务
时间 — 针对工单记录时间,查看自己的时间,工作角色查询,以及列出并提交时间表
公司与联系人 — 快速查找,联系人详情(电话/电子邮件),公司站点
配置 — 带序列号、IP、操作系统、保修信息的设备/资产(只读)
调度 (schedule) — 计划条目(列表/我的/创建/重新安排/取消),以及成员及其时区、工作时间和空闲/已预订可用性
开票 (finance, 只读) — 发票、协议,以及随时可开票的未开票计费时间
SQL (仅限本地部署) — 直接针对
cwwebapp_*Manage 数据库执行只读 T-SQL,用于 REST 无法表达的跨表报表,附带可搜索的架构目录和一个助手可以不断扩充的已保存查询库。通过配置CW_DB_*启用;一旦启用,每个未收窄工具集的会话都会拥有它工具集与角色预设 — 通过
x-cw-toolsets标头(或CW_TOOLSETS)仅启用会话所需的功能;预设tech/dispatch/invoicing/all。默认是all— 当需要更小的工具面时,可按会话收窄。每个工具还会将其工具集报告为_meta.group,因此聚合器(MSPStack 网关)可以按能力对工具进行分组和切换按成员 API 密钥 (BYOK) — 每个用户提供自己的 ConnectWise 成员密钥;ConnectWise 强制执行该成员的安全角色,并且每次写入都归属于实际人员
传输方式 — 本地使用 stdio,共享部署使用 streamable HTTP;包含 Docker 镜像
快速开始(本地,stdio)
npm install && npm run build
CW_SITE=na.myconnectwise.net \
CW_COMPANY_ID=yourcompany \
CW_CLIENT_ID=<integration clientId> \
CW_PUBLIC_KEY=xxxx CW_PRIVATE_KEY=yyyy \
CW_MEMBER_IDENTIFIER=jdoe \
node dist/index.jsClaude Desktop / Claude Code 配置:
{
"mcpServers": {
"connectwise": {
"command": "node",
"args": ["/path/to/mcp-connectwise-psa/dist/index.js"],
"env": {
"CW_SITE": "na.myconnectwise.net",
"CW_COMPANY_ID": "yourcompany",
"CW_CLIENT_ID": "<clientId>",
"CW_PUBLIC_KEY": "xxxx",
"CW_PRIVATE_KEY": "yyyy",
"CW_MEMBER_IDENTIFIER": "jdoe"
}
}
}
}ConnectWise API 要求提供 clientId — 在 developer.connectwise.com 注册一个(免费)集成。API 成员密钥在 ConnectWise 中创建,路径为 我的账户 → API 密钥(按成员)或 系统 → 成员 → API 成员(集成账户)。
Related MCP server: superops-mcp
HTTP 部署
CW_SITE=… CW_COMPANY_ID=… CW_CLIENT_ID=… \
node dist/index.js --transport http --port 3000或使用 Docker:docker build -t mcp-connectwise-psa . && docker run -p 3000:3000 -e CW_SITE -e CW_COMPANY_ID -e CW_CLIENT_ID mcp-connectwise-psa
路由 | 用途 |
| MCP streamable-http 端点 |
| 存活探针 |
会话保存在内存中 — 请运行单个实例(或使用粘性会话)。
访问控制 — 自带密钥 (BYOK)
在 HTTP 上没有 MCP 级别的角色系统。每个会话出示自己的 ConnectWise 成员 API 密钥,ConnectWise 本身就是访问控制:成员的安全角色决定哪些操作成功,每条备注和时间条目都归属于该成员。
在 initialize 请求中发送你的密钥(以及会话中的每个后续请求):
x-cw-public-key: <public key>
x-cw-private-key: <private key>
x-cw-member-id: <your member identifier> (optional — enables "my tickets"/"my time")没有密钥的请求将被拒绝并返回
401;两个密钥标头必须同时提供。密钥永远不会被记录。会话绑定到密钥对的 SHA-256 哈希;在同一会话 ID 上出示不同的密钥对 →
403。在 ConnectWise 中通过 我的账户 → API 密钥 创建成员 API 密钥。每个技术人员使用自己的密钥。
本地 stdio 是单用户的,使用环境变量 CW_PUBLIC_KEY/CW_PRIVATE_KEY 而不是标头。
工具集
工具被分组到工具集中,这样会话只能看到它所需的能力 — 调度员不需要开票工具,小的工具面可以让助手保持专注(并且其上下文成本更低)。写入是否真正成功仍然由成员的 ConnectWise 安全角色决定。
工具集键 | 工具 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
预设按角色捆绑键:tech = tickets + time + companies + configurations · dispatch = tickets + schedule + companies + configurations · invoicing = finance + time + companies · all = 所有键。角色预设刻意排除 sql — 技术人员工具面不是数据库工具面。
advanced 工具集是逃生舱(在 all 中,但不在任何角色预设中):cw_find_endpoint 搜索捆绑的完整 ConnectWise API 目录,cw_get 对任意路径执行只读 GET — 因此助手可以触及精选工具未包裹的长尾(采购、销售、项目、系统…)。要移除它,请改为指定键或角色预设(x-cw-toolsets: tech)。
使用逗号列表选择工具集,可混合键和预设:
HTTP — 每个会话的
x-cw-toolsets标头:x-cw-toolsets: dispatch或x-cw-toolsets: tech,finance。stdio —
CW_TOOLSETS环境变量或--toolsets标志:CW_TOOLSETS=invoicing。
默认是 all 预设 — 服务器配置了的所有能力;想要更小工具面的客户端会指定它需要的键或角色。CW_TOOLSETS/--toolsets 中的未知键会快速失败;x-cw-toolsets 标头中的未知令牌会被忽略。唯一的破坏性工具是 cw_delete_schedule_entry(dispatch);finance 是只读的。cw_db_save_query 会写入,但只写入查询库文件 — 数据库访问本身通过授权仅为 SELECT。
例外:sql 工具集
其他每个工具集都使用调用者自己的 ConnectWise 密钥运行,因此 ConnectWise 会过滤返回的内容。sql 则不然:它通过服务器范围的只读登录读取数据库,因此其结果不归属于任何成员,也不会被该成员的安全角色、看板限制或记录权限过滤。
因此,配置 CW_DB_* 才是关键决定。一旦服务器配置了数据库,sql 就是一个普通键:它在 all 中,在默认选择中,并且每个未收窄工具集的会话都可以读取整个 PSA 数据库。没有 CW_DB_* 的服务器会静默地移除它,因此从不想要它的部署不会出任何问题。
如果你需要让某些调用者而不是其他调用者访问数据库,请按会话执行(x-cw-toolsets: tech)或在服务器前面执行 — 聚合网关可以分别对 cw_db_* 工具分层。在服务器端限制损害的是登录:请参阅下面的运行手册,并将其保持为 db_datareader,同时拒绝凭据列。
SQL 工具集(本地部署数据库)
云托管的 ConnectWise 不提供数据库访问权限,因此此工具集仅适用于本地部署。请使用专门为此目的创建的登录,将其指向 Manage 数据库:
CW_DB_HOST=sqlhost CW_DB_NAME=cwwebapp_acme \
CW_DB_USER=cw_mcp_ro CW_DB_PASSWORD=… \
CW_DB_QUERY_LIBRARY=/data/cw-queries.json \
node dist/index.js这就是全部:配置了数据库后,sql 工具集就成为默认选择的一部分。如果没有 CW_DB_* 却显式指定 sql,启动时会失败(而像 all 这样仅包含它的选择会被剪除)。在会话真正使用工具之前,不会连接到数据库。
从报表视图开始。 ConnectWise 附带反规范化(denormalized)的 v_rpt_* 视图,这些视图已经将看板、状态、公司和联系人联接到记录上 — v_rpt_service、v_rpt_time、v_rpt_company、v_rpt_invoices、v_rpt_agreementlist。cw_db_find_table 知道这些视图及其背后的基础表;它只携带关键列,因为确切的列列表只需一次 INFORMATION_SCHEMA 查询即可获得,并且对于你的版本来说始终是正确的。
已保存查询库是已提交的核心加上位于 CW_DB_QUERY_LIBRARY 的可写覆盖层(JSON,{ version, queries[] })。覆盖层条目按 slug 优先,cw_db_save_query 会追加到其中,scripts/import-queries.mjs 从现有的 BrightGauge 导出中填充它:
node scripts/import-queries.mjs /path/to/brightgauge-export导入的查询保留在此存储库之外 — 它们是你的报表,可能包含公司名称和费率。在容器上,将 CW_DB_QUERY_LIBRARY 指向挂载的存储,否则已保存的查询会随容器一起消亡。
登录就是安全边界
没有语句验证:服务器按原样将模型的 SQL 发送给 SQL Server,因此登录被允许做什么,就恰好可能发生什么。两个脚本负责设置并证明这一点。
创建它 — 编辑顶部的四个变量,以 sysadmin 身份运行。@WhatIf 默认为 1,因此第一次运行只打印计划:
sqlcmd -S SQLHOST\CWPROD -d master -i scripts/create-readonly-login.sql它创建的登录不归属任何服务器角色,将其添加到某个数据库的 db_datareader,DENY 其他所有权限(EXECUTE、所有写入、DDL、BACKUP),并对其发现的每个看似凭据的列 DENY SELECT — 这些列名会随 Manage 版本变化,而且每个 MSP 都会添加自己的列,因此通过发现而非硬编码来找到它们。重新运行是安全的,也是在升级添加表后重新应用 DENY 的方式。它会报告必须关闭但从不更改的实例级设置:禁用 xp_cmdshell 可能破坏其他应用程序,因此这仍然是一个决策。
验证它 — 使用新的登录身份,而不是管理员身份:
sqlcmd -S SQLHOST\CWPROD -d cwwebapp_acme -U cw_mcp_ro -P '<password>' -i scripts/verify-readonly-login.sql每项检查都会输出 PASS 或 FAIL:SELECT 可正常使用,UPDATE/CREATE TABLE 被拒绝(在一个始终回滚的事务中执行,以防因缺少 DENY 而导致实际写操作发生),xp_cmdshell/sp_OACreate/OPENROWSET(BULK …) 不可达,凭据列不可读,且登录名未处于任何高风险角色中。只要是 FAIL 就代表当下不应启用该工具集。
先了解两个重要后果:
SELECT *在含被拒列的任意表上都会失败,而不是返回其余列。这正是有意为之;工具的错误信息会提示模型指定所需的列名。EXECUTE 权限才是关键权限。 拥有该权限后,“只读 SQL”会变成以 SQL Server 服务账户身份执行的远程代码执行——
xp_cmdshell、sp_OACreate、sp_send_dbmail,以及用于 NTLM 捕获的xp_dirtree。OPENROWSET/BULK INSERT在完全不需要 EXECUTE 权限的情况下即可读取文件,因此 Ad Hoc Distributed Queries(Ad Hoc 分布式查询)也必须关闭。
操作层面建议:优先使用可读的 AG 辅助数据库副本或当前生产环境已恢复的报表副本;将 SQL 端口访问限制为仅 MCP 主机可访问;并针对此登录名启用 SQL Audit 或 Extended Events 会话。
配置参考
Variable | Default | Purpose |
| — | ConnectWise 主机(云或本地部署;接受完整 URL) |
| — | 登录公司 ID |
| — | 集成 clientId |
| — | API 成员密钥 — stdio 必需;HTTP(自带证书)不使用 |
| — | stdio 密钥所属的成员(my-tickets/my-time) |
|
| 传输选择 |
|
| 启用的工具集(keys/预设);HTTP 可通过 |
| — | ConnectWise SQL Server 主机,或 |
| — | 数据库及其专用只读登录(四项必须同时提供) |
|
| TCP 端口;与无实例名同时使用时不生效 |
|
| TLS,以及接受本地站点常见的自签名证书 |
|
| 以 READ UNCOMMITTED 读取,避免报表扫描阻塞生产库的写操作 |
|
| 每次查询的截止时间和行数上限 |
| — | 可写已保存查询文件路径;未设置 ⇒ 仅内置查询,不提供保存工具 |
说明与限制
工单搜索默认为开放工单;状态 / 看板名称需要精确匹配,基于文本的过滤器使用子串匹配。
时间戳必须带整秒——服务器会进行格式化(ConnectWise 不接受含小数的秒)。
时间条目要求在 ConnectWise 中,该日期必须对应一个处于打开状态的时间报告周期;若不存在该周期,API 的提示信息会被原样透传。
部分本地版本未提供
/system/myAccount——对于“my tickets” / “my time”,需要显式提供成员标识符(CW_MEMBER_IDENTIFIER或x-cw-member-id)。讨论备注对客户同步可见;内部备注对客户不可见——工具本身会明确区分这一点。
cw_db_query在达到max_rows(默认 200)或约 20,000 字符预算限制时终止,并会从服务端取消该查询;响应中会说明当前命中哪个限制。单次查询默认超时时间为 30 秒,最长不超过 120 秒。数据库连接使用了 READ UNCOMMITTED 读级别,以避免报表扫描阻塞验证人员保存工单。代价是可能读到脏数据:在并发写入时,计数结果会不准。如需精确报表,请将
CW_DB_READ_UNCOMMITTED设为false。SELECT *在任意包含 DENY 列的表上都会失败——请明确列出所需列名。云端托管的 ConnectWise 实例没有数据库访问权限;
sql工具集仅限本地部署。
开发
npm install
npm run dev # stdio via tsx
npm run dev:http # http via tsx
npm test # vitest
npm run build # tsc → dist/语 .
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server for ConnectWise Manage PSA, enabling management of tickets, projects, contacts, billing, and service operations through ConnectWise Manage's API.19Apache 2.0
- AlicenseAqualityAmaintenanceAn MCP server for SuperOps PSA/RMM, enabling MSPs to manage tickets, assets, clients, and field technician operations through SuperOps's API.213Apache 2.0
- AlicenseNot gradedqualityAmaintenanceMCP server for Kaseya BMS PSA — tickets, accounts, time entries, and contracts. Enables AI assistants to manage service desk operations via the Kaseya BMS API.Apache 2.0
- AlicenseAqualityAmaintenanceMCP server for SolarWinds Service Desk (SWSD/Samanage) enabling reading and modifying tickets, comments, knowledge-base articles, and more via each user's own API token.37933MIT
Related MCP Connectors
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
A paid remote MCP for ClawManager, built to return verdicts, receipts, usage logs, and audit-ready J
MCP server for Appcircle mobile CI/CD platform.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mspstack/mcp-connectwise-psa'
If you have feedback or need assistance with the MCP directory API, please join our Discord server