loading…
Search for a command to run...
loading…
Enables AI assistants to fully access and manage SyncroMSP resources including tickets, customers, assets, invoices, and over 30 resource types through 180+ API
Enables AI assistants to fully access and manage SyncroMSP resources including tickets, customers, assets, invoices, and over 30 resource types through 180+ API endpoints.
A fully-featured Model Context Protocol server for the SyncroMSP IT/MSP platform. Gives AI assistants full access to tickets, customers, assets, invoices, and 30+ resource types.
| Method | Best For | Auto-Updates |
|---|---|---|
| Claude Code Plugin | One-command install of MCP + Skill in Claude Code | Yes (marketplace) |
| Claude Code (MCP only) | Developers wiring up the MCP without the bundled skill | Yes (npx) |
| Claude Desktop | Local desktop app users | Yes (npx) |
| Docker + Claude.ai | Teams, remote access, Claude.ai web | Yes (Watchtower) |
| From Source | Development and customization | Manual |
This repo also ships a Claude Skill that gives Claude operating context for the MCP — workflows, API quirks (e.g. line_items ignored on *_create), the two-step labor logging pattern, ticket status transitions, ticket comment subject conventions, and a hyperlink rule that renders every Syncro record as a clickable link. It's company-agnostic; user-specific values are discovered at runtime via API calls and cached locally.
Recommended — Claude Code plugin (auto-updating, bundles skill + MCP, prompts for credentials on install):
/plugin marketplace add advenimus/syncromsp-mcp
/plugin install syncromsp@syncromsp
On enable, Claude Code prompts for your Syncro subdomain and API key. The subdomain is stored in settings.json; the API key goes to your system keychain. Both are passed to the bundled MCP server as SYNCRO_SUBDOMAIN and SYNCRO_API_KEY automatically — no shell exports or manual claude mcp add needed.
New commits to main propagate to installed users on the next marketplace refresh — no manual re-install needed.
Claude Desktop / claude.ai (no public plugin marketplace yet): download syncromsp-skill.zip from Releases and upload via Settings → Capabilities → Skills (paid plan, preview feature). It syncs across that account automatically. For Team/Enterprise plans, an org admin can upload via Organization settings and every member gets auto-updates when the admin re-uploads a revised zip. Full instructions in plugins/syncromsp/skills/syncromsp/README.md.
The release zip is always published at:
https://github.com/advenimus/syncromsp-mcp/releases/latest/download/syncromsp-skill.zip
Your subdomain is the part before .syncromsp.com in your Syncro URL (e.g., mycompany from mycompany.syncromsp.com).
claude mcp add syncromsp \
--env SYNCRO_API_KEY=your-api-key \
--env SYNCRO_SUBDOMAIN=your-subdomain \
-- npx syncromsp-mcp
That's it. Claude Code will download and run the latest version automatically.
Download the latest .mcpb file from Releases and double-click to install. Claude Desktop will prompt you for your API key and subdomain.
Add to your claude_desktop_config.json:
{
"mcpServers": {
"syncromsp": {
"command": "npx",
"args": ["-y", "syncromsp-mcp"],
"env": {
"SYNCRO_API_KEY": "your-api-key",
"SYNCRO_SUBDOMAIN": "your-subdomain"
}
}
}
}
Config file location:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonRestart Claude Desktop after saving. The server updates automatically via npx on each restart.
Deploy as a Docker container for remote access from Claude.ai, shared team usage, or running on a server. Includes built-in OAuth 2.1 authentication so only authorized users can connect.
git clone https://github.com/advenimus/syncromsp-mcp.git
cd syncromsp-mcp
cp .env.example .env
Edit .env with your settings:
# Required: Syncro credentials
SYNCRO_API_KEY=your-api-key
SYNCRO_SUBDOMAIN=your-subdomain
# Required: The public URL where this server will be reachable
# Must be HTTPS for production (put behind Traefik, Caddy, nginx, etc.)
MCP_BASE_URL=https://mcp.yourcompany.com
# Required: Access key that users must enter to authorize connections.
# Minimum 32 characters; the server refuses to start on weak/default values.
# Generate with: openssl rand -hex 32
MCP_AUTH_SECRET=
docker compose up -d
The container runs on port 8080 by default. You need a reverse proxy (Traefik, Caddy, nginx) in front to provide HTTPS.
https://mcp.yourcompany.com/mcpMCP_AUTH_SECRET you configured in Step 1The server implements the MCP OAuth 2.1 + PKCE spec with an access key gate:
Client connects → 401 Unauthorized
→ Client discovers /.well-known/oauth-authorization-server
→ Client dynamically registers (RFC 7591)
→ Client redirects user to /authorize
→ User sees login page, enters MCP_AUTH_SECRET
→ Correct key: auth code issued → token granted → MCP access
→ Wrong key: 403 Access Denied, connection rejected
MCP_AUTH_SECRET is missing, shorter than 32 characters, or matches a known weak default (change-me, password, secret, etc.)redirect_uri so users can verify the destination before authorizing (anti-phishing)For the full threat model, defense layers, and operator responsibilities, see SECURITY.md.
services:
syncro-mcp:
image: ghcr.io/advenimus/syncromsp-mcp:latest
container_name: syncromsp-mcp
restart: unless-stopped
environment:
- SYNCRO_API_KEY=${SYNCRO_API_KEY}
- SYNCRO_SUBDOMAIN=${SYNCRO_SUBDOMAIN}
- MCP_TRANSPORT=http
- MCP_PORT=8080
- MCP_BASE_URL=https://mcp.yourcompany.com
- MCP_AUTH_SECRET=${MCP_AUTH_SECRET}
# Container hardening — recommended for any public-facing deployment
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp:size=10m,mode=1777
labels:
- "traefik.enable=true"
- "traefik.http.routers.mcp.rule=Host(`mcp.yourcompany.com`)"
- "traefik.http.routers.mcp.entrypoints=websecure"
- "traefik.http.routers.mcp.tls.certresolver=letsencrypt"
- "traefik.http.services.mcp.loadbalancer.server.port=8080"
services:
syncro-mcp:
image: ghcr.io/advenimus/syncromsp-mcp:latest
container_name: syncromsp-mcp
restart: unless-stopped
environment:
- SYNCRO_API_KEY=${SYNCRO_API_KEY}
- SYNCRO_SUBDOMAIN=${SYNCRO_SUBDOMAIN}
- MCP_TRANSPORT=http
- MCP_BASE_URL=https://mcp.yourcompany.com
- MCP_AUTH_SECRET=${MCP_AUTH_SECRET}
expose:
- "8080"
# Container hardening — recommended for any public-facing deployment
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp:size=10m,mode=1777
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes:
caddy_data:
Caddyfile:
mcp.yourcompany.com {
reverse_proxy syncro-mcp:8080
}
For testing on private networks only. The server refuses to start with MCP_AUTH=false unless you also set MCP_I_UNDERSTAND_INSECURE=true as an explicit foot-gun guard:
MCP_AUTH=false MCP_I_UNDERSTAND_INSECURE=true docker compose up -d
Warning: Without auth, anyone who can reach the URL gets full access to your Syncro account. Never disable auth on a publicly-reachable deployment, even briefly.
| Variable | Required | Default | Description |
|---|---|---|---|
SYNCRO_API_KEY |
Yes | — | Your Syncro API token |
SYNCRO_SUBDOMAIN |
Yes | — | Your Syncro subdomain |
MCP_TRANSPORT |
No | stdio |
stdio (local) or http (Docker/remote) |
MCP_PORT |
No | 8080 |
HTTP listen port |
MCP_BASE_URL |
For Docker | — | Public HTTPS URL (e.g., https://mcp.yourcompany.com) |
MCP_AUTH |
No | true |
true or false to disable OAuth (see foot-gun guard below) |
MCP_AUTH_SECRET |
For Docker | — | Access key users enter to authorize. Minimum 32 chars; weak/default values rejected at startup. |
MCP_I_UNDERSTAND_INSECURE |
If MCP_AUTH=false |
— | Must be true to start the server with auth disabled. Foot-gun guard. |
MCP_TOOL_MODE |
No | flat |
flat (all tools) or navigation (lazy domains) |
| Domain | Description | Key Operations |
|---|---|---|
| tickets | Service tickets | CRUD, comments (email/public/private), cross-ticket comment feed, line items, timers, attachments, blueprints |
| customers | Customer records | CRUD, phone numbers, autocomplete |
| assets | Customer assets | CRUD, patches, installed applications, policy folder assignment, properties (OS, RAM, HDD, etc.) |
| contacts | Customer contacts | CRUD |
| invoices | Invoices | CRUD, line items (manual + product catalog), print, email |
| estimates | Estimates/quotes | CRUD, line items, print, email, convert to invoice |
| appointments | Calendar appointments | CRUD, appointment types, ticket linking |
| products | Inventory/products | CRUD, serials, SKUs, categories, images |
| payments | Payment records | Create, read, multi-invoice distribution |
| leads | Leads/opportunities | Create, read, update |
| contracts | Service contracts | CRUD |
| rmm | RMM alerts | Create, read, mute, resolve |
| scheduling | Recurring invoices | CRUD, schedule line items |
| time | Timers and time logs | List, update |
| admin | Search, users, vendors, wiki, portal, settings, purchase orders, and more | Various |
| policies | Policy folders (Syncro accounts only) | List, get, create, update, delete folders; assign assets via assets_update |
The server checks for updates on startup and logs a warning if a newer version is available.
| Method | How to Update |
|---|---|
| npx / Claude Desktop | Automatic — npx pulls latest on each run |
| Docker | docker compose pull && docker compose up -d |
| Docker (auto) | Add Watchtower for automatic daily updates |
| MCPB | Download latest .mcpb from Releases |
| From Source | git pull && npm install && npm run build |
Recommended: run Watchtower in label-enable mode so it only auto-updates the containers that opt in. This is much safer than letting it auto-update every container on the host.
Watchtower stack (/root/docker/watchtower/docker-compose.yml):
services:
watchtower:
image: containrrr/watchtower:1.7.1
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_LABEL_ENABLE=true # only watch opted-in containers
- WATCHTOWER_POLL_INTERVAL=300 # check every 5 minutes
- WATCHTOWER_CLEANUP=true
# On hosts running modern Docker (29.x with MinAPI 1.40), Watchtower's
# bundled SDK can default to an older API version. Pin to 1.40 to avoid
# `client version 1.25 is too old` errors at runtime.
- DOCKER_API_VERSION=1.40
Then opt the syncromsp-mcp service in via a label in its compose:
labels:
- "com.centurylinklabs.watchtower.enable=true"
Bring both up: docker compose up -d in each directory. New releases on :latest will be pulled and the container recreated within 5 minutes of publish.
do_not_email: false), public note (do_not_email: true, hidden: false), and private note (hidden: true)disabled: true via update insteadgit clone https://github.com/advenimus/syncromsp-mcp.git
cd syncromsp-mcp
npm install
npm run build
export SYNCRO_API_KEY=your-api-key
export SYNCRO_SUBDOMAIN=your-subdomain
npm start
npm run dev # Run with tsx (hot reload)
npm run build # Compile TypeScript
npm test # Run tests
npm run lint # Lint source
MIT
Run in your terminal:
claude mcp add syncromsp-mcp-server -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.