npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mcp-connectwise-manage

v0.1.6

Published

Model Context Protocol server for ConnectWise Manage (OpenAPI auto-expose)

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 build

Run (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.js

On 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.js and SPEC_PATH to avoid CWD issues.
  • Start with CW_ACTIVE_PROFILE=admin to expose all tools, then tighten as needed.
  • Set LOG_LEVEL=debug temporarily to troubleshoot startup.
  • Required: Include CW_PROFILES, CW_ALLOWED_OPERATIONS, and CW_WRITE_ALLOWLIST in 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=true or dryRun=true; blackout windows are respected.
  • Large lists are capped by CW_TOTAL_ROWS_LIMIT.

License

MIT © 2025 Suleman Manji