mcp-connectwise-psa
mcp-connectwise-psa
ConnectWise PSA(Manage)용 MCP(Model Context Protocol) 서버 — 8개 툴셋에 걸친 선별된 도구로 기술자, 디스패처, 청구 담당자를 아우르며, 나머지 API를 위한 탈출구와 온프레미스 배포용 읽기 전용 SQL 툴셋까지 갖춰 AI 어시스턴트가 각 역할이 PSA를 다루는 방식 그대로 작업할 수 있게 합니다:
티켓(Tickets) — 검색 / 내 티켓 / 메모 포함 전체 상세, 생성, 상태/우선순위/담당자 업데이트, 토론·내부 메모 추가, 보드·상태·우선순위 탐색 및 티켓별 시간·작업
시간(Time) — 티켓에 시간 기록, 내 시간 조회, 작업 역할(work-role) 조회, 타임시트 목록 및 제출
회사 및 연락처(Companies & contacts) — 빠른 조회, 연락처 상세(전화/이메일), 회사 사이트
구성(Configurations) — 일련번호, IP, OS, 보증 정보가 포함된 장치/자산(읽기 전용)
디스패치(Dispatch) (일정) — 일정 항목(목록/내 일정/생성/재조정/취소), 시간대, 근무 시간, 예약 여부를 포함한 구성원 정보
인보이싱(Invoicing) (재무, 읽기 전용) — 인보이스, 계약, 청구 가능한 미청구 빌링 시간
SQL (온프레미스 전용) — REST로는 표현할 수 없는 교차 테이블 보고를 위해
cwwebapp_*Manage 데이터베이스에 직접 실행하는 읽기 전용 T-SQL. 검색 가능한 스키마 카탈로그와 어시스턴트가 확장할 수 있는 저장 쿼리 라이브러리 포함.CW_DB_*설정으로 활성화되며, 설정된 경우 툴셋을 좁히지 않는 모든 세션에서 사용 가능툴셋 및 페르소나(Toolsets & personas) —
x-cw-toolsets헤더(또는CW_TOOLSETS)로 세션이 필요한 기능만 활성화. 프리셋:tech/dispatch/invoicing/all. 기본값은all— 더 작은 표면이 필요할 때 세션별로 좁힐 수 있습니다. 각 도구는 또한 자체 툴셋을_meta.group으로 보고하므로, 집계자(MSPStack 게이트웨이)가 기능별로 도구를 그룹화하고 전환할 수 있습니다구성원별 API 키(BYOK) — 각 사용자가 자신의 ConnectWise 구성원 키를 제공합니다. ConnectWise가 해당 구성원의 보안 역할을 적용하며, 모든 쓰기 작업은 실제 사용자에게 귀속됩니다
전송(Transports) — 로컬 사용용 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(디스패치)입니다. 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는 보드, 상태, 회사 및 연락처를 레코드에 이미 조인한 비정규화된 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[] })로 구성됩니다. 오버레이 항목은 슬러그로 우선하며, 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에 추가하며, 다른 모든 것(EXECUTE, 모든 쓰기, DDL, BACKUP)을 DENY하고, 발견된 모든 자격 증명처럼 보이는 열에 대한 SELECT를 DENY합니다 — 이름은 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도 반드시 꺼야 합니다.
운영 관점에서: 프로덕션 기본 복제본 대신 읽기 가능한 AG 보조 복제본이나 복원된 보고용 복사본을 사용하고, MCP 호스트에 SQL 포트를 방화벽으로 차단하며, 이 로그인에 대해 SQL Audit 또는 Extended Events 세션을 유지하십시오.
구성 참조
변수 | 기본값 | 용도 |
| — | ConnectWise 호스트(클라우드 또는 온프레미스; 전체 URL 허용) |
| — | 로그인 회사 ID |
| — | 통합 클라이언트 ID |
| — | API 멤버 키 — stdio에서 필수; HTTP에서는 미사용 (BYOK) |
| — | 키가 속한 멤버 (my-tickets/my-time) |
|
| 전송 선택 |
|
| 활성화된 툴셋 (키/프리셋); 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 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