mcp-connectwise-psa
mcp-connectwise-psa
MCP-сервер (Model Context Protocol) для ConnectWise PSA (Manage) — подобранные инструменты из 8 наборов, закрывающие задачи техников, диспетчеров и выставления счетов, плюс запасной выход на остальную часть API и набор SQL только для чтения для локальных (on-prem) развертываний — чтобы ИИ-ассистент работал с PSA так, как с ней работает каждая роль:
Заявки — поиск / мои заявки / полная детализация с заметками, создание, изменение статуса/приоритета/ответственного, добавление обсуждений и внутренних заметок, а также получение списка досок·статусов·приоритетов и времени и задач по конкретной заявке
Время — списание времени по заявкам, просмотр собственного времени, поиск рабочих ролей и просмотр и отправка своих табелей учета времени
Компании и контакты — быстрый поиск, подробная карточка контакта (телефоны/эл. почта), площадки компаний
Объекты — устройства/активы с серией, IP, ОС и гарантийной сроком (только центральный доступ)
Диспетчеризация (расписание) — записи расписания (список/мои/создание/перенос/отмена), а также участники с часовым поясом, рабочими часами и доступностью «свободен/занят»
Выставление счетов (финансы, только чтение) — счета, агрехи и невыставленные оплачиваемые часы, готовые к выставлению
SQL (только on-prem) — T-SQL только для чтения напрямую против базы Manage
cwwebapp_*для межтабличной отчетности, которую REST не может выразить; в комплекте — каталог схемы с поиском и библиотека сохраненных запросов, которую ассистент может пополнять. Включается настройкойCW_DB_*; если она задана, каждая сессия, которая не сужает свои наборы, имеет этот наборНаборы и роли — возможность настроить только нужное для сессии через заголовок
x-cw-toolsets(илиCW_TOOLSETS); пресетыtech/dispatch/invoicing/all. По умолчанию —all; сузите его для сессии, если нужен маленький набор кода. Каждый инструмент также передает свой набор в виде_meta.tool, поэтому агрегатор (шлюз MSPMSP) может группировать и переключать инструменты по возможностиСвои API-ключи участника (BYOK) — каждый пользователь приносит свои ключи участника ConnectWise; ConnectWise сам применяет роль безопасности этого участника, и каждая запись приписывается конкретному человеку
Транспорты — STDIO для локального использования, streamable HTTP для общих развертываний; включая Docker-образ
Quick start (локальный, 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.jsКонфигурация Claude 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"
}
}
}
}Коллизии clientId требует API ConnectWise — зарегистрируйте (бесплатную) интеграцию на developer.connectwise.com. Ключи API-участника создаются в ConnectWise в разделе My Account → API Keys (для каждого участника) или System → Members. API Members (интеграционные записи).
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 |
| Проверка живости (liveness) |
Все сессии хранятся в памяти — запускайте один экземпляр сервера (или используйте липкие сессии).
Управление доступом — со своими ключами (BYOK)
Пов HTTP не имеет системы ролей на уровне MCP. Каждая сессия передает свои ключи участника ConnectWise, и контроль доступа осуществляет сам 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-хэшу пары ключей; предоставление другой пары в том же идентификаторе session →
403.Создавайте API-ключи участника в ConnectWise в разделе My Account → API Keys. Каждый участник техникой использует свой.
Локальный stdio — однопользовательский и использует переменные окружения CW_PUBLIC_KEY/CW_PRIVATE_KEY вместо заголовков.
Наборы инструментов
Инструменты сгруппированы в наборы инструментов (toolsets), чтобы сессия видела только нужные возможности: диспетчеру не нужны средства выставления счетов, а маленькая поверхность поддерживает фокус (и дешевле контекст ассистента). Управление на возникающие возможности по-прежнему определяется ролью безопасности участника во 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 только для чтения к любому пути — так ассистент может достичь "длинный хвост" (procurement, sales, projects, system…), который и текущие инструменты не охватывают. Чтобы исключить его, укажите вместо него ключи или ролевые пресеты — например, x-cw-toolsets: tech.
Выбирайте наборы с списком через коммуник, смешивая ключи и пресеты:
HTTP — заголовок
x-cw-toolsetsдля каждой сессии:x-cw-toolsets: dispatch, orx-cw-toolsets: tech,finance.stdio — переменная окружения
CW_TOOLSETSили флаг--toolsets:CW_TOOLSETS=invoicing.
По умолчанию — пресет all — все возможности, которые сервер настроен обрабатывать; клиент, который хочет меньший набор, называет нужные ему ключи или персона. Неизвестные ключи в CW_TOOLSETS/--toolsets приводят к быстрому завершению; неизвестные токены в заголовке x-cw-toolsets наверное и игнорируются. Единственный разрушающий инструмент — cw_delete_schedule_entry (dispatch); финансы — только на чтение. Инстро cw_db_save_query записывает данные, но только в файла библиотеки запросов: доступом к базе разрешен только SELECT по грантам.
Исключение: набор sql
Каждый остальной набор работает получения собственными ключами ConnectWise вызывающего, поэтому на ошибку фильтрации налагается. А вот набор sql — нет: он читает базу через серверный логин только для чтения, поэтому результаты не приписываются участнику и не уфильтруются его ролью безопасности, ограничниями по доскам или правами записей.
Поэтому настройка CW_DB_* — это важное решение. Как только на сервере есть база, sql становится обычным ключом: он входит в all, он входит в выбор по умолчанию, и каждая сессия, которая не сужает свои наборы инструментов, может прочитать всю базу PSA. Сервер без настройки CW_DB_* просто отбрасывает sql молча, так что в развертываниях, которые этого не хотели, ничего не ломается.
Если вам нужен доступ к базе для одних вызывающих, но не для других, делайте это по сессии (x-cw-toolsets: tech) или перед сервером — экскаются на шлюзе могут разделять cw_* инструменты по уровням. Что ограничивает ущерб на стороне сервера — это сам логин: смотрите у ниже в руководстве, и держите его ролью db_datareader с закрытием колонок с учетными данными.
SQL набор (база данных только для локального размещения)
Облачная ConnectWise не дают доступа к базе данных, поэтому этот набор — только для локали развернуть (on-prem). Направьте его на базу 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 входит в выбор по умолчанию. Если явно указать sql без CW_DB_*, запуск вызовет ошибку (а выбор, который лишь включает его, как all, молча сокращается). Никакое соединение с базой не происходит, hasta пока сессия не использует инструмент.
Начните с отчётовых представлений. ConnectOftenes постаставляет денормализованные представления v_rpt_*, которые уже связывают доски, статус, компанию и контакт с записью — v_rpt_service, v_rpt_time, v_rpt_company, v_rpt_invoices, v_rpt_greementlist. cw_db_find_table знает те представления и базовые таблицы за ними и несёт только ключевые поля, поскольку точный список полей — это один запрос к INFORMATION_SCHEMA, и он всегда верен для вашей версии.
Библиотека сохраненных запросов — это commit в репозитории единственное ядро plи запись-в к файл-наложение, указанный в 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 как есть, поэтому логин имеет ровно те права, которые реально могут выполнить. Два скрипта настраивают и подтvely.
Создание — правьте четыре переменные в начале, запустите как sysadmin. @WhatIf = 1 by default, so the first run only печатает план:
sqlcmd -S SQLHOST\CWPROD -d master -i scripts/create-readonly-login.sqlok создает логин без каких-либо ролей сервера, добавляет в db_datareader в одной базе, дает DENY для всего остального (EXECUTE, все записи, DDL, BACKUP) и выдает DENY SELECT on все похожие на учётные данные поля, которые обнаруживают — названия меняются между версиями Manage, и каждый MSP добавляет свои, так что они находятся, а не захардкожены. Повторный запуск безопасен; так вы заново применяете DENY после за upgrade, который добавил таблицы. Скрипт сообщает об инстанс-wide параметрах, которые должны быть выключены, но никогда их не меняет: отключение xp_cmdshell может сломать другие приложения, поэтому это остаёт администtake.
Проверка — от имени нового логина, не как admin:
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 — вот разрешение, которое имеет значение. При нём «read-only SQL» превращается в удалённое выполнение кода от имени учётной записи службы SQL Server:
xp_cmdshell,sp_OACreate,sp_send_dbmail,xp_dirtree— для перехвата NTLM.OPENROWSET/BULK INSERTчитают файлы вообще без EXECUTE, поэтому Ad Hoc Distributed Queries тоже должны быть выключены.
С эксплуатационной точки зрения: на отчётность берите читаемую вторичную реплику группы доступности или восстановленную копию, а не основной экземпляр прода, доступ к SQL-порту ограничьте межсетевым экраном по MCP-хосту и держите на этом логине сеанс SQL Audit или Extended Events.
Справочник по конфигурации
Переменная | По умолчанию | Назначение |
| — | Хост ConnectWise (облачный или локальный; принимаются полные URL) |
| — | company id для входа |
| — | clientId интеграции |
| — | Ключи API-участника — обязательны для stdio; в HTTP не используются (BYOK) |
| — | Участник, которому принадлежат ключи stdio (my-tickets/my-time) |
|
| Выбор транспорта |
|
| Включённые наборы инструментов (ключи/пресеты); на HTTP переопределяются на сессию через |
| — | Хост SQL Server ConnectWise или |
| — | База данных и её отдельная учётная запись только для чтения (все четыре задаются вместе) |
|
| TCP-порт; вместе с именованным экземпляром недопустим |
|
| TLS; также принимается типовой самоподписанный локальный сертификат (on-prem) |
|
| Чтение на READ UNCOMMITTED, чтобы отчётные запросы никогда не блокировали проводящие запись процессы прода |
|
| Предел времени на запрос и максимальное количество строк |
| — | Путь к файлу сохраняемых запросов с правом записи; не задан ⇒ только встроенные запросы, инструмента сохранения нет |
Notes & limits
Поиск тикетов по умолчанию ищет среди открытых тикетов; имена статусов и досок должны задаваться точно, текстовые фильтры работают по подстроке.
В метках времени должны быть целые секунды — сервер сам приводит их к такому виду (ConnectWise отклоняет доли секунды).
Для записей времени требуется открытый отчётный период времени в ConnectWise на указанную дату; когда его нет, передаётся сообщение API.
На некоторых локальных версиях
/system/myAccountотсутствует — передавайте идентификатор участника явно (CW_MEMBER_IDENTIFIERилиx-cw-member-id) для «my tickets»/«my time».Заметки обсуждения видны клиенту, а внутренние — нет: инструмент явно это указывает.
cw_db_queryостанавливается послеmax_rows(по умолчанию 200) или по бюджету в 20 000 символов; отменой и запрос на стороне сервера происходит с указанием лимита — эта информация попадает к клиенту. Дедлайн по умолчанию — 30 с, максимум 120 с.Подключение к базе данные читает на уровне READ UNCOMMITTED, чтобы сканирование отчёта не блокировало сохранение тикета специалистом. Цена этого — «грязные» чтения: при параллельной записи подсчёты выходят приблизительными. Установите
CW_DB_READ_UNCOMMITTED=false, если отчёт должен быть точным.SELECT *не будет работать на таблице с запрещённым столбцом — перечисляйте нужные вам столбцы.В облачных экземплярах ConnectWise нет доступа к базе данных; набор инструментов
sqlработает только на локальных установках.
Development
npm install
npm run dev # stdio via tsx
npm run dev:http # http via tsx
npm test # vitest
npm run build # tsc → dist/License
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for GLPI: tickets, ITIL, assets, knowledge base. GLPI 10/11. Not affiliated with Teclib'.
Hosted MCP servers for MSP tools: ConnectWise, NinjaOne, Microsoft 365, SentinelOne, Pax8 and more.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceAn MCP server for ConnectWise Manage PSA, enabling management of tickets, projects, contacts, billing, and service operations through ConnectWise Manage's API.27Apache 2.0
- AlicenseAqualityAmaintenanceAn MCP server for SuperOps PSA/RMM, enabling MSPs to manage tickets, assets, clients, and field technician operations through SuperOps's API.223Apache 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.37557 npm4MIT