Skip to main content
Glama
mspstack

mcp-connectwise-psa

by mspstack

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

Маршрут

Назначение

POST/GET/DELETE /mcp

Конечная точка MCP streamable-http

GET /health

Проверка живости (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.

Ключ набора

Инструменты

tickets

cw_search_tickets, cw_my_tickets, cw_get_ticket, cw_create_ticket, cw_update_ticket, cw_add_ticket_note, cw_list_boards, cw_get_board, cw_list_priorities, cw_list_ticket_time, cw_list_ticket_tasks

time

cw_create_time_entry, cw_update_time_entry, cw_list_my_time, cw_list_work_roles, cw_list_my_timesheets, cw_submit_timesheet

companies

cw_search_companies, cw_get_company, cw_search_contacts, cw_get_contact, cw_list_company_sites

configurations

cw_list_configurations, cw_get_configuration

scheduled

cw_list_schedule_entries, cw_my_schedule, cw_schedule_ticket, cw_update_schedule_entry, cw_delete_schedule_entry, cw_member_availability, cw_list_members, cw_get_member

finance

cw_list_invoices, cw_get_invoice, cw_list_agreements, cw_get_agreement, cw_list_unbilled_time

advanced

cw_find_endpoint (поистр по всему API CW — ~1,150 конечноtut), cw_get (только чтение GET по любому пути)

sql (on-prem, требует CW_DB_*)

cw_db_query (T-SQL только для чтения), cw_db_find_table (каталог схемы), cw_db_find_query / cw_db_save_query) (библиотека сохраненных запросов)

Пресеты группируют ключи по ролям: 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, or x-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.sql

ok создает логин без каких-либо ролей сервера, добавляет в 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.

Справочник по конфигурации

Переменная

По умолчанию

Назначение

CW_SITE

Хост ConnectWise (облачный или локальный; принимаются полные URL)

CW_COMPANY_ID

company id для входа

CW_CLIENT_ID

clientId интеграции

CW_PUBLIC_KEY / CW_PRIVATE_KEY

Ключи API-участника — обязательны для stdio; в HTTP не используются (BYOK)

CW_MEMBER_IDENTIFIER

Участник, которому принадлежат ключи stdio (my-tickets/my-time)

TRANSPORT / PORT

stdio / 3000

Выбор транспорта

CW_TOOLSETS

all

Включённые наборы инструментов (ключи/пресеты); на HTTP переопределяются на сессию через x-cw-toolsets

CW_DB_HOST

Хост SQL Server ConnectWise или host\INSTANCE — включает набор инструментов sql

CW_DB_NAME / CW_DB_USER / CW_DB_PASSWORD

База данных и её отдельная учётная запись только для чтения (все четыре задаются вместе)

CW_DB_PORT

1433

TCP-порт; вместе с именованным экземпляром недопустим

CW_DB_ENCRYPT / CW_DB_TRUST_SERVER_CERT

true / true

TLS; также принимается типовой самоподписанный локальный сертификат (on-prem)

CW_DB_READ_UNCOMMITTED

true

Чтение на READ UNCOMMITTED, чтобы отчётные запросы никогда не блокировали проводящие запись процессы прода

CW_DB_QUERY_TIMEOUT_MS / CW_DB_MAX_ROWS

30000 / 200

Предел времени на запрос и максимальное количество строк

CW_DB_QUERY_LIBRARY

Путь к файлу сохраняемых запросов с правом записи; не задан ⇒ только встроенные запросы, инструмента сохранения нет

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

MIT

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
4dRelease cycle
11Releases (12mo)
Commit activity

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

  • A
    license
    A
    quality
    A
    maintenance
    MCP 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.
    37
    93
    3
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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