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 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