mcp-connectwise-manage
v0.1.6
Published
Model Context Protocol server for ConnectWise Manage (OpenAPI auto-expose)
Maintainers
Readme
ConnectWise Manage MCP Server (Stdio Only)
A production‑ready Model Context Protocol (MCP) stdio server for ConnectWise Manage. Runs directly via Node using the compiled dist/stdio.js entrypoint and exposes a curated, role‑aware subset of the ConnectWise Manage OpenAPI 3.0 operations.
Highlights
- Curated allowlist across Service Desk, Time, Agreements, Companies, Projects, Sales, Setup tables
- Read‑only by default; write allowlist limited to Time Entry POST/PATCH with confirm/dry‑run gates
- Safe defaults (board/department, page‑size caps, bounded time windows)
- Profiles and semantic tool aliases (svc‑, time‑, agr‑, co‑, prj‑, sal‑, setup‑*)
- JSON Schema input validation (path/query/headers/body)
- Stdio transport only (recommended for Cursor/Claude Desktop/ChatGPT MCP)
Requirements
- Node.js >= 20
- ConnectWise Manage API credentials (company, clientId, public/private keys) and the ConnectWise Manage OpenAPI 3.0 JSON file (curated or full) accessible via developer.connect
Configure Environment
Set these variables in your shell (do not quote values):
# ConnectWise API base components
export CW_server=na.connectwise.com
export CW_company=yoCompanyName
export CW_clientId=<guid>
export CW_pub=<public-key>
export CW_priv=<private-key>
# Optional: override API path (default v4_6_release)
export CW_API_PATH=v4_6_release
# HTTP client tuning
export CW_TIMEOUT_MS=30000
export CW_MAX_CONCURRENCY=5
export CW_HEADERS_ALLOWLIST=Accept
# Curated exposure & safeguards
export CW_ENABLED_MODULES=service,time,agreements,companies,projects,sales,setup
export CW_ALLOWED_OPERATIONS='[{"method":"get","pathPattern":"^/service/tickets$"},{"method":"get","pathPattern":"^/service/boards$"},{"method":"get","pathPattern":"^/service/statuses$"},{"method":"get","pathPattern":"^/service/priorities$"},{"method":"get","pathPattern":"^/service/impacts$"},{"method":"get","pathPattern":"^/system/members$"},{"method":"get","pathPattern":"^/time/entries$"},{"method":"get","pathPattern":"^/time/periods$"}]'
export CW_WRITE_ALLOWLIST='[{"method":"post","pathPattern":"^/time/entries$"},{"method":"patch","pathPattern":"^/time/entries/[^/]+$"}]'
export CW_DEFAULT_SERVICE_BOARD="Managed Services"
export CW_DEFAULT_SERVICE_DEPARTMENT="Managed Services"
export CW_DEFAULT_COMPANY_SCOPE="All Companies"
export CW_DEFAULT_PAGE_SIZE=50
export CW_MAX_PAGE_SIZE=100
export CW_DEFAULT_TIME_WINDOW_DAYS=30
export CW_REQUIRE_CONFIRM_WRITES=true
export CW_ENABLE_DRY_RUN=true
export CW_RATE_LIMIT_BURST_RPS=5
export CW_RATE_LIMIT_SUSTAINED_RPM=60
export CW_BLACKOUT_WINDOWS='[]'
export CW_TOTAL_ROWS_LIMIT=500
# Profiles (prefix allowlist) - REQUIRED for tool filtering
export CW_PROFILES='{"technician":["svc-","time-","prj-","co-","setup-"],"billing":["time-","agr-","co-","sal-","setup-"],"procurement":["co-","sal-","setup-"],"admin":[""]}'
export CW_ACTIVE_PROFILE=technician
# Logging
export LOG_LEVEL=info
# Absolute path to your OpenAPI JSON spec
export SPEC_PATH="/absolute/path/to/curated-openapi.json"Build (from source)
cd mcp-connectwise-manage
npm ci
npm run buildRun (Direct Stdio)
Run the compiled stdio server directly with Node. It uses the environment above and SPEC_PATH to locate the spec.
node /absolute/path/to/mcp-connectwise-manage/dist/stdio.jsOn success you should see a log similar to:
{"level":30,"app":"cw-manage-mcp","total":<N>,"registered":<N>,"profile":"<profile>","msg":"MCP stdio server started"}Cursor MCP Configuration (.cursor/mcp.json)
Point Cursor to the stdio server using a direct Node command and absolute paths:
{
"mcpServers": {
"cw-manage": {
"command": "node",
"args": [
"/absolute/path/to/mcp-connectwise-manage/dist/stdio.js"
],
"env": {
"CW_server": "connect.viyu.net",
"CW_company": "viyunet",
"CW_clientId": "00000000-0000-0000-0000-000000000000",
"CW_pub": "<public-key>",
"CW_priv": "<private-key>",
"SPEC_PATH": "/absolute/path/to/curated-openapi.json",
"LOG_LEVEL": "info",
"CW_ACTIVE_PROFILE": "admin",
"CW_PROFILES": "{\"technician\":[\"svc-\",\"time-\",\"prj-\",\"co-\",\"setup-\"],\"billing\":[\"time-\",\"agr-\",\"co-\",\"sal-\",\"setup-\"],\"procurement\":[\"co-\",\"sal-\",\"setup-\"],\"admin\":[\"\"]}",
"CW_ALLOWED_OPERATIONS": "[{\"method\":\"get\",\"pathPattern\":\"^/service/tickets$\"},{\"method\":\"get\",\"pathPattern\":\"^/service/boards$\"},{\"method\":\"get\",\"pathPattern\":\"^/service/statuses$\"},{\"method\":\"get\",\"pathPattern\":\"^/service/priorities$\"},{\"method\":\"get\",\"pathPattern\":\"^/service/impacts$\"},{\"method\":\"get\",\"pathPattern\":\"^/system/members$\"},{\"method\":\"get\",\"pathPattern\":\"^/time/entries$\"},{\"method\":\"get\",\"pathPattern\":\"^/time/periods$\"}]",
"CW_WRITE_ALLOWLIST": "[{\"method\":\"post\",\"pathPattern\":\"^/time/entries$\"},{\"method\":\"patch\",\"pathPattern\":\"^/time/entries/[^/]+$\"}]"
}
}
}
}Notes
- Always use absolute paths for both
stdio.jsandSPEC_PATHto avoid CWD issues. - Start with
CW_ACTIVE_PROFILE=adminto expose all tools, then tighten as needed. - Set
LOG_LEVEL=debugtemporarily to troubleshoot startup. - Required: Include
CW_PROFILES,CW_ALLOWED_OPERATIONS, andCW_WRITE_ALLOWLISTin your environment for proper tool filtering and security.
Safety & Write Operations
- Read endpoints are exposed by default; writes are restricted to time entries.
- Writes require
confirm=trueordryRun=true; blackout windows are respected. - Large lists are capped by
CW_TOTAL_ROWS_LIMIT.
License
MIT © 2025 Suleman Manji
